KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > codegen > jmerge > JMerger


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2004 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: JMerger.java,v 1.12 2005/06/29 21:13:11 davidms Exp $
16  */

17 package org.eclipse.emf.codegen.jmerge;
18
19
20 import java.io.BufferedInputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.lang.reflect.InvocationTargetException JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35 import java.util.regex.Matcher JavaDoc;
36 import java.util.regex.Pattern JavaDoc;
37
38 import org.eclipse.core.runtime.IPlatformRunnable;
39 import org.eclipse.core.runtime.IProgressMonitor;
40 import org.eclipse.core.runtime.NullProgressMonitor;
41 import org.eclipse.jdt.core.jdom.DOMFactory;
42 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
43 import org.eclipse.jdt.core.jdom.IDOMField;
44 import org.eclipse.jdt.core.jdom.IDOMImport;
45 import org.eclipse.jdt.core.jdom.IDOMInitializer;
46 import org.eclipse.jdt.core.jdom.IDOMMember;
47 import org.eclipse.jdt.core.jdom.IDOMMethod;
48 import org.eclipse.jdt.core.jdom.IDOMNode;
49 import org.eclipse.jdt.core.jdom.IDOMPackage;
50 import org.eclipse.jdt.core.jdom.IDOMType;
51
52
53 /**
54  * This implements the method {@link #run},
55  * which is called just like main during headless workbench invocation.
56  */

57 public class JMerger implements IPlatformRunnable
58 {
59   protected DOMFactory jdomFactory = new DOMFactory();
60   protected JControlModel jControlModel;
61   protected IDOMCompilationUnit sourceCompilationUnit;
62   protected IDOMCompilationUnit targetCompilationUnit;
63   protected JPatternDictionary sourcePatternDictionary;
64   protected JPatternDictionary targetPatternDictionary;
65   protected Map JavaDoc sourceToTargetMap = new HashMap JavaDoc();
66   protected Map JavaDoc targetToSourceMap = new HashMap JavaDoc();
67   protected Map JavaDoc orderedSourceChildrenMap = new HashMap JavaDoc();
68   protected boolean isBlocked;
69
70   /**
71    * This creates an empty instances, an when used as a runnable.
72    */

73   public JMerger()
74   {
75   }
76
77   public JMerger(JControlModel jControlModel, IDOMCompilationUnit sourceCompilationUnit, IDOMCompilationUnit targetCompilationUnit)
78   {
79     this.jControlModel = jControlModel;
80     setSourceCompilationUnit(sourceCompilationUnit);
81     setTargetCompilationUnit(targetCompilationUnit);
82   }
83
84   public void merge()
85   {
86     pullTargetCompilationUnit();
87     if (!isBlocked)
88     {
89       pushSourceCompilationUnit();
90       sweepTargetCompilationUnit();
91       sortTargetCompilationUnit();
92     }
93   }
94
95   public void remerge()
96   {
97     sourceToTargetMap.clear();
98     targetToSourceMap.clear();
99     orderedSourceChildrenMap.clear();
100     isBlocked = false;
101     merge();
102   }
103
104   public JControlModel getControlModel()
105   {
106     return jControlModel;
107   }
108
109   public void setControlModel(JControlModel jControlModel)
110   {
111     this.jControlModel = jControlModel;
112   }
113   
114   public String JavaDoc getSourceCompilationUnitContents()
115   {
116     return sourceCompilationUnit.getContents();
117   }
118   
119   public IDOMCompilationUnit getSourceCompilationUnit()
120   {
121     return sourceCompilationUnit;
122   }
123
124   public void setSourceCompilationUnit(IDOMCompilationUnit sourceCompilationUnit)
125   {
126     this.sourceCompilationUnit = sourceCompilationUnit;
127     sourcePatternDictionary = new JPatternDictionary(sourceCompilationUnit, jControlModel);
128     // System.out.println("-- source --");
129
// sourcePatternDictionary.dumpMarkup();
130
}
131   
132   public String JavaDoc getTargetCompilationUnitContents()
133   {
134     return targetCompilationUnit.getContents();
135   }
136
137   public IDOMCompilationUnit getTargetCompilationUnit()
138   {
139     return targetCompilationUnit;
140   }
141
142   public void setTargetCompilationUnit(IDOMCompilationUnit targetCompilationUnit)
143   {
144     this.targetCompilationUnit = targetCompilationUnit;
145     targetPatternDictionary = new JPatternDictionary(targetCompilationUnit, jControlModel);
146     // System.out.println("-- target --");
147
// targetPatternDictionary.dumpMarkup();
148
}
149
150   public JPatternDictionary getSourcePatternDictionary()
151   {
152     return sourcePatternDictionary;
153   }
154
155   public void setSourcePatternDictionary(JPatternDictionary sourcePatternDictionary)
156   {
157     this.sourcePatternDictionary = sourcePatternDictionary;
158   }
159
160   public JPatternDictionary getTargetPatternDictionary()
161   {
162     return targetPatternDictionary;
163   }
164
165   public void setTargetPatternDictionary(JPatternDictionary targetPatternDictionary)
166   {
167     this.targetPatternDictionary = targetPatternDictionary;
168   }
169
170   public Map JavaDoc getSourceToTargetMap()
171   {
172     return sourceToTargetMap;
173   }
174
175   public void setSourceToTargetMap(Map JavaDoc sourceToTargetMap)
176   {
177     this.sourceToTargetMap = sourceToTargetMap;
178   }
179
180   /**
181    * Create a JDOM from a URI.
182    */

183   public IDOMCompilationUnit createCompilationUnitForURI(String JavaDoc uri)
184   {
185     try
186     {
187       URL JavaDoc url = null;
188       try
189       {
190         url = new URL JavaDoc(uri);
191       }
192       catch (MalformedURLException JavaDoc exception)
193       {
194         url = new URL JavaDoc("file:" + uri);
195       }
196       if (url != null)
197       {
198         BufferedInputStream JavaDoc bufferedInputStream = new BufferedInputStream JavaDoc(url.openStream());
199         byte [] input = new byte [bufferedInputStream.available()];
200         bufferedInputStream.read(input);
201         bufferedInputStream.close();
202         return jdomFactory.createCompilationUnit(new String JavaDoc(input), url.toString());
203       }
204     }
205     catch (IOException JavaDoc exception)
206     {
207       // exception.printStackTrace();
208
}
209
210     return null;
211   }
212
213   public IDOMCompilationUnit createCompilationUnitForInputStream(InputStream JavaDoc inputStream)
214   {
215     try
216     {
217       BufferedInputStream JavaDoc bufferedInputStream = new BufferedInputStream JavaDoc(inputStream);
218       byte [] input = new byte [bufferedInputStream.available()];
219       bufferedInputStream.read(input);
220       bufferedInputStream.close();
221       return jdomFactory.createCompilationUnit(new String JavaDoc(input), "NAME");
222     }
223     catch (IOException JavaDoc exception)
224     {
225       // exception.printStackTrace();
226
}
227     return null;
228   }
229
230   /**
231    * Create a JDOM from contents.
232    */

233   public IDOMCompilationUnit createCompilationUnitForContents(String JavaDoc contents)
234   {
235     return jdomFactory.createCompilationUnit(contents, "NAME");
236   }
237
238
239 ///////////////////////////////// PULL /////////////////////////////////////
240

241   protected void pullTargetCompilationUnit()
242   {
243     if (targetCompilationUnit == null)
244     {
245       setTargetCompilationUnit((IDOMCompilationUnit)insertClone(sourceCompilationUnit));
246     }
247     else
248     {
249       map(sourceCompilationUnit, targetCompilationUnit);
250       applyPullRules(sourceCompilationUnit, targetCompilationUnit);
251
252 /*
253     // PULL Header
254     //
255     String sourceHeader = sourceCompilationUnit.getHeader();
256     if (sourceHeader != null)
257     {
258       targetCompilationUnit.setHeader(sourceHeader);
259     }
260
261 */

262       for (IDOMNode child = targetCompilationUnit.getFirstChild(); child != null; child = child.getNextNode())
263       {
264         switch (child.getNodeType())
265         {
266           case IDOMNode.PACKAGE:
267           {
268             pullTargetPackage((IDOMPackage)child);
269             break;
270           }
271           case IDOMNode.IMPORT:
272           {
273             pullTargetImport((IDOMImport)child);
274             break;
275           }
276           case IDOMNode.TYPE:
277           {
278             IDOMType type = (IDOMType)child;
279             isBlocked =
280               jControlModel.getBlockPattern() != null &&
281                 type.getComment() != null &&
282                 jControlModel.getBlockPattern().matcher(type.getComment()).find();
283             if (!isBlocked)
284             {
285               pullTargetType(type);
286             }
287             break;
288           }
289         }
290       }
291     }
292   }
293
294   protected void pullTargetPackage(IDOMPackage targetPackage)
295   {
296     IDOMPackage sourcePackage = sourcePatternDictionary.getPackage();
297     map(sourcePackage, targetPackage);
298     applyPullRules(sourcePackage, targetPackage);
299
300 /*
301     // PULL Name
302     //
303     targetPackage.setName(sourcePackage.getName());
304 */

305   }
306
307   protected void pullTargetImport(IDOMImport targetImport)
308   {
309     IDOMImport sourceImport =
310       (IDOMImport)sourcePatternDictionary.getImportMap().get(targetPatternDictionary.getQualifiedName(targetImport));
311     map(sourceImport, targetImport);
312     if (sourceImport != null)
313     {
314       applyPullRules(sourceImport, targetImport);
315     }
316   }
317
318   protected void pullTargetType(IDOMType targetType)
319   {
320     IDOMType sourceType = (IDOMType)sourcePatternDictionary.getTypeMap().get(targetPatternDictionary.getQualifiedName(targetType));
321
322     map(sourceType, targetType);
323     if (sourceType != null)
324     {
325       applyPullRules(sourceType, targetType);
326
327 /*
328       // PULL: Comment
329       //
330       String sourceComment = sourceType.getComment();
331       if (sourceComment != null)
332       {
333         targetType.setComment(sourceComment);
334       }
335 */

336 /*
337       // PULL: Flags
338       //
339       int sourceFlags = sourceType.getFlags();
340       targetType.setFlags(sourceFlags);
341
342       // PULL: Superclass
343       //
344       targetType.setSuperclass(sourceType.getSuperclass());
345
346       // PULL: SuperInterfaces
347       //
348       ArrayList additionalSuperInterfaces = new ArrayList();
349       String [] sourceSuperInterfaces = sourceType.getSuperInterfaces();
350       if (sourceSuperInterfaces != null)
351       {
352         additionalSuperInterfaces.addAll(Arrays.asList(sourceSuperInterfaces));
353         String [] targetTypeSuperInterfaces = targetType.getSuperInterfaces();
354         if (targetTypeSuperInterfaces != null)
355         {
356           additionalSuperInterfaces.removeAll(Arrays.asList(targetType.getSuperInterfaces()));
357         }
358       }
359       for (Iterator i = additionalSuperInterfaces.iterator(); i.hasNext(); )
360       {
361         String superInterface = (String)i.next();
362         targetType.addSuperInterface(superInterface);
363       }
364 */

365     }
366
367     for (IDOMNode child = targetType.getFirstChild(); child != null; child = child.getNextNode())
368     {
369       switch (child.getNodeType())
370       {
371         case IDOMNode.INITIALIZER:
372         {
373           pullTargetInitializer((IDOMInitializer)child);
374           break;
375         }
376         case IDOMNode.FIELD:
377         {
378           pullTargetField((IDOMField)child);
379           break;
380         }
381         case IDOMNode.METHOD:
382         {
383           pullTargetMethod((IDOMMethod)child);
384           break;
385         }
386         case IDOMNode.TYPE:
387         {
388           pullTargetType((IDOMType)child);
389           break;
390         }
391       }
392     }
393   }
394
395   protected void pullTargetInitializer(IDOMInitializer targetInitializer)
396   {
397     IDOMInitializer sourceInitializer =
398       (IDOMInitializer)sourcePatternDictionary.getInitializerMap().get(targetPatternDictionary.getQualifiedName(targetInitializer));
399     map(sourceInitializer, targetInitializer);
400     if (sourceInitializer != null)
401     {
402       applyPullRules(sourceInitializer, targetInitializer);
403
404 /*
405       // PULL: Comment
406       //
407       String sourceComment = sourceInitializer.getComment();
408       if (sourceComment != null)
409       {
410         targetInitializer.setComment(sourceComment);
411       }
412 */

413
414 /*
415       // PULL: Body
416       //
417       String sourceBody = sourceInitializer.getBody();
418       if (sourceBody != null)
419       {
420         targetInitializer.setBody(sourceBody);
421       }
422 */

423     }
424   }
425
426   protected void pullTargetField(IDOMField targetField)
427   {
428     IDOMField sourceField =
429       (IDOMField)sourcePatternDictionary.getFieldMap().get(targetPatternDictionary.getQualifiedName(targetField));
430
431     map(sourceField, targetField);
432     if (sourceField != null)
433     {
434       applyPullRules(sourceField, targetField);
435
436 /*
437       // PULL: Comment
438       //
439       String sourceComment = sourceField.getComment();
440       if (sourceComment != null)
441       {
442         targetField.setComment(sourceComment);
443       }
444 */

445
446 /*
447       // PULL: Flags
448       //
449       int sourceFlags = sourceField.getFlags();
450       targetField.setFlags(sourceFlags);
451
452       // PULL: Type
453       //
454       String sourceFieldType = sourceField.getType();
455       if (sourceFieldType != null)
456       {
457         targetField.setType(sourceFieldType);
458       }
459
460       // PULL: Initializer
461       //
462       String sourceFieldInitializer = sourceField.getInitializer();
463       if (sourceFieldInitializer != null)
464       {
465         targetField.setInitializer(sourceFieldInitializer);
466       }
467 */

468     }
469   }
470
471   protected void pullTargetMethod(IDOMMethod targetMethod)
472   {
473     String JavaDoc qualifiedTargetMethodName = targetPatternDictionary.getQualifiedName(targetMethod);
474     IDOMMethod sourceMethod =
475       (IDOMMethod)sourcePatternDictionary.getMethodMap().get(qualifiedTargetMethodName);
476
477     if (sourceMethod == null &&
478           jControlModel.getRedirect() != null &&
479           targetMethod.getName() != null &&
480           targetMethod.getName().endsWith(jControlModel.getRedirect()))
481     {
482       int index = qualifiedTargetMethodName.indexOf("("); //)
483
qualifiedTargetMethodName =
484         qualifiedTargetMethodName.substring(0, index - jControlModel.getRedirect().length()) +
485           qualifiedTargetMethodName.substring(index);
486       sourceMethod =
487         (IDOMMethod)sourcePatternDictionary.getMethodMap().get(qualifiedTargetMethodName);
488     }
489
490     map(sourceMethod, targetMethod);
491     if (sourceMethod != null)
492     {
493       applyPullRules(sourceMethod, targetMethod);
494
495 /*
496       // PULL: Comment
497       //
498       String sourceComment = sourceMethod.getComment();
499       if (sourceComment != null)
500       {
501         targetMethod.setComment(sourceComment);
502       }
503 */

504
505 /*
506       // PULL: Flags
507       //
508       int sourceFlags = sourceMethod.getFlags();
509       targetMethod.setFlags(sourceFlags);
510
511       // PULL: Body
512       //
513       String sourceMethodBody = sourceMethod.getBody();
514       if (sourceMethodBody != null)
515       {
516         targetMethod.setBody(sourceMethodBody);
517       }
518
519       // PULL: ReturnType
520       //
521       String sourceMethodReturnType = sourceMethod.getReturnType();
522       if (sourceMethodReturnType != null)
523       {
524         targetMethod.setReturnType(sourceMethodReturnType);
525       }
526 */

527
528 /*
529       // PULL: Exceptions
530       //
531       ArrayList additionalExceptions = new ArrayList();
532       String [] sourceMethodExceptions = sourceMethod.getExceptions();
533       if (sourceMethodExceptions != null)
534       {
535         additionalExceptions.addAll(Arrays.asList(sourceMethodExceptions));
536         String [] targetMethodExceptions = targetMethod.getExceptions();
537         if (targetMethodExceptions != null)
538         {
539           additionalExceptions.removeAll(Arrays.asList(targetMethodExceptions));
540         }
541       }
542       for (Iterator i = additionalExceptions.iterator(); i.hasNext(); )
543       {
544         String exception = (String)i.next();
545         targetMethod.addException(exception);
546       }
547 */

548     }
549   }
550
551   // Platform-dependent literals for line separator character(s).
552
// Note: by using this, we assume that JETEmitter was run on same platform.
553
//
554
protected static String JavaDoc lineSeparator;
555   static
556   {
557     StringBuffer JavaDoc result = new StringBuffer JavaDoc();
558     String JavaDoc s = System.getProperty("line.separator");
559     for (int i = 0, len = s.length(); i < len; i++)
560     {
561       char c = s.charAt(i);
562       if (c == '\r') result.append("\\r");
563       else if (c == '\n') result.append("\\n");
564       else throw new RuntimeException JavaDoc("Unexpected line separator character");
565     }
566     lineSeparator = result.toString();
567   }
568
569   protected static Pattern JavaDoc braceLine = Pattern.compile("(\\s*" + lineSeparator + "\\s*\\{\\s*)" + lineSeparator); // }
570
protected static Pattern JavaDoc leadingTabs = Pattern.compile("^((\\t)+).*$", Pattern.MULTILINE);
571
572   public static abstract class FindAndReplace
573   {
574     protected Pattern JavaDoc pattern;
575     protected String JavaDoc string;
576     protected StringBuffer JavaDoc stringBuffer;
577     protected int current;
578
579     public FindAndReplace(Pattern JavaDoc pattern)
580     {
581       this.pattern = pattern;
582     }
583
584     public String JavaDoc apply(String JavaDoc string)
585     {
586       current = 0;
587       this.string = string;
588       this.stringBuffer = new StringBuffer JavaDoc();
589
590       for (int start = 0, end = string.length(); start < end; )
591       {
592         Matcher JavaDoc matcher = pattern.matcher(string.subSequence(start, end));
593         if (matcher.find())
594         {
595           if (!handleMatch(start, matcher))
596           {
597             break;
598           }
599           start += matcher.end();
600         }
601         else
602         {
603           break;
604         }
605       }
606
607       stringBuffer.append(string.substring(current));
608       return stringBuffer.toString();
609     }
610
611     public void replace(int begin, int end, String JavaDoc replacement)
612     {
613       stringBuffer.append(string.substring(current, begin));
614       stringBuffer.append(replacement);
615       current = end;
616     }
617
618     public abstract boolean handleMatch(int offset, Matcher JavaDoc matcher);
619   }
620
621   protected String JavaDoc applyFormatRules(String JavaDoc value)
622   {
623     final String JavaDoc tabReplacement = jControlModel.getLeadingTabReplacement();
624     if (tabReplacement != null)
625     {
626       FindAndReplace findAndReplaceLeadingTabs =
627         new FindAndReplace(leadingTabs)
628         {
629           public boolean handleMatch(int offset, Matcher JavaDoc matcher)
630           {
631             if (matcher.groupCount() >= 1)
632             {
633               int begin = offset + matcher.start(1);
634               int end = offset + matcher.end(1);
635               StringBuffer JavaDoc replacement = new StringBuffer JavaDoc();
636               for (int i = begin; i < end; ++i)
637               {
638                 replacement.append(tabReplacement);
639               }
640               replace(begin, end, replacement.toString());
641             }
642             return true;
643           }
644         };
645       value = findAndReplaceLeadingTabs.apply(value);
646     }
647
648     if (jControlModel.convertToStandardBraceStyle())
649     {
650       FindAndReplace findAndReplaceLineWithJustABrace =
651         new FindAndReplace(braceLine)
652         {
653           public boolean handleMatch(int offset, Matcher JavaDoc matcher)
654           {
655             if (matcher.groupCount() >= 1)
656             {
657               int begin = offset + matcher.start(1);
658
659               // Don't do replacement if we just did one, or if previous line
660
// ended with a semicolon.
661
//
662
if (current != 0 && (begin <= current || string.charAt(begin - 1) == ';'))
663               {
664                 return true;
665               }
666
667               // Don't do replacement if previous line ended with a comment.
668
//
669
for (int i = begin - 1; i >= current; --i)
670               {
671                 char character = string.charAt(i);
672                 if (character == '\n' || character == '\r')
673                 {
674                   boolean slash = false;
675                   while (++i < begin)
676                   {
677                     character = string.charAt(i);
678                     if (character == '/')
679                     {
680                       if (slash)
681                       {
682                         return true;
683                       }
684                       slash = true;
685                     }
686                     else
687                     {
688                       slash = false;
689                     }
690                   }
691
692                   break;
693                 }
694               }
695
696               int end = offset + matcher.end(1);
697               replace(begin, end, " {"); // }
698
}
699             return true;
700           }
701         };
702       value = findAndReplaceLineWithJustABrace.apply(value);
703     }
704
705     return value;
706   }
707
708   protected static Object JavaDoc [] noArguments = new Object JavaDoc [0];
709   protected void applyPullRules(IDOMNode sourceNode, IDOMNode targetNode)
710   {
711     try
712     {
713       LOOP:
714       for (Iterator JavaDoc pullRules = jControlModel.getPullRules().iterator(); pullRules.hasNext(); )
715       {
716         JControlModel.PullRule pullRule = (JControlModel.PullRule)pullRules.next();
717         if (sourcePatternDictionary.isMarkedUp(pullRule.getSourceMarkup(), sourceNode) &&
718               targetPatternDictionary.isMarkedUp(pullRule.getTargetMarkup(), targetNode) &&
719               pullRule.getSourceGetFeature().getFeatureClass().isInstance(sourceNode) &&
720               pullRule.getTargetPutFeature().getFeatureClass().isInstance(targetNode))
721         {
722           Method JavaDoc sourceGetMethod = pullRule.getSourceGetFeature().getFeatureMethod();
723           Object JavaDoc value = sourceGetMethod.invoke(sourceNode, noArguments);
724           Method JavaDoc targetPutMethod = pullRule.getTargetPutFeature().getFeatureMethod();
725           if (!sourceGetMethod.getReturnType().isArray() ||
726                 targetPutMethod.getParameterTypes()[0].isAssignableFrom(sourceGetMethod.getReturnType()))
727           {
728             if (value instanceof String JavaDoc)
729             {
730               String JavaDoc stringValue = (String JavaDoc)value;
731               stringValue = applyFormatRules(stringValue);
732               Pattern JavaDoc sourceTransfer = pullRule.getSourceTransfer();
733               if (sourceTransfer != null)
734               {
735                 String JavaDoc oldStringValue = (String JavaDoc)sourceGetMethod.invoke(targetNode, noArguments);
736                 Matcher JavaDoc sourceMatcher = sourceTransfer.matcher(stringValue);
737                 Matcher JavaDoc targetMatcher = sourceTransfer.matcher(oldStringValue);
738                 if (sourceMatcher.groupCount() >= 1 && targetMatcher.groupCount() >= 1)
739                 {
740                   StringBuffer JavaDoc result = new StringBuffer JavaDoc();
741                   int index = 0;
742                   while (sourceMatcher.find() && targetMatcher.find())
743                   {
744                     result.append(stringValue.substring(index, sourceMatcher.start(1)));
745                     result.append(targetMatcher.group(1));
746                     index = sourceMatcher.end(1);
747                   }
748                   // There must be at least one match.
749
//
750
if (result.length() == 0)
751                   {
752                     stringValue = null;
753                   }
754                   else
755                   {
756                     result.append(stringValue.substring(index));
757                     stringValue = result.toString();
758                   }
759                 }
760                 else
761                 {
762                   stringValue = null;
763                 }
764               }
765               value = stringValue;
766             }
767             if (value != null ||
768                   targetPutMethod.getName().equals("setInitializer") ||
769                   targetPutMethod.getName().equals("setSuperclass") ||
770                   targetPutMethod.getName().equals("setExceptions"))
771             {
772               // Ignore if there is not substantial change.
773
//
774
Object JavaDoc oldValue = sourceGetMethod.invoke(targetNode, noArguments);
775               if (value == null ? oldValue == null : value.equals(oldValue))
776               {
777                 continue;
778               }
779               else if (targetPutMethod.getName().equals("setSuperclass"))
780               {
781                 if (oldValue != null && value != null && ((String JavaDoc)oldValue).trim().equals(((String JavaDoc)value).trim()))
782                 {
783                   continue;
784                 }
785               }
786
787               // The block pattern needs to prevent merging of the return type, to allow changing from the modeled data
788
// type (Bugzilla 102209).
789
//
790
if (sourceGetMethod.getName().equals("getReturnType") &&
791                   jControlModel.getBlockPattern() != null &&
792                   ((IDOMMethod)targetNode).getComment() != null &&
793                   jControlModel.getBlockPattern().matcher(((IDOMMethod)targetNode).getComment()).find())
794               {
795                 continue;
796               }
797
798               targetPutMethod.invoke(targetNode, new Object JavaDoc [] { value });
799               if (targetPutMethod.getName().equals("setBody") && sourceNode instanceof IDOMMethod)
800               {
801                 IDOMMethod sourceMethod = (IDOMMethod)sourceNode;
802                 IDOMMethod targetMethod = (IDOMMethod)targetNode;
803                 String JavaDoc [] sourceParameterNames = sourceMethod.getParameterNames();
804                 String JavaDoc [] targetParameterTypes = targetMethod.getParameterTypes();
805                 targetMethod.setParameters(targetParameterTypes, sourceParameterNames);
806               }
807             }
808           }
809           else
810           {
811             ArrayList JavaDoc additionalStrings = new ArrayList JavaDoc();
812             String JavaDoc [] sourceStrings = (String JavaDoc [])value;
813             if (sourceStrings != null)
814             {
815               additionalStrings.addAll(Arrays.asList(sourceStrings));
816             }
817
818             if (targetPutMethod.getName().equals("addSuperInterface"))
819             {
820               Pattern JavaDoc sourceTransfer = pullRule.getSourceTransfer();
821               if (sourceTransfer != null)
822               {
823                 String JavaDoc comment = ((IDOMMember)targetNode).getComment();
824                 Matcher JavaDoc matcher = sourceTransfer.matcher(comment);
825                 while (matcher.find() && matcher.groupCount() >= 1)
826                 {
827                   String JavaDoc clientStrings =
828                     comment.substring(matcher.start(matcher.groupCount()), matcher.end(matcher.groupCount()));
829   
830                   for (StringTokenizer JavaDoc stringTokenizer = new StringTokenizer JavaDoc(clientStrings, ", \t\n\r\f");
831                        stringTokenizer.hasMoreTokens(); )
832                   {
833                     String JavaDoc token = stringTokenizer.nextToken();
834                     if (!additionalStrings.contains(token))
835                     {
836                       additionalStrings.add(token);
837                     }
838                   }
839                 }
840               }
841
842               IDOMType type = (IDOMType)targetNode;
843               String JavaDoc [] superInterfaces = (String JavaDoc [])additionalStrings.toArray(new String JavaDoc [additionalStrings.size()]);
844               if (type.getSuperInterfaces() == null ?
845                    superInterfaces.length != 0 :
846                    !Arrays.equals(type.getSuperInterfaces(), superInterfaces))
847               {
848                 type.setSuperInterfaces((String JavaDoc [])additionalStrings.toArray(new String JavaDoc [additionalStrings.size()]));
849               }
850             }
851             else
852             {
853               String JavaDoc [] oldStringValues = (String JavaDoc [])sourceGetMethod.invoke(targetNode, noArguments);
854               List JavaDoc old = oldStringValues == null ? Collections.EMPTY_LIST : Arrays.asList(oldStringValues);
855               for (Iterator JavaDoc i = additionalStrings.iterator(); i.hasNext(); )
856               {
857                 String JavaDoc string = (String JavaDoc)i.next();
858                 if (!old.contains(string))
859                 {
860                   targetPutMethod.invoke(targetNode, new Object JavaDoc [] { string });
861                 }
862               }
863             }
864           }
865         }
866       }
867
868     }
869     catch (InvocationTargetException JavaDoc exception)
870     {
871       // exception.printStackTrace();
872
}
873     catch (IllegalAccessException JavaDoc exception)
874     {
875       // exception.printStackTrace();
876
}
877   }
878
879
880 ///////////////////////////////// PUSH /////////////////////////////////////
881

882   protected void pushSourceCompilationUnit()
883   {
884     for (IDOMNode child = sourceCompilationUnit.getFirstChild(); child != null; child = child.getNextNode())
885     {
886       switch (child.getNodeType())
887       {
888         case IDOMNode.PACKAGE:
889         {
890           pushSourcePackage((IDOMPackage)child);
891           break;
892         }
893         case IDOMNode.IMPORT:
894         {
895           pushSourceImport((IDOMImport)child);
896           break;
897         }
898         case IDOMNode.TYPE:
899         {
900           pushSourceType((IDOMType)child);
901           break;
902         }
903       }
904     }
905   }
906
907   protected void pushSourcePackage(IDOMPackage sourcePackage)
908   {
909     if (!sourceToTargetMap.containsKey(sourcePackage))
910     {
911       insertClone(sourcePackage);
912     }
913   }
914
915   protected void pushSourceImport(IDOMImport sourceImport)
916   {
917     if (!sourceToTargetMap.containsKey(sourceImport) && !targetPatternDictionary.isNoImport(sourceImport))
918     {
919       insertClone(sourceImport);
920     }
921   }
922
923   protected void pushSourceType(IDOMType sourceType)
924   {
925     if (!sourceToTargetMap.containsKey(sourceType))
926     {
927       insertClone(sourceType);
928     }
929     else
930     {
931       for (IDOMNode child = sourceType.getFirstChild(); child != null; child = child.getNextNode())
932       {
933         switch (child.getNodeType())
934         {
935           case IDOMNode.INITIALIZER:
936           {
937             pushSourceInitializer((IDOMInitializer)child);
938             break;
939           }
940           case IDOMNode.FIELD:
941           {
942             pushSourceField((IDOMField)child);
943             break;
944           }
945           case IDOMNode.METHOD:
946           {
947             pushSourceMethod((IDOMMethod)child);
948             break;
949           }
950           case IDOMNode.TYPE:
951           {
952             pushSourceType((IDOMType)child);
953             break;
954           }
955         }
956       }
957     }
958   }
959
960   protected void pushSourceInitializer(IDOMInitializer sourceInitializer)
961   {
962     if (!sourceToTargetMap.containsKey(sourceInitializer))
963     {
964       insertClone(sourceInitializer);
965     }
966   }
967
968   protected void pushSourceField(IDOMField sourceField)
969   {
970     applySortRules(sourceField);
971     if (!sourceToTargetMap.containsKey(sourceField))
972     {
973       insertClone(sourceField);
974     }
975   }
976
977   protected void pushSourceMethod(IDOMMethod sourceMethod)
978   {
979     if (!sourceToTargetMap.containsKey(sourceMethod))
980     {
981       insertClone(sourceMethod);
982     }
983   }
984
985   public void applySortRules(IDOMNode sourceNode)
986   {
987     LOOP:
988     for (Iterator JavaDoc sortRules = jControlModel.getSortRules().iterator(); sortRules.hasNext(); )
989     {
990       JControlModel.SortRule sortRule = (JControlModel.SortRule)sortRules.next();
991       if (sourcePatternDictionary.isMarkedUp(sortRule.getMarkup(), sourceNode) &&
992             sortRule.getSelector().isInstance(sourceNode))
993       {
994         IDOMNode parent = sourceNode.getParent();
995         List JavaDoc children = (List JavaDoc)orderedSourceChildrenMap.get(parent);
996         if (children == null)
997         {
998           children = new ArrayList JavaDoc();
999           orderedSourceChildrenMap.put(parent, children);
1000        }
1001        children.add(sourceNode);
1002        break;
1003      }
1004    }
1005  }
1006
1007
1008///////////////////////////////// SWEEP /////////////////////////////////////
1009

1010  protected void sweepTargetCompilationUnit()
1011  {
1012    for (Iterator JavaDoc entries = targetToSourceMap.entrySet().iterator(); entries.hasNext(); )
1013    {
1014      Map.Entry JavaDoc entry = (Map.Entry JavaDoc)entries.next();
1015      if (entry.getValue() == null)
1016      {
1017        applySweepRules((IDOMNode)entry.getKey());
1018      }
1019    }
1020  }
1021
1022  protected void applySweepRules(IDOMNode targetNode)
1023  {
1024    LOOP:
1025    for (Iterator JavaDoc sweepRules = jControlModel.getSweepRules().iterator(); sweepRules.hasNext(); )
1026    {
1027      JControlModel.SweepRule sweepRule = (JControlModel.SweepRule)sweepRules.next();
1028      if (sweepRule.getSelector() == IDOMImport.class && targetNode instanceof IDOMImport)
1029      {
1030        if (sweepRule.getMarkup().matcher(((IDOMNode)targetNode).getName()).find())
1031        {
1032          targetNode.remove();
1033          break;
1034        }
1035      }
1036      else if (targetPatternDictionary.isMarkedUp(sweepRule.getMarkup(), targetNode) &&
1037            sweepRule.getSelector().isInstance(targetNode))
1038      {
1039        targetNode.remove();
1040        break;
1041      }
1042    }
1043  }
1044
1045///////////////////////////////// SORT /////////////////////////////////////
1046

1047  protected void sortTargetCompilationUnit()
1048  {
1049    for (Iterator JavaDoc values = orderedSourceChildrenMap.values().iterator(); values.hasNext(); )
1050    {
1051      List JavaDoc children = (List JavaDoc)values.next();
1052      if (children.size() > 2)
1053      {
1054        Iterator JavaDoc i = children.iterator();
1055        IDOMNode sourceNode = (IDOMNode)i.next();
1056        IDOMNode previousTargetNode = (IDOMNode)sourceToTargetMap.get(sourceNode);
1057        do
1058        {
1059          sourceNode = (IDOMNode)i.next();
1060          IDOMNode nextTargetNode = (IDOMNode)sourceToTargetMap.get(sourceNode);
1061
1062          boolean reorder = true;
1063          for (IDOMNode domNode = nextTargetNode.getPreviousNode(); domNode != null; domNode = domNode.getPreviousNode())
1064          {
1065            if (domNode == previousTargetNode)
1066            {
1067              reorder = false;
1068              break;
1069            }
1070          }
1071
1072          if (reorder)
1073          {
1074            nextTargetNode.remove();
1075            if (previousTargetNode.getNextNode() == null)
1076            {
1077              previousTargetNode.getParent().addChild(nextTargetNode);
1078            }
1079            else
1080            {
1081              previousTargetNode.getNextNode().insertSibling(nextTargetNode);
1082            }
1083          }
1084
1085          previousTargetNode = nextTargetNode;
1086        }
1087        while (i.hasNext());
1088      }
1089    }
1090  }
1091
1092///////////////////////////////// CLONE AND MAP /////////////////////////////////////
1093

1094  protected IDOMNode insertClone(IDOMNode sourceNode)
1095  {
1096    IDOMNode targetNode = null;
1097    switch (sourceNode.getNodeType())
1098    {
1099      case IDOMNode.COMPILATION_UNIT:
1100      {
1101        targetNode =
1102          jdomFactory.createCompilationUnit
1103            (applyFormatRules(sourceNode.getContents()), ((IDOMCompilationUnit)sourceNode).getName());
1104        break;
1105      }
1106      case IDOMNode.PACKAGE:
1107      {
1108        targetNode = jdomFactory.createPackage(applyFormatRules(sourceNode.getContents()));
1109        break;
1110      }
1111      case IDOMNode.IMPORT:
1112      {
1113        targetNode = jdomFactory.createImport(applyFormatRules(sourceNode.getContents()));
1114        break;
1115      }
1116      case IDOMNode.TYPE:
1117      {
1118        targetNode = jdomFactory.createType(applyFormatRules(sourceNode.getContents()));
1119        break;
1120      }
1121      case IDOMNode.INITIALIZER:
1122      {
1123        targetNode = jdomFactory.createInitializer(applyFormatRules(sourceNode.getContents()));
1124        break;
1125      }
1126      case IDOMNode.FIELD:
1127      {
1128        targetNode = jdomFactory.createField(applyFormatRules(sourceNode.getContents()));
1129        break;
1130      }
1131      case IDOMNode.METHOD:
1132      {
1133        targetNode = jdomFactory.createMethod(applyFormatRules(sourceNode.getContents()));
1134        break;
1135      }
1136      default:
1137      {
1138        targetNode = (IDOMNode)sourceNode.clone();
1139        break;
1140      }
1141    }
1142
1143    if (targetNode != null)
1144    {
1145      map(sourceNode, targetNode);
1146      mapChildren(sourceNode, targetNode);
1147    }
1148    else
1149    {
1150      // System.err.println("Warning: Cannot clone '" + sourceNode.getContents() + "'");
1151
}
1152    for (IDOMNode previousNode = sourceNode.getPreviousNode(); previousNode != null; previousNode = previousNode.getPreviousNode())
1153    {
1154      IDOMNode targetSibling = (IDOMNode)sourceToTargetMap.get(previousNode);
1155      if (targetSibling != null)
1156      {
1157        IDOMNode targetNextSibling = targetSibling.getNextNode();
1158        if (targetNextSibling == null)
1159        {
1160          targetSibling.getParent().addChild(targetNode);
1161        }
1162        else
1163        {
1164          targetNextSibling.insertSibling(targetNode);
1165        }
1166
1167        return targetNode;
1168      }
1169    }
1170    if (sourceNode.getParent() != null)
1171    {
1172      IDOMNode targetParent = (IDOMNode)sourceToTargetMap.get(sourceNode.getParent());
1173      IDOMNode targetSibling = targetParent.getFirstChild();
1174      if (targetSibling == null)
1175      {
1176        targetParent.addChild(targetNode);
1177      }
1178      else
1179      {
1180        targetSibling.insertSibling(targetNode);
1181      }
1182    }
1183    return targetNode;
1184  }
1185
1186  protected void mapChildren(IDOMNode sourceNode, IDOMNode targetNode)
1187  {
1188    map(sourceNode, targetNode);
1189    for (IDOMNode sourceChild = sourceNode.getFirstChild(), targetChild = targetNode.getFirstChild();
1190         sourceChild != null;
1191         sourceChild = sourceChild.getNextNode(), targetChild = targetChild.getNextNode())
1192    {
1193      mapChildren(sourceChild, targetChild);
1194    }
1195  }
1196
1197  protected void map(IDOMNode sourceNode, IDOMNode targetNode)
1198  {
1199    if (sourceNode != null)
1200    {
1201      sourceToTargetMap.put(sourceNode, targetNode);
1202    }
1203    targetToSourceMap.put(targetNode, sourceNode);
1204  }
1205
1206///////////////////////////////// HEADLESS INVOCATION /////////////////////////////////////
1207

1208  /**
1209   * This is called with the command line arguments of a headless workbench invocation.
1210   */

1211  public Object JavaDoc run(Object JavaDoc object)
1212  {
1213    try
1214    {
1215      // Three arguments are expected: the .xml jControlModel URI, the source java URI, and the target java URI.
1216
//
1217
String JavaDoc contents = execute(new NullProgressMonitor(), (String JavaDoc[])object);
1218
1219      System.out.println("**********************************************");
1220      System.out.println(contents);
1221
1222      return new Integer JavaDoc(0);
1223    }
1224    catch (Exception JavaDoc exception)
1225    {
1226      // exception.printStackTrace();
1227
return new Integer JavaDoc(1);
1228    }
1229  }
1230  
1231  /**
1232   * Utilitiy for headless operations.
1233   *
1234   * @param mergeXML
1235   * @param sourceURI
1236   * @param targetURI
1237   * @return the merged content
1238   * @since 2.1.0
1239   */

1240  public String JavaDoc execute(IProgressMonitor progressMonitor, String JavaDoc[] arguments)
1241  {
1242    String JavaDoc mergeXML = arguments[0];
1243    String JavaDoc sourceURI = arguments[1];
1244    String JavaDoc targetURI = arguments[2];
1245    
1246    // Create the options model.
1247
//
1248
jControlModel = new JControlModel(mergeXML);
1249
1250    // Create the source and target JDOMs.
1251
//
1252
sourceCompilationUnit = createCompilationUnitForURI(sourceURI);
1253    targetCompilationUnit = createCompilationUnitForURI(targetURI);
1254
1255    // Create a pattern dictionary for each.
1256
//
1257
sourcePatternDictionary = new JPatternDictionary(sourceCompilationUnit, jControlModel);
1258    targetPatternDictionary = new JPatternDictionary(targetCompilationUnit, jControlModel);
1259    
1260    merge();
1261    
1262    return targetCompilationUnit.getContents();
1263  }
1264}
1265
Popular Tags