Coverage Report - liquibase.change.AbstractChange
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractChange
56%
28/50
50%
13/26
1.833
 
 1  
 package liquibase.change;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.Arrays;
 5  
 import java.util.HashSet;
 6  
 import java.util.List;
 7  
 import java.util.Set;
 8  
 
 9  
 import liquibase.changelog.ChangeSet;
 10  
 import liquibase.database.Database;
 11  
 import liquibase.database.structure.DatabaseObject;
 12  
 import liquibase.exception.RollbackImpossibleException;
 13  
 import liquibase.exception.SetupException;
 14  
 import liquibase.exception.UnsupportedChangeException;
 15  
 import liquibase.exception.ValidationErrors;
 16  
 import liquibase.exception.Warnings;
 17  
 import liquibase.logging.LogFactory;
 18  
 import liquibase.resource.ResourceAccessor;
 19  
 import liquibase.serializer.core.string.StringChangeLogSerializer;
 20  
 import liquibase.sqlgenerator.SqlGeneratorFactory;
 21  
 import liquibase.statement.SqlStatement;
 22  
 
 23  
 /**
 24  
  * Standard superclass for Changes to implement. This is a <i>skeletal implementation</i>, as defined in Effective
 25  
  * Java#16.
 26  
  * 
 27  
  * @see Change
 28  
  */
 29  
 public abstract class AbstractChange implements Change {
 30  
 
 31  
     @ChangeProperty(includeInSerialization = false)
 32  
     private ChangeMetaData changeMetaData;
 33  
 
 34  
     @ChangeProperty(includeInSerialization = false)
 35  
     private ResourceAccessor resourceAccessor;
 36  
 
 37  
     @ChangeProperty(includeInSerialization = false)
 38  
     private ChangeSet changeSet;
 39  
 
 40  
     /**
 41  
      * Constructor with tag name and name
 42  
      * 
 43  
      * @param changeName
 44  
      *            the tag name for this change
 45  
      * @param changeDescription
 46  
      *            the name for this change
 47  
      */
 48  1029
     protected AbstractChange(String changeName, String changeDescription, int priority) {
 49  1029
         this.changeMetaData = new ChangeMetaData(changeName, changeDescription, priority);
 50  1029
     }
 51  
 
 52  
     @Override
 53  
     public ChangeMetaData getChangeMetaData() {
 54  1214
         return changeMetaData;
 55  
     }
 56  
 
 57  
     protected void setPriority(int newPriority) {
 58  0
         this.changeMetaData.setPriority(newPriority);
 59  0
     }
 60  
 
 61  
     @Override
 62  
     public ChangeSet getChangeSet() {
 63  0
         return changeSet;
 64  
     }
 65  
 
 66  
     @Override
 67  
     public void setChangeSet(ChangeSet changeSet) {
 68  62
         this.changeSet = changeSet;
 69  62
     }
 70  
 
 71  
     @Override
 72  
     public boolean requiresUpdatedDatabaseMetadata(Database database) {
 73  0
         for (SqlStatement statement : generateStatements(database)) {
 74  0
             if (SqlGeneratorFactory.getInstance().requiresCurrentDatabaseMetadata(statement, database)) {
 75  0
                 return true;
 76  
             }
 77  
         }
 78  0
         return false;
 79  
     }
 80  
 
 81  
     @Override
 82  
     public boolean supports(Database database) {
 83  1680
         for (SqlStatement statement : generateStatements(database)) {
 84  918
             if (!SqlGeneratorFactory.getInstance().supports(statement, database)) {
 85  78
                 return false;
 86  
             }
 87  
         }
 88  762
         return true;
 89  
     }
 90  
 
 91  
     @Override
 92  
     public Warnings warn(Database database) {
 93  5
         Warnings warnings = new Warnings();
 94  10
         for (SqlStatement statement : generateStatements(database)) {
 95  5
             if (SqlGeneratorFactory.getInstance().supports(statement, database)) {
 96  4
                 warnings.addAll(SqlGeneratorFactory.getInstance().warn(statement, database));
 97  
             }
 98  
         }
 99  
 
 100  5
         return warnings;
 101  
     }
 102  
 
 103  
     @Override
 104  
     public ValidationErrors validate(Database database) {
 105  386
         ValidationErrors changeValidationErrors = new ValidationErrors();
 106  810
         for (SqlStatement statement : generateStatements(database)) {
 107  424
             boolean supported = SqlGeneratorFactory.getInstance().supports(statement, database);
 108  424
             if (!supported) {
 109  1
                 if (statement.skipOnUnsupported()) {
 110  1
                     LogFactory.getLogger().info(
 111  
                             getChangeMetaData().getName() + " is not supported on " + database.getTypeName()
 112  
                                     + " but will continue");
 113  
                 } else {
 114  0
                     changeValidationErrors.addError(getChangeMetaData().getName() + " is not supported on "
 115  
                             + database.getTypeName());
 116  
                 }
 117  
             } else {
 118  423
                 changeValidationErrors.addAll(SqlGeneratorFactory.getInstance().validate(statement, database));
 119  
             }
 120  
         }
 121  
 
 122  386
         return changeValidationErrors;
 123  
     }
 124  
 
 125  
     /*
 126  
      * Skipped by this skeletal implementation
 127  
      * 
 128  
      * @see liquibase.change.Change#generateStatements(liquibase.database.Database)
 129  
      */
 130  
 
 131  
     /**
 132  
      * @see liquibase.change.Change#generateRollbackStatements(liquibase.database.Database)
 133  
      */
 134  
     @Override
 135  
     public SqlStatement[] generateRollbackStatements(Database database) throws UnsupportedChangeException,
 136  
             RollbackImpossibleException {
 137  0
         return generateRollbackStatementsFromInverse(database);
 138  
     }
 139  
 
 140  
     /**
 141  
      * @see Change#supportsRollback(liquibase.database.Database)
 142  
      * @param database
 143  
      */
 144  
     @Override
 145  
     public boolean supportsRollback(Database database) {
 146  0
         return createInverses() != null;
 147  
     }
 148  
 
 149  
     /**
 150  
      * @see liquibase.change.Change#generateCheckSum()
 151  
      */
 152  
     @Override
 153  
     public CheckSum generateCheckSum() {
 154  298
         return CheckSum.compute(new StringChangeLogSerializer().serialize(this));
 155  
     }
 156  
 
 157  
     // ~ ------------------------------------------------------------------------------- private methods
 158  
     /*
 159  
      * Generates rollback statements from the inverse changes returned by createInverses()
 160  
      * 
 161  
      * @param database the target {@link Database} associated to this change's rollback statements
 162  
      * 
 163  
      * @return an array of {@link String}s containing the rollback statements from the inverse changes
 164  
      * 
 165  
      * @throws UnsupportedChangeException if this change is not supported by the {@link Database} passed as argument
 166  
      * 
 167  
      * @throws RollbackImpossibleException if rollback is not supported for this change
 168  
      */
 169  
     private SqlStatement[] generateRollbackStatementsFromInverse(Database database) throws UnsupportedChangeException,
 170  
             RollbackImpossibleException {
 171  0
         Change[] inverses = createInverses();
 172  0
         if (inverses == null) {
 173  0
             throw new RollbackImpossibleException("No inverse to " + getClass().getName() + " created");
 174  
         }
 175  
 
 176  0
         List<SqlStatement> statements = new ArrayList<SqlStatement>();
 177  
 
 178  0
         for (Change inverse : inverses) {
 179  0
             statements.addAll(Arrays.asList(inverse.generateStatements(database)));
 180  
         }
 181  
 
 182  0
         return statements.toArray(new SqlStatement[statements.size()]);
 183  
     }
 184  
 
 185  
     /*
 186  
      * Create inverse changes that can roll back this change. This method is intended to be overriden by the subclasses
 187  
      * that can create inverses.
 188  
      * 
 189  
      * @return an array of {@link Change}s containing the inverse changes that can roll back this change
 190  
      */
 191  
     protected Change[] createInverses() {
 192  0
         return null;
 193  
     }
 194  
 
 195  
     /**
 196  
      * Default implementation that stores the file opener provided when the Change was created.
 197  
      */
 198  
     @Override
 199  
     public void setResourceAccessor(ResourceAccessor resourceAccessor) {
 200  51
         this.resourceAccessor = resourceAccessor;
 201  51
     }
 202  
 
 203  
     /**
 204  
      * Returns the FileOpen as provided by the creating ChangeLog.
 205  
      * 
 206  
      * @return The file opener
 207  
      */
 208  
     public ResourceAccessor getResourceAccessor() {
 209  30
         return resourceAccessor;
 210  
     }
 211  
 
 212  
     /**
 213  
      * Most Changes don't need to do any setup. This implements a no-op
 214  
      */
 215  
     @Override
 216  
     public void init() throws SetupException {
 217  
 
 218  27
     }
 219  
 
 220  
     @Override
 221  
     public Set<DatabaseObject> getAffectedDatabaseObjects(Database database) {
 222  0
         Set<DatabaseObject> affectedObjects = new HashSet<DatabaseObject>();
 223  0
         for (SqlStatement statement : generateStatements(database)) {
 224  0
             affectedObjects.addAll(SqlGeneratorFactory.getInstance().getAffectedDatabaseObjects(statement, database));
 225  
         }
 226  
 
 227  0
         return affectedObjects;
 228  
     }
 229  
 
 230  
 }