// ============================================================================ // // Copyright (C) 2006-2012 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.core.model.context; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.PatternCompiler; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; import org.apache.oro.text.regex.Perl5Substitution; import org.apache.oro.text.regex.Util; import org.talend.core.language.ECodeLanguage; import org.talend.core.language.LanguageManager; import org.talend.core.model.process.IConnection; import org.talend.core.model.process.IElementParameter; import org.talend.core.model.process.INode; import org.talend.core.model.process.IProcess; import org.talend.core.model.utils.ContextParameterUtils; import org.talend.designer.core.model.utils.emf.talendfile.ConnectionType; import org.talend.designer.core.model.utils.emf.talendfile.ContextParameterType; import org.talend.designer.core.model.utils.emf.talendfile.ContextType; import org.talend.designer.core.model.utils.emf.talendfile.ElementParameterType; import org.talend.designer.core.model.utils.emf.talendfile.NodeType; import org.talend.designer.core.model.utils.emf.talendfile.ProcessType; /** * ggu class global comment. Detailled comment. */ public final class UpdateContextVariablesHelper { /** * * ggu Comment method "updateProcess". * * update parameters for the current opened job . */ public static boolean updateProcessForRenamed(IProcess process, final String oldVarName, final String newVarName) { if (process == null || oldVarName == null || newVarName == null) { return false; } Map<String, String> renamedMap = new HashMap<String, String>(); renamedMap.put(newVarName, oldVarName); return updateProcessForRenamed(process, renamedMap); } /** * renamedMap must be mapped from new to old. */ @SuppressWarnings("unchecked") public static boolean updateProcessForRenamed(IProcess process, final Map<String, String> renamedMap) { if (process == null || renamedMap == null || renamedMap.isEmpty()) { return false; } // old to new map Map<String, String> varScriptCodeMap = retrieveRenamedScriptCodeMap(renamedMap); if (varScriptCodeMap.isEmpty()) { return false; } boolean changed = false; // update main parameters changed = updateElementParameters((List<IElementParameter>) process.getElementParametersWithChildrens(), varScriptCodeMap); // update nodes parameters. for (INode node : (List<INode>) process.getGraphicalNodes()) { for (String oldScriptCode : varScriptCodeMap.keySet()) { String newScriptCode = varScriptCodeMap.get(oldScriptCode); if (newScriptCode != null) { node.renameData(oldScriptCode, newScriptCode); changed = true; } } // update links parameters(bug 3993) for (IConnection conn : node.getOutgoingConnections()) { changed |= updateElementParameters((List<IElementParameter>) conn.getElementParametersWithChildrens(), varScriptCodeMap); } } return changed; } /** * * ggu Comment method "updateProcess". * * update paramters for the job item file. * * renamedMap must be mapped from new to old. */ public static boolean updateProcessForRenamed(ProcessType processType, final Map<String, String> renamedMap) { if (processType == null || renamedMap == null || renamedMap.isEmpty()) { return false; } Map<String, String> renamedScriptCodeMap = retrieveRenamedScriptCodeMap(renamedMap); if (renamedScriptCodeMap.isEmpty()) { return false; } return updateProcess(processType, renamedScriptCodeMap, false); } @SuppressWarnings("unchecked") public static boolean updateProcessForReplacedOldScriptCode(ProcessType processType) { if (processType == null) { return false; } // get old syntax map of the context variables. Map<String, String> replacedScriptCodeMap = retrieveReplacedScriptCodeMap((List<ContextType>) processType.getContext(), processType.getDefaultContext()); if (replacedScriptCodeMap.isEmpty()) { return false; } return updateProcess(processType, replacedScriptCodeMap, true); } @SuppressWarnings("unchecked") private static boolean updateProcess(ProcessType processType, final Map<String, String> varScriptCodeMap, boolean oldSyntax) { if (processType == null || varScriptCodeMap == null || varScriptCodeMap.isEmpty()) { return false; } boolean changed = false; // update process parameter changed = updateElementParameter((List<ElementParameterType>) processType.getParameters().getElementParameter(), varScriptCodeMap, oldSyntax); // update nodes parameter for (NodeType node : (List<NodeType>) processType.getNode()) { // update parameter changed |= updateElementParameter((List<ElementParameterType>) node.getElementParameter(), varScriptCodeMap, oldSyntax); // update extend node data String strdata = node.getStringData(); if (strdata != null) { String newData = replaceQuotStringData(strdata, varScriptCodeMap, oldSyntax); if (newData != null && !newData.equals(strdata)) { node.setStringData(newData); changed = true; } } } // update links parameters(bug 3993) for (ConnectionType conn : (List<ConnectionType>) processType.getConnection()) { // update parameter changed |= updateElementParameter((List<ElementParameterType>) conn.getElementParameter(), varScriptCodeMap, oldSyntax); } return changed; } private static boolean updateElementParameter(List<ElementParameterType> eleParameterList, final Map<String, String> varScriptCodeMap, boolean oldSyntax) { if (eleParameterList == null || eleParameterList.isEmpty() || varScriptCodeMap == null || varScriptCodeMap.isEmpty()) { return false; } boolean changed = false; for (ElementParameterType eleParameterType : (List<ElementParameterType>) eleParameterList) { String oldValue = eleParameterType.getValue(); if (oldValue != null) { String newValue = hasAndReplaceValue(oldValue, varScriptCodeMap, oldSyntax); if (newValue != null && !oldValue.equals(newValue)) { eleParameterType.setValue(newValue); changed = true; } } } return changed; } private static String hasAndReplaceValue(final String value, final Map<String, String> varScriptCodeMap, boolean oldSyntax) { if (value == null || varScriptCodeMap == null || varScriptCodeMap.isEmpty()) { return value; // keep original value } String returnValue = value; for (String oldScriptCode : varScriptCodeMap.keySet()) { String contextNameFullName = varScriptCodeMap.get(oldScriptCode); returnValue = hasAndReplaceValue(returnValue, replaceSpecialChar(oldScriptCode), varScriptCodeMap.get(oldScriptCode), oldSyntax); if (LanguageManager.getCurrentLanguage() == ECodeLanguage.JAVA) { // add this for bug 3455 returnValue = migrateContextPropertySetter(returnValue, contextNameFullName.replaceAll("context\\.", ""), false); //$NON-NLS-1$ //$NON-NLS-2$ } } return returnValue; } private static String migrateContextPropertySetter(String fullContent, String varName, boolean isExtension) { String beginString = "context.setProperty("; //$NON-NLS-1$ if (!fullContent.contains(beginString)) { return fullContent; } String regex = beginString + "\"" + varName + "\","; //$NON-NLS-1$ //$NON-NLS-2$ regex = replaceSpecialChar(regex); if (isExtension) { regex = regex.replaceAll("\"", """); //$NON-NLS-1$ //$NON-NLS-2$ } regex = "(.*?)(" + regex + ")(.*?)\\);"; //$NON-NLS-1$ //$NON-NLS-2$ String out = ContextParameterUtils.JAVA_NEW_CONTEXT_PREFIX + varName + "="; //$NON-NLS-1$ out = "$1" + out + "$3;"; //$NON-NLS-1$ //$NON-NLS-2$ return fullContent.replaceAll(regex, out); } private static String hasAndReplaceValue(final String value, final String oldScriptCode, final String newScriptCode, boolean oldSyntax) { if (value == null || oldScriptCode == null || newScriptCode == null) { return value; // keep original value } PatternCompiler compiler = new Perl5Compiler(); Perl5Matcher matcher = new Perl5Matcher(); matcher.setMultiline(true); // old syntax script code. String prefix = "\\b("; //$NON-NLS-1$ String suffix = ")\\b"; //$NON-NLS-1$ if (oldSyntax) { prefix = "("; //$NON-NLS-1$ suffix = ")"; //$NON-NLS-1$ } String returnValue = value; Pattern pattern; try { pattern = compiler.compile(prefix + oldScriptCode + suffix); } catch (MalformedPatternException e) { return value; // keep original value } if (matcher.contains(value, pattern)) { // replace Perl5Substitution substitution = new Perl5Substitution(newScriptCode, Perl5Substitution.INTERPOLATE_ALL); returnValue = Util.substitute(matcher, pattern, substitution, value, Util.SUBSTITUTE_ALL); } return returnValue; } /** * * ggu Comment method "retrieveRenamedScriptCodeMap". * * retrieve the renamed variables script code map. */ private static Map<String, String> retrieveRenamedScriptCodeMap(final Map<String, String> renamedMap) { if (renamedMap == null || renamedMap.isEmpty()) { return Collections.emptyMap(); } Map<String, String> scriptCodeMap = new HashMap<String, String>(); ECodeLanguage language = LanguageManager.getCurrentLanguage(); for (String newName : renamedMap.keySet()) { String oldName = renamedMap.get(newName); String oldScriptCode = ContextParameterUtils.getNewScriptCode(oldName, language); String newScriptCode = ContextParameterUtils.getNewScriptCode(newName, language); if (oldScriptCode == null || newScriptCode == null) { continue; } scriptCodeMap.put(oldScriptCode, newScriptCode); } for (String newName : renamedMap.keySet()) { String oldName = renamedMap.get(newName); String oldScriptCode = ContextParameterUtils.getNewScriptCode(oldName, language); String newScriptCode = ContextParameterUtils.getNewScriptCode(newName, language); if (oldScriptCode == null || newScriptCode == null) { continue; } scriptCodeMap.put(oldScriptCode, newScriptCode); } return scriptCodeMap; } /** * * ggu Comment method "retrieveReplacedScriptCodeMap". * * retrieve the new and old variables script code map. */ @SuppressWarnings("unchecked") private static Map<String, String> retrieveReplacedScriptCodeMap(List<ContextType> contextsList, final String contextName) { if (contextsList == null || contextsList.isEmpty() || contextName == null) { return Collections.emptyMap(); } ContextType contextType = ContextUtils.getContextTypeByName(contextsList, contextName); if (contextType == null) { return Collections.emptyMap(); } Map<String, String> varsScriptCodeMap = new HashMap<String, String>(); ECodeLanguage language = LanguageManager.getCurrentLanguage(); for (ContextParameterType parameter : (List<ContextParameterType>) contextType.getContextParameter()) { String oldCode = ContextParameterUtils.getScriptCode(parameter, language); String newCode = ContextParameterUtils.getNewScriptCode(parameter.getName(), language); varsScriptCodeMap.put(oldCode, newCode); } return varsScriptCodeMap; } private static String replaceQuotStringData(String data, final Map<String, String> varScriptCodeMap, boolean oldSyntax) { Map<String, String> varScriptCodeMapExt = new HashMap<String, String>(); for (String oldScriptCode : varScriptCodeMap.keySet()) { String newScriptCode = varScriptCodeMap.get(oldScriptCode); if (newScriptCode == null) { continue; } oldScriptCode = oldScriptCode.replaceAll("\"", """); //$NON-NLS-1$ //$NON-NLS-2$ varScriptCodeMapExt.put(oldScriptCode, newScriptCode); data = migrateContextPropertySetter(data, newScriptCode.replaceAll("context\\.", ""), true); //$NON-NLS-1$ //$NON-NLS-2$ } return hasAndReplaceValue(data, varScriptCodeMapExt, oldSyntax); } public static String replaceSpecialChar(String expression) { if (expression == null) { return null; } expression = expression.replaceAll("\\(", "\\\\("); //$NON-NLS-1$ //$NON-NLS-2$ expression = expression.replaceAll("\\)", "\\\\)"); //$NON-NLS-1$ //$NON-NLS-2$ expression = expression.replaceAll("\\.", "\\\\."); //$NON-NLS-1$ //$NON-NLS-2$ return expression; } private static boolean updateElementParameters(List<IElementParameter> parameters, Map<String, String> varScriptCodeMap) { if (parameters == null || parameters.isEmpty() || varScriptCodeMap == null || varScriptCodeMap.isEmpty()) { return false; } boolean changed = false; for (IElementParameter parameter : parameters) { Object obj = parameter.getValue(); if (obj != null && obj instanceof String) { String value = (String) obj; String newValue = hasAndReplaceValue(value, varScriptCodeMap, false); if (newValue != null && !value.equals(newValue)) { parameter.setValue(newValue); changed = true; } } } return changed; } }