// ============================================================================ // // Copyright (C) 2006-2016 Talend Inc. - www.talend.com // // This source code is available under agreement available at // %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt // // You should have received a copy of the agreement // along with this program; if not, write to Talend SA // 9 rue Pages 92150 Suresnes, France // // ============================================================================ package org.talend.cwm.compare.factory.comparisonlevel; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.EMFCompare.Builder; import org.eclipse.emf.compare.diff.DefaultDiffEngine; import org.eclipse.emf.compare.diff.DiffBuilder; import org.eclipse.emf.compare.diff.FeatureFilter; import org.eclipse.emf.compare.diff.IDiffEngine; import org.eclipse.emf.compare.diff.IDiffProcessor; import org.eclipse.emf.compare.match.DefaultComparisonFactory; import org.eclipse.emf.compare.match.DefaultEqualityHelperFactory; import org.eclipse.emf.compare.match.IComparisonFactory; import org.eclipse.emf.compare.match.IMatchEngine; import org.eclipse.emf.compare.match.eobject.IEObjectMatcher; import org.eclipse.emf.compare.match.impl.MatchEngineFactoryRegistryImpl; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.merge.IMerger.Registry; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; import org.eclipse.emf.compare.utils.UseIdentifiers; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.talend.commons.utils.WorkspaceUtils; import org.talend.core.model.metadata.builder.connection.Connection; import org.talend.core.model.metadata.builder.database.DqRepositoryViewService; import org.talend.cwm.compare.DQStructureComparer; import org.talend.cwm.compare.ModelElementMatchEngine; import org.talend.cwm.compare.exception.ReloadCompareException; import org.talend.cwm.compare.factory.DQMatchEngineFactory; import org.talend.cwm.compare.factory.IComparisonLevel; import org.talend.cwm.compare.factory.IUIHandler; import org.talend.cwm.compare.factory.update.AddTdRelationalSwitch; import org.talend.cwm.compare.factory.update.RemoveTdRelationalSwitch; import org.talend.cwm.compare.factory.update.UpdateTdRelationalSwitch; import org.talend.cwm.compare.merge.DQReferenceMerger; import org.talend.cwm.helper.SwitchHelpers; import org.talend.cwm.helper.TaggedValueHelper; import org.talend.cwm.relational.TdColumn; import org.talend.dq.helper.PropertyHelper; import org.talend.dq.nodes.foldernode.AbstractDatabaseFolderNode; import org.talend.dq.writer.EMFSharedResources; import org.talend.dq.writer.impl.ElementWriterFactory; import org.talend.resource.ResourceManager; import org.talend.utils.sugars.TypedReturnCode; import orgomg.cwm.objectmodel.core.ModelElement; import orgomg.cwm.objectmodel.core.Package; import orgomg.cwm.objectmodel.core.util.CoreSwitch; import orgomg.cwm.resource.relational.ColumnSet; /** * DOC rli class global comment. Detailled comment */ public abstract class AbstractComparisonLevel implements IComparisonLevel { protected static final boolean CASE_INSENSTIVE = true; // MOD klliu bug 14689 2010-08-04 protected CoreSwitch<Package> packageSwitch; protected UpdateTdRelationalSwitch updateRelationalStructSwitch = new UpdateTdRelationalSwitch(); protected RemoveTdRelationalSwitch removeRelationalSwitch = new RemoveTdRelationalSwitch(); protected AddTdRelationalSwitch addRelationalSwitch = new AddTdRelationalSwitch(); private boolean removeElementConfirm = false; protected Object selectedObj; private AbstractDatabaseFolderNode dbFolderNode = null; protected Connection oldDataProvider; protected Connection tempReloadProvider; protected Map<String, Object> options; protected Connection copyedDataProvider; protected IUIHandler guiHandler; protected EMFSharedResources util = EMFSharedResources.getInstance(); public AbstractComparisonLevel(Object selObj) { if (selObj instanceof AbstractDatabaseFolderNode) { AbstractDatabaseFolderNode fNode = (AbstractDatabaseFolderNode) selObj; Package ctatlogSwtich = SwitchHelpers.PACKAGE_SWITCH.doSwitch((EObject) fNode.getParent()); ColumnSet columnSet = SwitchHelpers.COLUMN_SET_SWITCH.doSwitch((EObject) fNode.getParent()); if (ctatlogSwtich != null) { this.selectedObj = ctatlogSwtich; } else if (columnSet != null) { this.selectedObj = columnSet; } this.dbFolderNode = fNode; } else { selectedObj = selObj; } } @Override public Connection reloadCurrentLevelElement() throws ReloadCompareException { if (!isValid()) { return null; } oldDataProvider = upperCaseConnection(findDataProvider()); if (oldDataProvider == null) { return null; } IFile tempFile = createTempConnectionFile(); if (compareWithReloadObject()) { // before save, reset the old the taggedvalues resetTaggedValues(); saveReloadResult(); } deleteTempConnectionFile(tempFile); return oldDataProvider; } /** * reset the targedvalues */ protected void resetTaggedValues() throws ReloadCompareException { // Copy db type and db version tagged values . String databaseType = TaggedValueHelper.getValueString(TaggedValueHelper.DB_PRODUCT_NAME, tempReloadProvider); String productVersion = TaggedValueHelper.getValueString(TaggedValueHelper.DB_PRODUCT_VERSION, tempReloadProvider); TaggedValueHelper.setTaggedValue(oldDataProvider, TaggedValueHelper.DB_PRODUCT_NAME, databaseType); TaggedValueHelper.setTaggedValue(oldDataProvider, TaggedValueHelper.DB_PRODUCT_VERSION, productVersion); } /** * Delete temp file */ private void deleteTempConnectionFile(IFile tempFile) { DQStructureComparer.deleteFile(tempFile); } @Override public void popComparisonUI(IUIHandler uiHandler) throws ReloadCompareException { this.guiHandler = uiHandler; if (!isValid()) { return; } oldDataProvider = upperCaseConnection(findDataProvider()); if (oldDataProvider == null) { return; } // DQStructureComparer.deleteCopiedResourceFile(); // DQStructureComparer.deleteNeedReloadElementFile(); createTempConnectionFile(); createCopyedProvider(); // MOD mzhao 2009-01-20 Extract method openDiffCompareEditor to class // DQStructureComparer. // MOD mzhao 2009-03-09 add param dbname for displaying datasource(db // name) in compare // editor. Object needReloadObject = dbFolderNode == null ? selectedObj : dbFolderNode; // DQStructureComparer.openDiffCompareEditor(getLeftResource(), getRightResource(), options, guiHandler, // DQStructureComparer.getDiffResourceFile(), oldDataProvider.getName(), needReloadObject, false); testInit(); } @SuppressWarnings("deprecation") protected void createCopyedProvider() throws ReloadCompareException { IFile selectedFile = WorkspaceUtils.getModelElementResource(oldDataProvider); IFile createNeedReloadElementsFile = DQStructureComparer.getNeedReloadElementsFile(); IFile copyedFile = DQStructureComparer.copyedToDestinationFile(selectedFile, createNeedReloadElementsFile); TypedReturnCode<Connection> returnValue = DqRepositoryViewService.readFromFile(copyedFile); if (returnValue.isOk()) { copyedDataProvider = returnValue.getObject(); } else { DQStructureComparer.deleteFile(createNeedReloadElementsFile); throw new ReloadCompareException(returnValue.getMessage()); } } /** * DOC rli Comment method "createTempConnectionFile". * * @throws ReloadCompareException */ protected IFile createTempConnectionFile() throws ReloadCompareException { IFile tempConnectionFile = DQStructureComparer.getTempRefreshFile(); // MOD mzhao ,Extract method getRefreshedDataProvider to class // DQStructureComparer for common use. TypedReturnCode<Connection> returnProvider = DQStructureComparer.getRefreshedDataProvider(oldDataProvider); if (!returnProvider.isOk()) { throw new ReloadCompareException(returnProvider.getMessage()); } tempReloadProvider = upperCaseConnection(returnProvider.getObject()); tempReloadProvider.setComponent(oldDataProvider.getComponent()); // MOD mzhao bug:9012 2009-09-08 ElementWriterFactory.getInstance().createDataProviderWriter() .create(tempReloadProvider, tempConnectionFile.getFullPath(), false); tempReloadProvider.setComponent(null); oldDataProvider.getComponent(); return tempConnectionFile; } private void testInit() throws ReloadCompareException { URI uri = URI.createPlatformResourceURI(DQStructureComparer.getNeedReloadElementsFile().getFullPath().toString(), false); Resource leftResource = EMFSharedResources.getInstance().getResource(uri, true); uri = URI.createPlatformResourceURI(DQStructureComparer.getTempRefreshFile().getFullPath().toString(), false); Resource rightResource = EMFSharedResources.getInstance().getResource(uri, true); // openDiffCompareEditor(leftResource, rightResource, options); } protected abstract EObject getSavedReloadObject() throws ReloadCompareException; protected abstract Resource getRightResource() throws ReloadCompareException; protected void saveReloadResult() { if (oldDataProvider.getName() == null) { oldDataProvider.setName(PropertyHelper.getProperty(oldDataProvider).getLabel()); } // MOD klliu bug 15940 201-09-30 // MOD msjian 2011-5-23 bug 20875: fix the issue2 error(because two times updateDependecy) ElementWriterFactory.getInstance().createDataProviderWriter().save(oldDataProvider, true); // PrvResourceFileHelper.getInstance().save(oldDataProvider); } /** * Method "findDataProvider". * * @return the data provider of the selected object */ protected abstract Connection findDataProvider(); protected boolean isValid() { return true; } /** * remove the jrxml from the ResourceSet before doMatch, if the ResourceSet is null, return empty Map. Should call * this method only before doMatch. * * @return */ protected Map<ResourceSet, List<Resource>> removeJrxmlsFromResourceSet() { Map<ResourceSet, List<Resource>> map = new HashMap<ResourceSet, List<Resource>>(); ResourceSet resourceSet = oldDataProvider.eResource() == null ? null : oldDataProvider.eResource().getResourceSet(); if (resourceSet != null) { map.put(resourceSet, ResourceManager.removeJrxmls(resourceSet)); } return map; } /** * add the jrxml into the ResourceSet after doMatch. Should call this method only after doMatch * * @param rsJrxmlMap */ protected void addJrxmlsIntoResourceSet(Map<ResourceSet, List<Resource>> rsJrxmlMap) { if (!rsJrxmlMap.isEmpty()) { ResourceSet resourceSet = rsJrxmlMap.keySet().iterator().next(); List<Resource> jrxmlResources = rsJrxmlMap.get(resourceSet); if (resourceSet != null && !jrxmlResources.isEmpty()) { resourceSet.getResources().addAll(jrxmlResources); } } } /** * Compare the old selected object with reload object(rightResource), and updated the content of old selected * object. * * @param rightResource * @return * @throws ReloadCompareException */ protected boolean compareWithReloadObject() throws ReloadCompareException { Map<ResourceSet, List<Resource>> rsJrxmlMap = removeJrxmlsFromResourceSet(); EMFCompare comparator = createDefaultEMFCompare(); IComparisonScope scope = new DefaultComparisonScope(oldDataProvider, getSavedReloadObject(), null); Comparison compare = comparator.compare(scope); // add the jrxml into the ResourceSet after doMatch addJrxmlsIntoResourceSet(rsJrxmlMap); EList<Diff> differences = compare.getDifferences(); for (Diff diff : differences) { // ignore the move Kind if (diff.getKind() == DifferenceKind.MOVE) { continue; } copyRightToLeft(diff); } return true; } protected abstract Resource getLeftResource() throws ReloadCompareException; protected void popRemoveElementConfirm() { if (!removeElementConfirm) { final Connection provider = oldDataProvider; if (guiHandler != null) { guiHandler.popRemoveElement(provider); } removeElementConfirm = true; } } protected Resource upperCaseResource(Resource res) { if (CASE_INSENSTIVE) { EList<EObject> contents = res.getContents(); for (EObject eo : contents) { upperCase(eo); } } return res; } protected Connection upperCaseConnection(Connection connection) { if (CASE_INSENSTIVE) { EList<ModelElement> ownedElement = connection.getOwnedElement(); for (ModelElement me : ownedElement) { upperCase(me); } } return connection; } private void upperCase(EObject eObject) { Package pckg = SwitchHelpers.PACKAGE_SWITCH.doSwitch(eObject); ColumnSet columnSet = SwitchHelpers.COLUMN_SET_SWITCH.doSwitch(eObject); TdColumn column = SwitchHelpers.COLUMN_SWITCH.doSwitch(eObject); if (column != null) { column.setName(column.getName() == null ? "" : column.getName().toUpperCase());//$NON-NLS-1$ column.setLabel(column.getLabel() == null ? "" : column.getLabel().toUpperCase());//$NON-NLS-1$ column.getSqlDataType().setName( column.getSqlDataType().getName() == null ? "" : column.getSqlDataType().getName().toUpperCase());//$NON-NLS-1$ column.setContentType(column.getContentType() == null ? "" : column.getContentType().toUpperCase());//$NON-NLS-1$ column.setSourceType(column.getSourceType() == null ? "" : column.getSourceType().toUpperCase());//$NON-NLS-1$ } else if (pckg != null) { pckg.setName(pckg.getName() == null ? "" : pckg.getName().toUpperCase());//$NON-NLS-1$ } else if (columnSet != null) { columnSet.setName(columnSet.getName() == null ? "" : columnSet.getName().toUpperCase());//$NON-NLS-1$ } } /** * * create a EMFCompare with default configuration. * * @return */ protected EMFCompare createDefaultEMFCompare() { // Configure EMF Compare IEObjectMatcher matcher = ModelElementMatchEngine.createDQEObjectMatcher(UseIdentifiers.NEVER); DefaultEqualityHelperFactory equalityHelperFactory = new DefaultEqualityHelperFactory(); IComparisonFactory comparisonFactory = new DefaultComparisonFactory(equalityHelperFactory); IMatchEngine.Factory.Registry matchEngineRegistry = new MatchEngineFactoryRegistryImpl(); // IMatchEngine.Factory.Registry matchEngineRegistry = // EMFCompareRCPPlugin.getDefault().getMatchEngineFactoryRegistry(); DQMatchEngineFactory matchEngineFactoryImpl = new DQMatchEngineFactory(matcher, comparisonFactory); matchEngineRegistry.add(matchEngineFactoryImpl); Builder builder = EMFCompare.builder(); builder.setDiffEngine(diffEngineWithFilter()); EMFCompare comparator = builder.setMatchEngineFactoryRegistry(matchEngineRegistry).build(); return comparator; } /** * * ignore the difference of id(not xmi id) Atrribute. * * @return */ protected IDiffEngine diffEngineWithFilter() { IDiffProcessor diffProcessor = new DiffBuilder(); IDiffEngine diffEngine = new DefaultDiffEngine(diffProcessor) { @Override protected FeatureFilter createFeatureFilter() { return new FeatureFilter() { // @Override @Override public boolean checkForOrderingChanges(EStructuralFeature feature) { return false; } @Override protected boolean isIgnoredAttribute(EAttribute attribute) { return "id".equals(attribute.getName()) || attribute.isID() || super.isIgnoredAttribute(attribute); //$NON-NLS-1$ } }; } }; return diffEngine; } /** * DOC qiongli Comment method "copyRightToLeft". * * @param diff */ protected void copyRightToLeft(Diff diff) { // copy right to left Registry registry = IMerger.RegistryImpl.createStandaloneInstance(); DQReferenceMerger dqReferenceMerger = new DQReferenceMerger(); dqReferenceMerger.setRanking(50); registry.add(dqReferenceMerger); final IMerger merger = registry.getHighestRankingMerger(diff); merger.copyRightToLeft(diff, new BasicMonitor()); } }