// ============================================================================ // // 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.dq.helper; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Stack; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.talend.commons.emf.EMFUtil; import org.talend.commons.utils.WorkspaceUtils; import org.talend.core.model.metadata.builder.connection.Connection; import org.talend.core.model.metadata.builder.connection.MetadataColumn; import org.talend.core.model.metadata.builder.connection.MetadataTable; import org.talend.core.model.properties.ConnectionItem; import org.talend.core.model.properties.Item; import org.talend.core.model.repository.ERepositoryObjectType; import org.talend.core.model.repository.IRepositoryViewObject; import org.talend.core.repository.model.ProxyRepositoryFactory; import org.talend.core.repository.utils.XmiResourceManager; import org.talend.cwm.dependencies.DependenciesHandler; import org.talend.cwm.helper.ColumnHelper; import org.talend.cwm.helper.ColumnSetHelper; import org.talend.cwm.helper.ConnectionHelper; import org.talend.cwm.helper.ModelElementHelper; import org.talend.cwm.helper.SwitchHelpers; import org.talend.cwm.relational.TdColumn; import org.talend.cwm.relational.TdTable; import org.talend.dataquality.analysis.Analysis; import org.talend.dataquality.analysis.AnalysisContext; import org.talend.dataquality.helpers.ReportHelper; import org.talend.dataquality.helpers.ReportHelper.ReportType; import org.talend.dataquality.reports.AnalysisMap; import org.talend.dataquality.reports.TdReport; import org.talend.dq.factory.ModelElementFileFactory; import org.talend.dq.helper.resourcehelper.ResourceFileMap; import org.talend.dq.nodes.ReportRepNode; import org.talend.repository.model.IRepositoryNode; import org.talend.resource.EResourceConstant; import org.talend.resource.ResourceManager; import orgomg.cwm.objectmodel.core.Dependency; import orgomg.cwm.objectmodel.core.ModelElement; import orgomg.cwm.objectmodel.core.Package; import orgomg.cwm.resource.relational.Catalog; import orgomg.cwm.resource.relational.ColumnSet; import orgomg.cwm.resource.relational.Schema; /** * @author rli * */ public final class EObjectHelper { private EObjectHelper() { } public static TdColumn[] getColumns(ColumnSet columnSet) { List<TdColumn> columns = ColumnSetHelper.getColumns(columnSet); return columns.toArray(new TdColumn[columns.size()]); } public static Package getParent(ColumnSet columnSet) { Catalog catalog = SwitchHelpers.CATALOG_SWITCH.doSwitch(columnSet.eContainer()); if (catalog != null) { return catalog; } else { Schema schema = SwitchHelpers.SCHEMA_SWITCH.doSwitch(columnSet.eContainer()); return schema; } } /** * * @deprecated it's probably better to use {@link ConnectionHelper#getTdDataProvider(TdColumn)} */ @Deprecated public static Connection getTdDataProvider(TdColumn column) { ColumnSet columnSetOwner = ColumnHelper.getColumnSetOwner(column); Package parentCatalogOrSchema = ColumnSetHelper.getParentCatalogOrSchema(columnSetOwner); return ConnectionHelper.getTdDataProvider(parentCatalogOrSchema); } public static Connection getTdDataProvider(TdTable table) { Package parentCatalogOrSchema = ColumnSetHelper.getParentCatalogOrSchema(table); return ConnectionHelper.getTdDataProvider(parentCatalogOrSchema); } public static void removeDependencys(IResource... resources) { for (IResource selectedObj : resources) { IFile file = ((IFile) selectedObj); // String fileName = file.getName(); if (file.getFileExtension() == null) { continue; } ModelElement elementToDelete = getModelElement(file); if (elementToDelete != null) { List<Resource> modifiedResources = DependenciesHandler.getInstance().clearDependencies(elementToDelete); // save now modified resources (that contain the Dependency objects) for (Resource resource : modifiedResources) { EMFUtil.saveSingleResource(resource); } } } } /** * * DOC qiongli Comment method "removeDependencys". * * @param elementToDelete */ public static void removeDependencys(ModelElement elementToDelete) { if (elementToDelete != null) { List<Resource> modifiedResources = DependenciesHandler.getInstance().clearDependencies(elementToDelete); // save now modified resources (that contain the Dependency objects) for (Resource resource : modifiedResources) { EMFUtil.saveSingleResource(resource); // ElementWriterFactory.getInstance().createDataProviderWriter().save(modify); } } } private static ModelElement getModelElement(IFile file) { ResourceFileMap resourceFileMap = ModelElementFileFactory.getResourceFileMap(file); return resourceFileMap != null ? resourceFileMap.getModelElement(file) : null; } private static ModelElement getModelElement(IRepositoryViewObject repositoryObject) { ModelElement modelElement = null; Item theItem = repositoryObject.getProperty().getItem(); if (theItem instanceof ConnectionItem) { modelElement = ((ConnectionItem) theItem).getConnection(); } return modelElement; // ResourceFileMap resourceFileMap = ModelElementFileFactory.getResourceFileMap(file); // return resourceFileMap != null ? resourceFileMap.getModelElement(file) : null; } public static List<ModelElement> getDependencySuppliers(IFile file) { ModelElement findElement = getModelElement(file); EList<Dependency> clientDependencys = findElement.getClientDependency(); // locate resource of each Dependency object List<ModelElement> supplierList = new ArrayList<ModelElement>(); for (Dependency dependency : clientDependencys) { EList<ModelElement> supplier = dependency.getSupplier(); if (supplier != null) { supplierList.addAll(supplier); } } return supplierList; } public static List<ModelElement> getDependencyClients(IFile file) { ModelElement findElement = getModelElement(file); return getDependencyClients(findElement); } public static List<ModelElement> getDependencyClients(IRepositoryViewObject repositoryObject) { ModelElement findElement = getModelElement(repositoryObject); return getDependencyClients(findElement); } /** * * DOC qiongli Comment method "getDependencyClients". * * @param respositoryNode * @return */ public static List<ModelElement> getDependencyClients(IRepositoryNode respositoryNode) { // Added 20130305 check the jRxml and its folder here, because the jrxml are not modelelement type. if (ERepositoryObjectType.TDQ_JRAXML_ELEMENT.equals(respositoryNode.getObjectType())) { return getDependedReportOfJrxml(respositoryNode); } else if (ERepositoryObjectType.METADATA_CON_TABLE.equals(respositoryNode.getObjectType()) || ERepositoryObjectType.METADATA_CON_VIEW.equals(respositoryNode.getObjectType())) { return EObjectHelper.getFirstDependency(respositoryNode); } ModelElement findElement = RepositoryNodeHelper.getModelElementFromRepositoryNode(respositoryNode); return getDependencyClients(findElement); } /** * Go throught all reports in the project and return all which used the current jrxml. * * @param node the Jrxml node * @return list of reports who used this jrxml as user defined template */ public static List<ModelElement> getDependedReportOfJrxml(IRepositoryNode node) { List<ModelElement> dependedReport = new ArrayList<ModelElement>(); if (node.getObject().getProperty() == null) { return dependedReport; } IPath path = PropertyHelper.getItemPath(node.getObject().getProperty()); // check if it has depended Report // get all reports List<ReportRepNode> repNodes = RepositoryNodeHelper.getReportRepNodes( RepositoryNodeHelper.getDataProfilingFolderNode(EResourceConstant.REPORTS), true, true); // go through every report to find if any one used current jrxml for (ReportRepNode report : repNodes) { EList<AnalysisMap> analysisMap = ((TdReport) report.getReport()).getAnalysisMap(); for (AnalysisMap anaMap : analysisMap) { if (isUsedByDeletedJrxml(path, anaMap)) { dependedReport.add(report.getReport()); break; } } } return dependedReport; } /** * check if the anaMap comtains the Jrxml or not, by compare the jrxml's path with anaMap's jrxml source(when user * mode) * * @param path the path of the jrxml saved in the analysis map * @param anaMap the analysis map in the report. * @return the analysis map used the current jrxml or not. */ private static boolean isUsedByDeletedJrxml(IPath path, AnalysisMap anaMap) { ReportType reportType = ReportHelper.ReportType.getReportType(anaMap.getAnalysis(), anaMap.getReportType()); // compare the Jrxml path if the report has the user defined one. if (ReportHelper.ReportType.USER_MADE.equals(reportType)) { String jrxmlPath = anaMap.getJrxmlSource(); String deletedpath = path.removeFirstSegments(2).toString(); if (jrxmlPath.contains(deletedpath)) { return true; } } return false; } public static List<ModelElement> getDependencyClients(ModelElement modelElement) { if (modelElement == null) { return new ArrayList<ModelElement>(); } EList<Dependency> clientDependencys = modelElement.getSupplierDependency(); // locate resource of each Dependency object List<ModelElement> supplierList = new ArrayList<ModelElement>(); for (Dependency dependency : clientDependencys) { EList<ModelElement> clients = dependency.getClient(); if (clients != null) { for (ModelElement client : clients) { if (!client.eIsProxy()) { supplierList.add(client); } } } } return supplierList; } /** * * DOC qiongli Comment method "hasDependences". * * @param node * @return */ public static boolean hasDependencyClients(IRepositoryNode node) { List<ModelElement> dependencies = getDependencyClients(node); if (dependencies == null || dependencies.isEmpty()) { return false; } return true; } /** * get the first Dependency of node(only used for METADATA_CON_TABLE and METADATA_CON_VIEW). * * @param node * @return */ public static List<ModelElement> getFirstDependency(IRepositoryNode node) { List<ModelElement> result = new ArrayList<ModelElement>(); if (node == null) { return result; } // use the connection supplier to get analyses, and then check them when they use the droped table // get the connection ModelElement deleteModel = RepositoryNodeHelper.getMetadataElement(node); Connection connection = ModelElementHelper.getConnection(deleteModel); if (connection == null) { return result; } // get the supplier Dependency of the connection EList<Dependency> supplierDependency = connection.getSupplierDependency(); if (supplierDependency != null && supplierDependency.size() > 0) { EList<ModelElement> clients = supplierDependency.get(0).getClient(); for (ModelElement client : clients) { if (!(client instanceof Analysis)) { continue; } Analysis analysis = (Analysis) client; if (analysis.eIsProxy()) { analysis = (Analysis) EObjectHelper.resolveObject(analysis); } AnalysisContext context = analysis.getContext(); EList<ModelElement> analysedElements = context.getAnalysedElements(); if (analysedElements != null && analysedElements.size() > 0) { ModelElement analysisModel = null; ModelElement firstAnalysisElement = analysedElements.get(0); if (firstAnalysisElement instanceof MetadataColumn) { analysisModel = ModelElementHelper.getContainer(firstAnalysisElement); } else if (firstAnalysisElement instanceof MetadataTable) { analysisModel = firstAnalysisElement; } if (compareModelElement(deleteModel, analysisModel)) { result.add(analysis); break; } } } } return result; } /** * compare two ModelElements. * * @param model1 * @param model2 * @return boolean true: when they have the same name and uuid. */ private static boolean compareModelElement(ModelElement model1, ModelElement model2) { if (model1 == null && model2 == null) { return true; } if (model1 != null && model2 != null) { if (model1.getName().equals(model2.getName())) { if (model2.eIsProxy()) { model2 = (ModelElement) EObjectHelper.resolveObject(model2); } if (model1.eIsProxy()) { model1 = (ModelElement) EObjectHelper.resolveObject(model1); } if (ModelElementHelper.compareUUID(model1, model2)) { return true; } } } return false; } /** * add Dependencies For File. * * @param file * @param modelElements */ public static void addDependenciesForFile(IFile file, List<ModelElement> modelElements) { ModelElement findElement = getModelElement(file); for (int i = 0; i < modelElements.size(); i++) { DependenciesHandler.getInstance().setUsageDependencyOn(findElement, modelElements.get(i)); } } /** * DOC bZhou Comment method "retrieveEObject". * * @param filePath * @param classfier * @return */ public static Object retrieveEObject(IPath filePath, EClass classfier) { if (isEObjectPathExited(filePath)) { URI uri; if (filePath.isAbsolute()) { uri = URI.createFileURI(filePath.toOSString()); } else { uri = URI.createPlatformResourceURI(filePath.toOSString(), false); } Resource res = new ResourceSetImpl().getResource(uri, true); return EcoreUtil.getObjectByType(res.getContents(), classfier); } return null; } /** * DOC bZhou Comment method "isEObjectPathExited". * * @param objectPath * @return */ public static boolean isEObjectPathExited(IPath objectPath) { if (objectPath.isAbsolute()) { return objectPath.toFile().exists(); } else { return ResourceManager.getRoot().getFile(objectPath).exists(); } } /** * * DOC qiongli Comment method "resolveObject". * * @param proxy * @return */ public static EObject resolveObject(EObject proxy) { if (proxy != null && proxy.eIsProxy()) { // if it is remote project,xmiRes will be null XmiResourceManager xmiRes = ProxyRepositoryFactory.getInstance().getRepositoryFactoryFromProvider() .getResourceManager(); if (xmiRes != null) { ResourceSet resourceSet = xmiRes.resourceSet; // FIXME the input proxy object should not be changed in this method. proxy = EcoreUtil.resolve(proxy, resourceSet); } } return proxy; } /** * DOC bZhou Comment method "getURI". * * Get uri for an object. * * @param object * @return */ public static URI getURI(EObject object) { URI uri = null; if (object != null) { if (object.eIsProxy()) { uri = ((InternalEObject) object).eProxyURI(); } else { uri = object.eResource().getURI(); } } return uri; } public static <T extends EObject> T deepCopy(T emfObject) { EcoreUtil.Copier copier = new EcoreUtil.Copier(Boolean.TRUE, Boolean.FALSE); preDeepCopy(emfObject, copier); T copy = (T) copier.copy(emfObject); copier.copyReferences(); return copy; } private static void preDeepCopy(EObject emfObject, EcoreUtil.Copier copier) { Stack<EObject> work = new Stack<EObject>(); work.push(emfObject); Collection<EObject> collection = new LinkedHashSet<EObject>(); while (!work.isEmpty()) { EObject o = work.pop(); if (collection.contains(o)) { continue; } collection.add(o); List<EObject> list = o.eContents(); for (EObject eo : list) { if (!collection.contains(eo)) { work.push(eo); } } list = o.eCrossReferences(); for (EObject eo : list) { if (!collection.contains(eo)) { work.push(eo); } } EObject container = o.eContainer(); if (container != null && !collection.contains(container)) { work.push(container); } } collection = copier.copyAll(collection); copier.copyReferences(); } public static File modelElement2File(ModelElement mElement) { URI uri = getURI(mElement); if (uri != null) { String uriString = WorkspaceUtils.toFile(uri); if (uriString != null) { return new File(uriString); } } return null; } }