Package liquibase.diff.compare

Source Code of liquibase.diff.compare.DatabaseObjectComparatorFactory

package liquibase.diff.compare;

import liquibase.database.Database;
import liquibase.diff.ObjectDifferences;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.servicelocator.ServiceLocator;
import liquibase.structure.AbstractDatabaseObject;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Catalog;
import liquibase.structure.core.Schema;
import liquibase.util.StringUtils;

import java.util.*;

public class DatabaseObjectComparatorFactory {

    private static DatabaseObjectComparatorFactory instance;

    private List<DatabaseObjectComparator> comparators = new ArrayList<DatabaseObjectComparator>();

    private Map<String, List<DatabaseObjectComparator>> validComparatorsByClassAndDatabase = new HashMap<String, List<DatabaseObjectComparator>>();
    private Map<String, DatabaseObjectComparatorChain> comparatorChainsByClassAndDatabase = new HashMap<String, DatabaseObjectComparatorChain>();

    private DatabaseObjectComparatorFactory() {
        Class[] classes;
        try {
            classes = ServiceLocator.getInstance().findClasses(DatabaseObjectComparator.class);

            for (Class clazz : classes) {
                register((DatabaseObjectComparator) clazz.getConstructor().newInstance());
            }

        } catch (Exception e) {
            throw new UnexpectedLiquibaseException(e);
        }

    }

    /**
     * Return singleton DatabaseObjectComparatorFactory
     */
    public static DatabaseObjectComparatorFactory getInstance() {
        if (instance == null) {
            instance = new DatabaseObjectComparatorFactory();
        }
        return instance;
    }

    public static void reset() {
        instance = new DatabaseObjectComparatorFactory();
    }


    public void register(DatabaseObjectComparator generator) {
        comparators.add(generator);
    }

    public void unregister(DatabaseObjectComparator generator) {
        comparators.remove(generator);
    }

    public void unregister(Class generatorClass) {
        DatabaseObjectComparator toRemove = null;
        for (DatabaseObjectComparator existingGenerator : comparators) {
            if (existingGenerator.getClass().equals(generatorClass)) {
                toRemove = existingGenerator;
            }
        }

        unregister(toRemove);
    }

    protected List<DatabaseObjectComparator> getComparators(Class<? extends DatabaseObject> comparatorClass, Database database) {
        String key = comparatorClass.getName()+":"+database.getShortName();
        if (validComparatorsByClassAndDatabase.containsKey(key)) {
            return validComparatorsByClassAndDatabase.get(key);
        }

        List<DatabaseObjectComparator> validComparators = new ArrayList<DatabaseObjectComparator>();

        for (DatabaseObjectComparator comparator : comparators) {
            if (comparator.getPriority(comparatorClass, database) > 0) {
                validComparators.add(comparator);
            }
        }

        Collections.sort(validComparators, new DatabaseObjectComparatorComparator(comparatorClass, database));

        validComparatorsByClassAndDatabase.put(key, validComparators);

        return validComparators;
    }


    public static void resetAll() {
        instance = null;
    }

    public boolean isSameObject(DatabaseObject object1, DatabaseObject object2, Database accordingTo) {
        if (object1 == null && object2 == null) {
            return true;
        }

        if (object1 instanceof Schema || object2 instanceof Schema) {
            if (object1 == null) {
                object1 = new Schema();
            }
            if (object2 == null) {
                object2 = new Schema();
            }
        } else if (object1 instanceof Catalog || object2 instanceof Catalog) {
                if (object1 == null) {
                    object1 = new Catalog();
                }
                if (object2 == null) {
                    object2 = new Catalog();
                }
        }
        if (object1 == null || object2 == null) {
            return false;
        }

        String snapshotId1 = object1.getSnapshotId();
        String snapshotId2 = object2.getSnapshotId();
        if (snapshotId1 != null && snapshotId2 != null) {
            if (snapshotId1.equals(snapshotId2)) {
                return true;
            }
        }

        boolean aHashMatches = false;

        List<String> hash1 = Arrays.asList(hash(object1, accordingTo));
        List<String> hash2 = Arrays.asList(hash(object2, accordingTo));
        for (String hash : hash1) {
            if (hash2.contains(hash)) {
                aHashMatches = true;
                break;
            }
        }

        if (!aHashMatches) {
            return false;
        }


        return createComparatorChain(object1.getClass(), accordingTo).isSameObject(object1, object2, accordingTo);
    }

    public String[] hash(DatabaseObject databaseObject, Database accordingTo) {
        String[] hash = null;
        if (databaseObject != null) {
            hash = createComparatorChain(databaseObject.getClass(), accordingTo).hash(databaseObject, accordingTo);
        }

        if (hash == null) {
            hash = new String[] {
                    "null"
            };
        }

        for (int i=0; i<hash.length; i++) {
            if (StringUtils.trimToNull(hash[i]) == null) {
                hash[i] = "null";
            }
        }
        return hash;
    }

    public ObjectDifferences findDifferences(DatabaseObject object1, DatabaseObject object2, Database accordingTo, CompareControl compareControl) {
        return createComparatorChain(object1.getClass(), accordingTo).findDifferences(object1, object2, accordingTo, compareControl, new HashSet<String>());

    }

    private DatabaseObjectComparatorChain createComparatorChain(Class<? extends DatabaseObject> databaseObjectType, Database database) {
        String key = databaseObjectType.getName()+":"+database.getShortName();

        if (comparatorChainsByClassAndDatabase.containsKey(key)) {
            return comparatorChainsByClassAndDatabase.get(key).copy();
        }

        List<DatabaseObjectComparator> comparators = DatabaseObjectComparatorFactory.getInstance().getComparators(databaseObjectType, database);
        if (comparators == null || comparators.size() == 0) {
            return null;
        }

        DatabaseObjectComparatorChain chain = new DatabaseObjectComparatorChain(comparators);
        comparatorChainsByClassAndDatabase.put(key, chain);
        //noinspection unchecked
        return chain;
    }

}
TOP

Related Classes of liquibase.diff.compare.DatabaseObjectComparatorFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.