blob: cc96fb0182f989818570ab368653193698635e89 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2006-2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*
* </copyright>
*
* $Id: JMerger.java,v 1.27 2008/12/22 14:25:30 emerks Exp $
*/
package org.eclipse.egf.common.generator;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.emf.codegen.merge.java.JControlModel;
import org.eclipse.emf.codegen.merge.java.JMerger;
import org.eclipse.emf.codegen.merge.java.facade.JMember;
import org.eclipse.emf.codegen.merge.java.facade.JMethod;
import org.eclipse.emf.codegen.merge.java.facade.JNode;
/**
* @author Xavier Maysonnave
*
*/
public class EGFJMerger extends JMerger {
public EGFJMerger(JControlModel controlModel) {
super(controlModel);
}
@Override
protected void applyPullRules(JNode sourceNode, JNode targetNode) {
try {
for (JControlModel.PullRule pullRule : getControlModel().getPullRules()) {
if (pullRule.getSourceGetFeature().getFeatureMethod() != null && pullRule.getSourceGetFeature().getFeatureClass().isInstance(sourceNode) && pullRule.getTargetPutFeature().getFeatureMethod() != null && pullRule.getTargetPutFeature().getFeatureClass().isInstance(targetNode)
&& sourcePatternDictionary.isMarkedUp(pullRule.getSourceMarkup(), pullRule.getSourceParentMarkup(), sourceNode) && targetPatternDictionary.isMarkedUp(pullRule.getTargetMarkup(), pullRule.getTargetParentMarkup(), targetNode)) {
// Skip if there's an equality filter and the values aren't equal.
//
if (pullRule.getEqualityFeature() != null) {
Method equalityFeatureMethod = pullRule.getEqualityFeature().getFeatureMethod();
Object value1 = equalityFeatureMethod.invoke(sourceNode, NO_ARGUMENTS);
Object value2 = equalityFeatureMethod.invoke(targetNode, NO_ARGUMENTS);
if (value1 == null ? value2 != null : value1.equals(value2) == false) {
continue;
}
}
Method sourceGetMethod = pullRule.getSourceGetFeature().getFeatureMethod();
Object value = sourceGetMethod.invoke(sourceNode, NO_ARGUMENTS);
Method targetPutMethod = pullRule.getTargetPutFeature().getFeatureMethod();
if (sourceGetMethod.getReturnType().isArray() == false || targetPutMethod.getParameterTypes()[0].isAssignableFrom(sourceGetMethod.getReturnType())) {
if (value instanceof String) {
String stringValue = (String) value;
stringValue = getControlModel().getFacadeHelper().applyFormatRules(stringValue);
Pattern sourceTransfer = pullRule.getSourceTransfer();
if (sourceTransfer != null && targetPutMethod.getName().equals("setSuperclass") == false) { //$NON-NLS-1$
String oldStringValue = (String) sourceGetMethod.invoke(targetNode, NO_ARGUMENTS);
if (oldStringValue != null) {
Matcher sourceMatcher = sourceTransfer.matcher(stringValue);
Matcher targetMatcher = sourceTransfer.matcher(oldStringValue);
if (sourceMatcher.groupCount() >= 1 && targetMatcher.groupCount() >= 1) {
StringBuilder result = new StringBuilder();
int index = 0;
int sourceStart = 0;
int targetStart = 0;
if (sourceTransfer.pattern().startsWith("(\\s*<!--")) { //$NON-NLS-1$
sourceStart = getStartIndex(stringValue);
targetStart = getStartIndex(oldStringValue);
}
// Something to merge
//
for (boolean match = sourceMatcher.find(sourceStart) && targetMatcher.find(targetStart); match; match = sourceMatcher.find() && targetMatcher.find()) {
result.append(stringValue.substring(index, sourceMatcher.start(1)));
result.append(targetMatcher.group(1));
index = sourceMatcher.end(1);
}
// There must be at least one match.
//
if (result.length() == 0) {
stringValue = null;
} else {
result.append(stringValue.substring(index));
stringValue = result.toString();
}
} else {
stringValue = null;
}
}
}
value = stringValue;
}
if (value != null || targetPutMethod.getName().equals("setInitializer") //$NON-NLS-1$
|| targetPutMethod.getName().equals("setSuperclass") //$NON-NLS-1$
|| targetPutMethod.getName().equals("setExceptions") //$NON-NLS-1$
) {
// Ignore if there is not substantial change.
//
Object oldValue = sourceGetMethod.invoke(targetNode, NO_ARGUMENTS);
if (value == null ? oldValue == null : value.equals(oldValue)) {
continue;
} else if (value instanceof Object[] && oldValue instanceof Object[] && Arrays.equals((Object[]) value, (Object[]) oldValue)) {
continue;
} else if (targetPutMethod.getName().equals("setSuperclass")) { //$NON-NLS-1$
if (oldValue != null && value != null && ((String) oldValue).trim().equals(((String) value).trim())) {
continue;
}
Pattern sourceTransfer = pullRule.getSourceTransfer();
String comment = ((JMember) targetNode).getComment();
if (sourceTransfer != null && comment != null) {
Matcher matcher = sourceTransfer.matcher(comment);
while (matcher.find() && matcher.groupCount() >= 1) {
String clientStrings = comment.substring(matcher.start(matcher.groupCount()), matcher.end(matcher.groupCount()));
for (StringTokenizer stringTokenizer = new StringTokenizer(clientStrings, ", \t\n\r\f"); stringTokenizer.hasMoreTokens();) { //$NON-NLS-1$
value = stringTokenizer.nextToken();
}
}
}
}
// The block pattern needs to prevent merging of the return type, to allow changing from the modeled data
// type (Bugzilla 102209).
//
if (sourceGetMethod.getName().equals("getReturnType") //$NON-NLS-1$
&& getControlModel().getBlockPattern() != null && ((JMethod) targetNode).getComment() != null && getControlModel().getBlockPattern().matcher(((JMethod) targetNode).getComment()).find()) {
continue;
}
targetPutMethod.invoke(targetNode, new Object[] { value });
targetCompilationChanged = true;
if (targetPutMethod.getName().equals("setBody") && sourceNode instanceof JMethod) { //$NON-NLS-1$
JMethod sourceMethod = (JMethod) sourceNode;
JMethod targetMethod = (JMethod) targetNode;
String[] sourceParameterTypes = sourceMethod.getParameterTypes();
String[] targetParameterTypes = targetMethod.getParameterTypes();
if (Arrays.equals(sourceParameterTypes, targetParameterTypes)) {
targetMethod.setParameterNames(sourceMethod.getParameterNames());
} else {
// The methods were matched by a process that doesn't consider the
// parameters
targetMethod.setParameters(sourceMethod.getParameters());
}
}
}
} else {
// source method return type is array (getExceptions), target is not array (i.e. addException)
ArrayList<String> additionalStrings = new ArrayList<String>();
String[] sourceStrings = (String[]) value;
if (sourceStrings != null) {
additionalStrings.addAll(Arrays.asList(sourceStrings));
}
if (targetPutMethod.getName().equals("addSuperInterface")) { //$NON-NLS-1$
Pattern sourceTransfer = pullRule.getSourceTransfer();
String comment = ((JMember) targetNode).getComment();
if (sourceTransfer != null && comment != null) {
Matcher matcher = sourceTransfer.matcher(comment);
while (matcher.find() && matcher.groupCount() >= 1) {
String clientStrings = comment.substring(matcher.start(matcher.groupCount()), matcher.end(matcher.groupCount()));
for (StringTokenizer stringTokenizer = new StringTokenizer(clientStrings, ", \t\n\r\f"); stringTokenizer.hasMoreTokens();) { //$NON-NLS-1$
String token = stringTokenizer.nextToken();
if (additionalStrings.contains(token) == false) {
additionalStrings.add(token);
}
}
}
}
String[] oldSuperInterfaces = (String[]) sourceGetMethod.invoke(targetNode);
String[] superInterfaces = additionalStrings.toArray(new String[additionalStrings.size()]);
if (oldSuperInterfaces == null ? superInterfaces.length != 0 : Arrays.equals(oldSuperInterfaces, superInterfaces) == false) {
Method putMethod = targetNode.getClass().getMethod("setSuperInterfaces", String[].class); //$NON-NLS-1$
putMethod.invoke(targetNode, new Object[] { superInterfaces });
targetCompilationChanged = true;
}
} else {
// target method is NOT addSuperInterface
String[] oldStringValues = (String[]) sourceGetMethod.invoke(targetNode, NO_ARGUMENTS);
List<String> old = oldStringValues == null ? Collections.<String> emptyList() : Arrays.<String> asList(oldStringValues);
for (String string : additionalStrings) {
if (old.contains(string) == false) {
targetPutMethod.invoke(targetNode, new Object[] { string });
targetCompilationChanged = true;
}
}
}
}
}
}
} catch (InvocationTargetException exception) {
if (DEBUG) {
exception.printStackTrace();
}
} catch (IllegalAccessException exception) {
if (DEBUG) {
exception.printStackTrace();
}
} catch (SecurityException e) {
if (DEBUG) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
if (DEBUG) {
e.printStackTrace();
}
}
}
// Method created to increase the performance of regular expressions
// by reducing the length of the string that is matched.
//
private int getStartIndex(String string) {
int index = string.indexOf("<!--"); //$NON-NLS-1$
if (index > 0) {
while (Character.isWhitespace(string.charAt(--index)) && index > 0) {
// Back up over the whitespace.
}
return index;
}
return 0;
}
}