/* * Generates rollback statements from the inverse changes returned by createInverses(). * Throws RollbackImpossibleException if the changes created by createInverses() is not supported for the passed database. * */ private SqlStatement[] generateRollbackStatementsFromInverse(Database database) throws RollbackImpossibleException { Change[] inverses = createInverses(); if (inverses == null) { throw new RollbackImpossibleException("No inverse to " + getClass().getName() + " created"); } List<SqlStatement> statements = new ArrayList<SqlStatement>(); try { for (Change inverse : inverses) { if (!inverse.supports(database)) { throw new RollbackImpossibleException( ChangeFactory.getInstance().getChangeMetaData(inverse).getName() + " is not supported on " + database.getShortName()); } statements.addAll(Arrays.asList(inverse.generateStatements(database))); } } catch (LiquibaseException e) { throw new RollbackImpossibleException(e); } return statements.toArray(new SqlStatement[statements.size()]); }
/** * Implementation delegates logic to the {@link * liquibase.sqlgenerator.SqlGenerator#warn(liquibase.statement.SqlStatement, * liquibase.database.Database, liquibase.sqlgenerator.SqlGeneratorChain)} method on the {@link * SqlStatement} objects returned by {@link #generateStatements }. If a generated statement is not * supported for the given database, no warning will be added since that is a validation error. If * no or null SqlStatements are returned by generateStatements then this method returns no * warnings. */ @Override public Warnings warn(Database database) { Warnings warnings = new Warnings(); if (generateStatementsVolatile(database)) { return warnings; } SqlStatement[] statements = generateStatements(database); if (statements == null) { return warnings; } for (SqlStatement statement : statements) { if (SqlGeneratorFactory.getInstance().supports(statement, database)) { warnings.addAll(SqlGeneratorFactory.getInstance().warn(statement, database)); } else if (statement.skipOnUnsupported()) { warnings.addWarning( statement.getClass().getName() + " is not supported on " + database.getShortName() + ", but " + ChangeFactory.getInstance().getChangeMetaData(this).getName() + " will still execute"); } } return warnings; }
/** * Implementation checks the ChangeParameterMetaData for declared required fields and also * delegates logic to the {@link * liquibase.sqlgenerator.SqlGenerator#validate(liquibase.statement.SqlStatement, * liquibase.database.Database, liquibase.sqlgenerator.SqlGeneratorChain)} method on the {@link * SqlStatement} objects returned by {@link #generateStatements }. If no or null SqlStatements are * returned by generateStatements then this method returns no errors. If there are no parameters * than this method returns no errors */ @Override public ValidationErrors validate(Database database) { ValidationErrors changeValidationErrors = new ValidationErrors(); for (ChangeParameterMetaData param : ChangeFactory.getInstance().getChangeMetaData(this).getParameters().values()) { if (param.isRequiredFor(database) && param.getCurrentValue(this) == null) { changeValidationErrors.addError( param.getParameterName() + " is required for " + ChangeFactory.getInstance().getChangeMetaData(this).getName() + " on " + database.getShortName()); } } if (changeValidationErrors.hasErrors()) { return changeValidationErrors; } String unsupportedWarning = ChangeFactory.getInstance().getChangeMetaData(this).getName() + " is not supported on " + database.getShortName(); if (!this.supports(database)) { changeValidationErrors.addError(unsupportedWarning); } else if (!generateStatementsVolatile(database)) { boolean sawUnsupportedError = false; SqlStatement[] statements; statements = generateStatements(database); if (statements != null) { for (SqlStatement statement : statements) { boolean supported = SqlGeneratorFactory.getInstance().supports(statement, database); if (!supported && !sawUnsupportedError) { if (!statement.skipOnUnsupported()) { changeValidationErrors.addError(unsupportedWarning); sawUnsupportedError = true; } } else { changeValidationErrors.addAll( SqlGeneratorFactory.getInstance().validate(statement, database)); } } } } return changeValidationErrors; }
@Override public SerializationType getSerializableFieldType(String field) { return ChangeFactory.getInstance() .getChangeMetaData(this) .getParameters() .get(field) .getSerializationType(); }
@Override public Object getSerializableFieldValue(String field) { return ChangeFactory.getInstance() .getChangeMetaData(this) .getParameters() .get(field) .getCurrentValue(this); }
@Override public ParsedNode serialize() throws ParsedNodeException { ParsedNode node = new ParsedNode(null, getSerializedObjectName()); ChangeMetaData metaData = ChangeFactory.getInstance().getChangeMetaData(this); for (ChangeParameterMetaData param : metaData.getSetParameters(this).values()) { Object currentValue = param.getCurrentValue(this); currentValue = serializeValue(currentValue); if (currentValue != null) { node.addChild(null, param.getParameterName(), currentValue); } } return node; }
@Override public void load(ParsedNode parsedNode, ResourceAccessor resourceAccessor) throws ParsedNodeException { ChangeMetaData metaData = ChangeFactory.getInstance().getChangeMetaData(this); this.setResourceAccessor(resourceAccessor); try { for (ChangeParameterMetaData param : metaData.getParameters().values()) { if (Collection.class.isAssignableFrom(param.getDataTypeClass())) { Class collectionType = (Class) param.getDataTypeClassParameters()[0]; if (param.getDataTypeClassParameters().length == 1) { if (ColumnConfig.class.isAssignableFrom(collectionType)) { List<ParsedNode> columnNodes = new ArrayList<ParsedNode>(parsedNode.getChildren(null, param.getParameterName())); columnNodes.addAll(parsedNode.getChildren(null, "column")); Object nodeValue = parsedNode.getValue(); if (nodeValue instanceof ParsedNode) { columnNodes.add((ParsedNode) nodeValue); } else if (nodeValue instanceof Collection) { for (Object nodeValueChild : ((Collection) nodeValue)) { if (nodeValueChild instanceof ParsedNode) { columnNodes.add((ParsedNode) nodeValueChild); } } } for (ParsedNode child : columnNodes) { if (child.getName().equals("column") || child.getName().equals("columns")) { List<ParsedNode> columnChildren = child.getChildren(null, "column"); if (columnChildren != null && columnChildren.size() > 0) { for (ParsedNode columnChild : columnChildren) { ColumnConfig columnConfig = (ColumnConfig) collectionType.newInstance(); columnConfig.load(columnChild, resourceAccessor); ((ChangeWithColumns) this).addColumn(columnConfig); } } else { ColumnConfig columnConfig = (ColumnConfig) collectionType.newInstance(); columnConfig.load(child, resourceAccessor); ((ChangeWithColumns) this).addColumn(columnConfig); } } } } else if (LiquibaseSerializable.class.isAssignableFrom(collectionType)) { List<ParsedNode> childNodes = new ArrayList<ParsedNode>(parsedNode.getChildren(null, param.getParameterName())); for (ParsedNode childNode : childNodes) { LiquibaseSerializable childObject = (LiquibaseSerializable) collectionType.newInstance(); childObject.load(childNode, resourceAccessor); ((Collection) param.getCurrentValue(this)).add(childObject); } } } } else if (LiquibaseSerializable.class.isAssignableFrom(param.getDataTypeClass())) { try { ParsedNode child = parsedNode.getChild(null, param.getParameterName()); if (child != null) { LiquibaseSerializable serializableChild = (LiquibaseSerializable) param.getDataTypeClass().newInstance(); serializableChild.load(child, resourceAccessor); param.setValue(this, serializableChild); } } catch (InstantiationException e) { throw new UnexpectedLiquibaseException(e); } catch (IllegalAccessException e) { throw new UnexpectedLiquibaseException(e); } } else { Object childValue = parsedNode.getChildValue(null, param.getParameterName(), param.getDataTypeClass()); if (childValue == null && param.getSerializationType() == SerializationType.DIRECT_VALUE) { childValue = parsedNode.getValue(); } param.setValue(this, childValue); } } } catch (InstantiationException e) { throw new UnexpectedLiquibaseException(e); } catch (IllegalAccessException e) { throw new UnexpectedLiquibaseException(e); } customLoadLogic(parsedNode, resourceAccessor); try { this.finishInitialization(); } catch (SetupException e) { throw new ParsedNodeException(e); } }
@Override public String toString() { return ChangeFactory.getInstance().getChangeMetaData(this).getName(); }
@Override public String getSerializedObjectName() { return ChangeFactory.getInstance().getChangeMetaData(this).getName(); }
/** Returns the fields on this change that are serializable. */ @Override public Set<String> getSerializableFields() { return ChangeFactory.getInstance().getChangeMetaData(this).getParameters().keySet(); }