// ============================================================================ // // 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.dataprofiler.core.migration.impl; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang.StringUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.talend.commons.emf.EMFUtil; import org.talend.commons.utils.io.FilesUtils; import org.talend.core.model.metadata.builder.connection.DatabaseConnection; import org.talend.cwm.dependencies.DependenciesHandler; import org.talend.cwm.helper.ConnectionHelper; import org.talend.cwm.helper.SwitchHelpers; import org.talend.cwm.relational.TdColumn; import org.talend.dataprofiler.core.migration.AbstractWorksapceUpdateTask; import org.talend.dataquality.analysis.Analysis; import org.talend.dq.writer.EMFSharedResources; import org.talend.resource.EResourceConstant; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import orgomg.cwm.foundation.softwaredeployment.DataManager; import orgomg.cwm.foundation.softwaredeployment.DataProvider; import orgomg.cwm.objectmodel.core.Dependency; import orgomg.cwm.objectmodel.core.ModelElement; import orgomg.cwm.objectmodel.core.Package; import orgomg.cwm.resource.relational.Catalog; /** * created by yyin on 2013-7-10 check the client dependency of the analysis according to TDQ-7327 if there are more than * one client dependency(db connection), remove the not used one, and remove the related dependency in the removed db * connection * */ public class CheckAndUpdateAnalysisDependencyTask extends AbstractWorksapceUpdateTask { /* * (non-Javadoc) * * @see org.talend.dataprofiler.migration.IMigrationTask#getOrder() */ public Date getOrder() { return createDate(2013, 7, 10); } /* * (non-Javadoc) * * @see org.talend.dataprofiler.migration.IMigrationTask#getMigrationTaskType() */ public MigrationTaskType getMigrationTaskType() { return MigrationTaskType.FILE; } /* * (non-Javadoc) * * @see org.talend.dataprofiler.migration.AMigrationTask#doExecute() */ @Override protected boolean doExecute() throws Exception { // load all connections and check if any catelog has more than one datamanager checkAndRemoveWrongDataManager(getConnections()); // load all analyses and check their dependency correct or not. checkAndRemoveWrongDependencies(getAnalyses()); return true; } /** * DOC yyin Comment method "getConnections". * * @return */ private List<DataManager> getConnections() { List<DataManager> connections = new ArrayList<DataManager>(); File sysIndsFolder = getWorkspacePath().append(EResourceConstant.DB_CONNECTIONS.getPath()).toFile(); ArrayList<File> fileList = new ArrayList<File>(); FilesUtils.getAllFilesFromFolder(sysIndsFolder, fileList, getFilenameFilter("item")); for (File file : fileList) { DataManager indDef = getDataManagerFromFile(file); if (indDef != null) { connections.add(indDef); } } return connections; } private List<Analysis> getAnalyses() { List<Analysis> analyses = new ArrayList<Analysis>(); File sysIndsFolder = getWorkspacePath().append(EResourceConstant.ANALYSIS.getPath()).toFile(); ArrayList<File> fileList = new ArrayList<File>(); FilesUtils.getAllFilesFromFolder(sysIndsFolder, fileList, getFilenameFilter("ana")); for (File file : fileList) { File cleanFile = removeNotUsedModels(file); Analysis indDef = getAnalysisFromFile(cleanFile); if (indDef != null) { analyses.add(indDef); } } return analyses; } private File removeNotUsedModels(File file) { // remove not used any more: where aide rule DocumentBuilder db; try { boolean needSave = false; db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = db.parse(file); Element root = document.getDocumentElement(); NodeList list = root.getElementsByTagName("indicators"); //$NON-NLS-1$ for (int i = 0; i < list.getLength(); i++) { Node item = list.item(i); NamedNodeMap attributes = item.getAttributes(); Node typeItem = attributes.getNamedItem("xsi:type"); //$NON-NLS-1$ if (StringUtils.equals("dataquality.indicators.sql:WhereRuleAideIndicator", typeItem.getNodeValue())) { //$NON-NLS-1$ item.getParentNode().removeChild(item); needSave = true; } } if (needSave) { saveFile(file, document); } } catch (ParserConfigurationException e) { e.printStackTrace(); return null; } catch (SAXException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } return file; } private void saveFile(File needSaveFile, Document doc) {// 将Document输出到文件 TransformerFactory transFactory = TransformerFactory.newInstance(); try { Transformer transformer = transFactory.newTransformer(); Source xmlSource = new DOMSource(doc); Result result = new StreamResult(needSaveFile); transformer.transform(xmlSource, result); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } } private FilenameFilter getFilenameFilter(final String ends) { return new FilenameFilter() { public boolean accept(File dir, String name) { if (name.endsWith(ends)) { return true; } return false; } }; } /** * @param file * @return */ private DataManager getDataManagerFromFile(File file) { Resource itemResource = getResource(file); if (itemResource == null) { return null; } for (EObject object : itemResource.getContents()) { if (object instanceof DataManager) { return (DataManager) object; } } return null; } /** * @param file * @return */ private Analysis getAnalysisFromFile(File file) { Resource itemResource = getResource(file); if (itemResource == null) { return null; } for (EObject object : itemResource.getContents()) { if (object instanceof Analysis) { return (Analysis) object; } } return null; } /** * only need to check database connection * * @param connections */ private void checkAndRemoveWrongDataManager(List<DataManager> connections) { for (DataManager connection : connections) { if (connection instanceof DatabaseConnection) { EList<Package> packages = connection.getDataPackage(); for (EObject obj : packages) { Catalog catalog = SwitchHelpers.CATALOG_SWITCH.doSwitch(obj); // if catelog has more than one data manager if (catalog != null && catalog.getDataManager().size() > 1) { List<DataManager> wrongManagers = new ArrayList<DataManager>(); // remove the wrong datamanger from the catelog; for (DataManager manager : catalog.getDataManager()) { // if the name of the manager does not equal with the parent of the catalog,it is the wrong // one if (!StringUtils.equals(((DatabaseConnection) manager).getName(), ((DatabaseConnection) connection).getName())) { wrongManagers.add(manager); } } removeWrongDataManager(catalog, wrongManagers, connection); } } } } } /** * remove the Wrong Data Manager,and save the connection * * @param catalog * @param connection * @param parent */ private void removeWrongDataManager(Catalog catalog, List<DataManager> wrongManagers, DataManager parent) { for (DataManager wrongone : wrongManagers) { catalog.getDataManager().remove(wrongone); } EMFSharedResources.getInstance().saveResource(parent.eResource()); } /** * check each analysis if it has only one client dependency, if more than one, remove the useless one. * * @param list * @throws CoreException */ private void checkAndRemoveWrongDependencies(List<Analysis> analyses) throws CoreException { for (Analysis analysis : analyses) { if (analysis != null) { boolean isAnalysisModified = false; if (analysis.getContext().getAnalysedElements() == null || analysis.getContext().getAnalysedElements().size() < 1) { continue; } TdColumn tdColumn = SwitchHelpers.COLUMN_SWITCH.doSwitch(analysis.getContext().getAnalysedElements().get(0)); if (tdColumn == null) { continue; } // find the correct db connection from analyzed element DataManager correctDB = ConnectionHelper.getConnection(tdColumn); // check if the connection is correct or not DataManager connection = analysis.getContext().getConnection(); if (connection == null || !correctDB.getName().equals(connection.getName())) { analysis.getContext().setConnection(correctDB); isAnalysisModified = true; } List<DataProvider> clientDependencyDB = null; for (Dependency dependency : analysis.getClientDependency()) { ModelElement supplier = dependency.getSupplier().get(0); if (supplier instanceof DataProvider) { if (supplier != null && correctDB.getName().equals(supplier.getName())) { continue; } else { if (clientDependencyDB == null) { clientDependencyDB = new ArrayList<DataProvider>(); } clientDependencyDB.add((DataProvider) supplier); } } } if (clientDependencyDB != null) { for (DataProvider uselessDB : clientDependencyDB) { // if the db in client dependency do not equal to the correct db, remove it from both the // analysis and db connection removeDependenciesBetweenAnaCon(uselessDB, analysis); isAnalysisModified = true; } } if (isAnalysisModified) { EMFSharedResources.getInstance().saveResource(analysis.eResource()); } } } } private void removeDependenciesBetweenAnaCon(DataProvider oldDataProvider, Analysis tempAnalysis) { List<ModelElement> tempList = new ArrayList<ModelElement>(); tempList.add(oldDataProvider); // remove the cliend dependency in the analysis List<Resource> modified = DependenciesHandler.getInstance().removeDependenciesBetweenModels(tempAnalysis, tempList); for (Resource me : modified) { EMFUtil.saveSingleResource(me); } // remove the supplier dependency in the dataprovider tempList.clear(); tempList.add(tempAnalysis); modified = removeSupplierDependenciesBetweenModels(oldDataProvider, tempList); for (Resource me : modified) { EMFUtil.saveSingleResource(me); } EMFUtil.saveSingleResource(oldDataProvider.eResource()); } /* * This task should be done before the import * * @see org.talend.dataprofiler.migration.AMigrationTask#isModelTask() */ @Override public Boolean isModelTask() { return true; } private List<Resource> removeSupplierDependenciesBetweenModels(ModelElement elementFromRemove, List<? extends ModelElement> elementToRemove) { EList<Dependency> supplierDependencies; List<String> toRemoveResources = new ArrayList<String>(); for (ModelElement modelElement : elementToRemove) { toRemoveResources.add(modelElement.getName()); } // get the client dependencies ( supplierDependencies = elementFromRemove.getSupplierDependency(); List<Resource> modifiedResources = new ArrayList<Resource>(); for (Dependency dependency : supplierDependencies) { EList<ModelElement> client = dependency.getClient(); // get the resource of each client Iterator<ModelElement> dependencyIterator = client.iterator(); while (dependencyIterator.hasNext()) { ModelElement dependencyModel = dependencyIterator.next(); Resource clientResource = dependencyModel.eResource(); if (clientResource != null) { if (toRemoveResources.contains(dependencyModel.getName())) { modifiedResources.add(clientResource); dependencyIterator.remove(); } } } } return modifiedResources; } }