View | Details | Raw Unified | Return to bug 128620
Collapse All | Expand All

(-)src/org/eclipse/gmf/codegen/util/Messages.java (-7 lines)
Lines 17-27 Link Here
17
17
18
	public static String initproject;
18
	public static String initproject;
19
19
20
	public static String merge;
21
22
	public static String interrupted;
23
24
	public static String unexpected;
25
26
	public static String problems; 
27
}
20
}
(-)src/org/eclipse/gmf/codegen/util/Generator.java (-310 / +95 lines)
Lines 13-43 Link Here
13
13
14
import java.io.ByteArrayInputStream;
14
import java.io.ByteArrayInputStream;
15
import java.lang.ref.SoftReference;
15
import java.lang.ref.SoftReference;
16
import java.net.URL;
16
import java.util.Collection;
17
import java.util.Collection;
17
import java.util.Collections;
18
import java.util.Collections;
18
import java.util.HashMap;
19
import java.util.HashMap;
19
import java.util.Iterator;
20
import java.util.Iterator;
20
import java.util.LinkedList;
21
import java.util.List;
21
import java.util.List;
22
import java.util.Map;
22
import java.util.Map;
23
23
24
import org.eclipse.core.resources.IFile;
24
import org.eclipse.core.resources.IFile;
25
import org.eclipse.core.resources.IProject;
26
import org.eclipse.core.resources.IResource;
25
import org.eclipse.core.resources.IResource;
27
import org.eclipse.core.resources.ResourcesPlugin;
28
import org.eclipse.core.runtime.CoreException;
26
import org.eclipse.core.runtime.CoreException;
29
import org.eclipse.core.runtime.IPath;
27
import org.eclipse.core.runtime.IPath;
30
import org.eclipse.core.runtime.IProgressMonitor;
28
import org.eclipse.core.runtime.IProgressMonitor;
31
import org.eclipse.core.runtime.IStatus;
32
import org.eclipse.core.runtime.MultiStatus;
33
import org.eclipse.core.runtime.NullProgressMonitor;
34
import org.eclipse.core.runtime.Path;
29
import org.eclipse.core.runtime.Path;
35
import org.eclipse.core.runtime.Status;
36
import org.eclipse.core.runtime.SubProgressMonitor;
30
import org.eclipse.core.runtime.SubProgressMonitor;
37
import org.eclipse.emf.codegen.jet.JETEmitter;
38
import org.eclipse.emf.codegen.jet.JETException;
31
import org.eclipse.emf.codegen.jet.JETException;
39
import org.eclipse.emf.codegen.jmerge.JControlModel;
40
import org.eclipse.emf.codegen.jmerge.JMerger;
41
import org.eclipse.emf.codegen.util.CodeGenUtil;
32
import org.eclipse.emf.codegen.util.CodeGenUtil;
42
import org.eclipse.emf.common.util.URI;
33
import org.eclipse.emf.common.util.URI;
43
import org.eclipse.gmf.codegen.gmfgen.GenChildContainer;
34
import org.eclipse.gmf.codegen.gmfgen.GenChildContainer;
Lines 54-96 Link Here
54
import org.eclipse.gmf.codegen.gmfgen.GenNodeLabel;
45
import org.eclipse.gmf.codegen.gmfgen.GenNodeLabel;
55
import org.eclipse.gmf.codegen.gmfgen.GenTopLevelNode;
46
import org.eclipse.gmf.codegen.gmfgen.GenTopLevelNode;
56
import org.eclipse.gmf.common.UnexpectedBehaviourException;
47
import org.eclipse.gmf.common.UnexpectedBehaviourException;
57
import org.eclipse.gmf.common.codegen.ImportUtil;
48
import org.eclipse.gmf.common.codegen.GeneratorBase;
58
import org.eclipse.jdt.core.ICompilationUnit;
59
import org.eclipse.jdt.core.IPackageFragment;
60
import org.eclipse.jdt.core.IPackageFragmentRoot;
61
import org.eclipse.jdt.core.JavaCore;
62
import org.eclipse.jdt.core.JavaModelException;
63
import org.eclipse.jdt.core.ToolFactory;
64
import org.eclipse.jdt.core.formatter.CodeFormatter;
65
import org.eclipse.jface.text.Document;
66
import org.eclipse.jface.text.IDocument;
67
import org.eclipse.text.edits.TextEdit;
68
49
69
/**
50
/**
70
 * Invokes JET templates to populate diagram editor project.
51
 * Invokes JET templates to populate diagram editor project.
71
 * 
52
 * 
72
 * @author artem
53
 * @author artem
73
 */
54
 */
74
public class Generator implements Runnable {
55
public class Generator extends GeneratorBase implements Runnable {
75
56
76
	private final GenEditorGenerator myEditorGen; 
57
	private final GenEditorGenerator myEditorGen; 
77
58
78
	private final GenDiagram myDiagram;
59
	private final GenDiagram myDiagram;
79
60
80
	// myDestRoot.getJavaProject().getElementName() == myDestProject.getName()
81
	private IPackageFragmentRoot myDestRoot;
82
83
	private IProject myDestProject;
84
85
	private JControlModel myJControlModel;
86
87
	private CodeFormatter myCodeFormatter;
88
89
	private IProgressMonitor myProgress;
90
91
	private IStatus myRunStatus = Status.CANCEL_STATUS;
92
	private List/*<IStatus>*/ myExceptions;
93
94
	private CodegenEmitters myEmitters;
61
	private CodegenEmitters myEmitters;
95
62
96
	private static Map/*<URI, SoftReference>*/ myCachedURI2EmitterMap = new HashMap();
63
	private static Map/*<URI, SoftReference>*/ myCachedURI2EmitterMap = new HashMap();
Lines 119-250 Link Here
119
			myEmitters = old;
86
			myEmitters = old;
120
		}
87
		}
121
	}
88
	}
122
89
	
123
	public void run(IProgressMonitor progress) throws InterruptedException {
90
	protected URL getJMergeControlFile() {
124
		setProgressMonitor(progress);
91
		return myEmitters.getJMergeControlFile();
125
		doRun();
126
	}
127
128
	public void run() {
129
		try {
130
			doRun();
131
		} catch (InterruptedException ex) {
132
			myRunStatus = new Status(IStatus.CANCEL, "org.eclipse.gmf.codegen", 0, Messages.interrupted, ex);
133
		}
134
	}
92
	}
135
93
	
136
	private void doRun() throws InterruptedException {
94
	protected void customRun() throws InterruptedException, JETException, UnexpectedBehaviourException {
137
		try {
95
		initializeEditorProject(myDiagram.getEditorGen().getPlugin().getID(), createReferencedProjectsList());
138
			setupProgressMonitor();
96
		// commands
139
			myExceptions = new LinkedList/*<IStatus>*/();
97
		generateReorientConnectionViewCommand();
140
			initializeEditorProject();
98
141
99
		// edit parts, edit policies and providers
142
			// commands
100
		generateSemanticHints();
143
			generateReorientConnectionViewCommand();
101
		generateAbstractParser();
144
102
		generateStructuralFeatureParser();
145
			// edit parts, edit policies and providers
103
		generateStructuralFeaturesParser();
146
			generateSemanticHints();
104
		generateBaseItemSemanticEditPolicy();
147
			generateAbstractParser();
105
		generateBaseGraphicalNodeEditPolicy();
148
			generateStructuralFeatureParser();
106
		generateReferenceConnectionEditPolicy();
149
			generateStructuralFeaturesParser();
107
		generateDiagramCanonicalEditPolicy();
150
			generateBaseItemSemanticEditPolicy();
108
		generateDiagramItemSemanticEditPolicy();
151
			generateBaseGraphicalNodeEditPolicy();
109
		for (Iterator nodes = myDiagram.getTopLevelNodes().iterator(); nodes.hasNext();) {
152
			generateReferenceConnectionEditPolicy();
110
			GenTopLevelNode node = (GenTopLevelNode) nodes.next();
153
			generateDiagramCanonicalEditPolicy();
111
			generateNode(node);
154
			generateDiagramItemSemanticEditPolicy();
112
		}
155
			for (Iterator nodes = myDiagram.getTopLevelNodes().iterator(); nodes.hasNext();) {
113
		for (Iterator nodes = myDiagram.getChildNodes().iterator(); nodes.hasNext();) {
156
				GenTopLevelNode node = (GenTopLevelNode) nodes.next();
114
			GenChildNode node = (GenChildNode) nodes.next();
157
				generateNode(node);
115
			if (node.isListContainerEntry()) {
158
			}
116
				generateListContainerNode(node);
159
			for (Iterator nodes = myDiagram.getChildNodes().iterator(); nodes.hasNext();) {
160
				GenChildNode node = (GenChildNode) nodes.next();
161
				if (node.isListContainerEntry()) {
162
					generateListContainerNode(node);
163
				} else {
164
					generateNode(node);
165
				}
166
			}
167
			for (Iterator compartments = myDiagram.getCompartments().iterator(); compartments.hasNext();) {
168
				GenCompartment compartment = (GenCompartment) compartments.next();
169
				generateCompartment(compartment);
170
			}
171
			for (Iterator it = myDiagram.getLinks().iterator(); it.hasNext();) {
172
				final GenLink next = (GenLink) it.next();
173
				generateViewFactory(next);
174
				generateLinkEditPart(next);
175
				generateLinkItemSemanticEditPolicy(next);
176
				for (Iterator labels = next.getLabels().iterator(); labels.hasNext();) {
177
					GenLinkLabel label = (GenLinkLabel) labels.next();
178
					generateLinkLabelEditPart(label);
179
					generateLinkLabelTextEditPart(label);
180
					generateLinkLabelViewFactory(label);
181
					generateLinkLabelTextViewFactory(label);
182
				}
183
			}
184
			generateViewFactory(myDiagram);
185
			generateDiagramEditPart();
186
			generateDiagramExternalNodeLabelEditPart();
187
			generateEditPartFactory();
188
			generateElementTypes();
189
			generateViewProvider();
190
			generateEditPartProvider();
191
			generatePaletteProvider();
192
			generateModelingAssistantProvider();
193
			generatePropertyProvider();
194
			generateIconProvider();
195
			generateParserProvider();
196
			if(myDiagram.isValidationEnabled()) {
197
				generateValidationProvider();
198
				generateMarkerNavigationProvider();				
199
			}
200
201
			// editor
202
			generateInitDiagramFileAction();
203
			generatePalette();
204
			generateDiagramEditorUtil();
205
			generateDiagramFileCreator();
206
			generateVisualIDRegistry();
207
			generateCreationWizard();
208
			generateCreationWizardPage();
209
			generateEditor();
210
			generateCreateShortcutAction();
211
			generateLoadResourceAction();
212
			generateElementChooser();
213
			generateDocumentProvider();
214
			generateActionBarContributor();
215
			generateMatchingStrategy();
216
			generatePreferencesInitializer();
217
			generatePluginClass();
218
			generateBundleManifest();
219
			generatePluginProperties();
220
			generatePluginXml();
221
			generateBuildProperties();
222
			generateShortcutIcon();
223
224
			if (myExceptions.isEmpty()) {
225
				myRunStatus = Status.OK_STATUS;
226
			} else {
117
			} else {
227
				IStatus[] s = (IStatus[]) myExceptions.toArray(new IStatus[myExceptions.size()]);
118
				generateNode(node);
228
				myRunStatus = new MultiStatus("org.eclipse.gmf.codegen", 0, s, Messages.problems, null);
229
			}
119
			}
230
		} catch (NullPointerException ex) {
231
			myRunStatus = new Status(IStatus.ERROR, "org.eclipse.gmf.codegen", 0, NullPointerException.class.getName(), ex);
232
		} catch (JETException ex) {
233
			myRunStatus = ex.getStatus();
234
		} catch (UnexpectedBehaviourException ex) {
235
			myRunStatus = new Status(Status.ERROR, "org.eclipse.gmf.codegen", 0, Messages.unexpected, ex);
236
		} finally {
237
			myProgress.done();
238
			myExceptions = null;
239
		}
120
		}
240
	}
121
		for (Iterator compartments = myDiagram.getCompartments().iterator(); compartments.hasNext();) {
241
122
			GenCompartment compartment = (GenCompartment) compartments.next();
242
	/**
123
			generateCompartment(compartment);
243
	 * Provides information about success/failures during {@link #run()}
124
		}
244
	 * @return state of the generator run, or CANCEL if generator was not yet run.
125
		for (Iterator it = myDiagram.getLinks().iterator(); it.hasNext();) {
245
	 */
126
			final GenLink next = (GenLink) it.next();
246
	public IStatus getRunStatus() {
127
			generateViewFactory(next);
247
		return myRunStatus;
128
			generateLinkEditPart(next);
129
			generateLinkItemSemanticEditPolicy(next);
130
			for (Iterator labels = next.getLabels().iterator(); labels.hasNext();) {
131
				GenLinkLabel label = (GenLinkLabel) labels.next();
132
				generateLinkLabelEditPart(label);
133
				generateLinkLabelTextEditPart(label);
134
				generateLinkLabelViewFactory(label);
135
				generateLinkLabelTextViewFactory(label);
136
			}
137
		}
138
		generateViewFactory(myDiagram);
139
		generateDiagramEditPart();
140
		generateDiagramExternalNodeLabelEditPart();
141
		generateEditPartFactory();
142
		generateElementTypes();
143
		generateViewProvider();
144
		generateEditPartProvider();
145
		generatePaletteProvider();
146
		generateModelingAssistantProvider();
147
		generatePropertyProvider();
148
		generateIconProvider();
149
		generateParserProvider();
150
		if(myDiagram.isValidationEnabled()) {
151
			generateValidationProvider();
152
			generateMarkerNavigationProvider();				
153
		}
154
155
		// editor
156
		generateInitDiagramFileAction();
157
		generatePalette();
158
		generateDiagramEditorUtil();
159
		generateDiagramFileCreator();
160
		generateVisualIDRegistry();
161
		generateCreationWizard();
162
		generateCreationWizardPage();
163
		generateEditor();
164
		generateCreateShortcutAction();
165
		generateLoadResourceAction();
166
		generateElementChooser();
167
		generateDocumentProvider();
168
		generateActionBarContributor();
169
		generateMatchingStrategy();
170
		generatePreferencesInitializer();
171
		generatePluginClass();
172
		generateBundleManifest();
173
		generatePluginProperties();
174
		generatePluginXml();
175
		generateBuildProperties();
176
		generateShortcutIcon();
248
	}
177
	}
249
178
250
	private void generateNode(GenNode node) throws JETException, InterruptedException {
179
	private void generateNode(GenNode node) throws JETException, InterruptedException {
Lines 855-863 Link Here
855
		IProgressMonitor pm = getNextStepMonitor();
784
		IProgressMonitor pm = getNextStepMonitor();
856
		try {
785
		try {
857
			pm.beginTask(iconPath.lastSegment(), 3);
786
			pm.beginTask(iconPath.lastSegment(), 3);
858
			IPath containerPath = myDestProject.getFullPath().append(iconPath.removeLastSegments(1));
787
			IPath containerPath = getDestProject().getFullPath().append(iconPath.removeLastSegments(1));
859
			CodeGenUtil.findOrCreateContainer(containerPath, false, (IPath) null, new SubProgressMonitor(pm, 1));
788
			CodeGenUtil.findOrCreateContainer(containerPath, false, (IPath) null, new SubProgressMonitor(pm, 1));
860
			IFile f = myDestProject.getFile(iconPath);
789
			IFile f = getDestProject().getFile(iconPath);
861
			if (f.exists()) {
790
			if (f.exists()) {
862
				f.setContents(new ByteArrayInputStream(myEmitters.getShortcutImageEmitter().generateGif()), true, true, new SubProgressMonitor(pm, 1));
791
				f.setContents(new ByteArrayInputStream(myEmitters.getShortcutImageEmitter().generateGif()), true, true, new SubProgressMonitor(pm, 1));
863
			} else {
792
			} else {
Lines 865-1034 Link Here
865
			}
794
			}
866
			f.getParent().refreshLocal(IResource.DEPTH_ONE, new SubProgressMonitor(pm, 1));
795
			f.getParent().refreshLocal(IResource.DEPTH_ONE, new SubProgressMonitor(pm, 1));
867
		} catch (CoreException ex) {
796
		} catch (CoreException ex) {
868
			myExceptions.add(ex.getStatus());
797
			handleException(ex);
869
		} finally {
870
			pm.done();
871
		}
872
873
	}
874
	
875
	/**
876
	 * Generate ordinary file. No merge is performed at the moment.
877
	 * @param emitter template to use
878
	 * @param filePath - project-relative path to file, e.g. META-INF/MANIFEST.MF
879
	 * @param param TODO
880
	 * @throws JETException
881
	 * @throws InterruptedException
882
	 */
883
	private void doGenerateFile(JETEmitter emitter, IPath filePath, Object param) throws JETException, InterruptedException {
884
		assert !myDestProject.getName().equals(filePath.segment(0));
885
		IProgressMonitor pm = getNextStepMonitor();
886
		try {
887
			pm.beginTask(filePath.lastSegment(), 4);
888
			IPath containerPath = myDestProject.getFullPath().append(filePath.removeLastSegments(1));
889
			CodeGenUtil.findOrCreateContainer(containerPath, false, (IPath) null, new SubProgressMonitor(pm, 1));
890
			String genText = emitter.generate(new SubProgressMonitor(pm, 1), new Object[] { param });
891
			IFile f = myDestProject.getFile(filePath);
892
			// FIXME merge!
893
			if (f.exists()) {
894
				f.setContents(new ByteArrayInputStream(genText.getBytes()), true, true, new SubProgressMonitor(pm, 1));
895
			} else {
896
				f.create(new ByteArrayInputStream(genText.getBytes()), true, new SubProgressMonitor(pm, 1));
897
			}
898
			f.getParent().refreshLocal(IResource.DEPTH_ONE, new SubProgressMonitor(pm, 1));
899
		} catch (CoreException ex) {
900
			myExceptions.add(ex.getStatus());
901
		} finally {
798
		} finally {
902
			pm.done();
799
			pm.done();
903
		}
800
		}
904
	}
801
	}
905
802
906
	/**
803
	protected void setupProgressMonitor() {
907
	 * Optionally, specify progressMonitor to use. Should be called prior to {@link #run()}
908
	 * @param progress
909
	 */
910
	public void setProgressMonitor(IProgressMonitor progress) {
911
		myProgress = progress;
912
	}
913
914
	private void setupProgressMonitor() {
915
		if (myProgress == null) {
916
			myProgress = new NullProgressMonitor();
917
			return;
918
			// no need to set it up
919
		}
920
		Counter c = new Counter(myDiagram);
804
		Counter c = new Counter(myDiagram);
921
		c.setAdditionalOperations(8); // init, palette, editor, plugin.xml, etc
805
		c.setAdditionalOperations(8); // init, palette, editor, plugin.xml, etc
922
		c.setOperationsPerNode(2);
806
		c.setOperationsPerNode(2);
923
		c.setOperationsPerListContainerNode(1);
807
		c.setOperationsPerListContainerNode(1);
924
		c.setOperationsPerLink(2);
808
		c.setOperationsPerLink(2);
925
		myProgress.beginTask(Messages.start, c.getTotal());
809
		setupProgressMonitor(Messages.start, c.getTotal());
926
	}
927
928
	private IProgressMonitor getNextStepMonitor() throws InterruptedException {
929
		if (myProgress.isCanceled()) {
930
			throw new InterruptedException();
931
		}
932
		return new SubProgressMonitor(myProgress, 1);
933
	}
810
	}
934
811
	
935
	private void initializeEditorProject() throws UnexpectedBehaviourException, InterruptedException {
812
	
936
		myDestProject = ResourcesPlugin.getWorkspace().getRoot().getProject(myDiagram.getEditorGen().getPlugin().getID());
813
	protected final List createReferencedProjectsList() {
937
		final Path srcPath = new Path('/' + myDestProject.getName() + "/src"); //$NON-NLS-1$
938
		final Path projectLocation = null; // use default
939
		final List referencedProjects = createReferencedProjectsList();
940
		final int style = org.eclipse.emf.codegen.ecore.Generator.EMF_PLUGIN_PROJECT_STYLE;
941
		// pluginVariables is NOT used when style is EMF_PLUGIN_PROJECT_STYLE
942
		final List pluginVariables = null;
943
		final IProgressMonitor pm = getNextStepMonitor();
944
945
		org.eclipse.emf.codegen.ecore.Generator.createEMFProject(srcPath, projectLocation, referencedProjects, pm, style, pluginVariables);
946
947
		try {
948
			myDestRoot = JavaCore.create(myDestProject).findPackageFragmentRoot(srcPath);
949
		} catch (JavaModelException ex) {
950
			throw new UnexpectedBehaviourException(ex.getMessage());
951
		}
952
		if (myDestRoot == null) {
953
			throw new UnexpectedBehaviourException("no source root can be found");
954
		}
955
	}
956
957
	private List createReferencedProjectsList() {
958
		return Collections.EMPTY_LIST;
814
		return Collections.EMPTY_LIST;
959
	}
815
	}
960
816
961
	/**
962
	 * NOTE: potential problem - packageName and className should match those specified in 
963
	 * the template. Besides, getQualifiedXXX helpers in diagram GenModel should also correctly
964
	 * return qualified class names.  
965
	 */
966
	private void doGenerateJavaClass(JETEmitter emitter, String packageName, String className, Object input) throws InterruptedException {
967
		IProgressMonitor pm = getNextStepMonitor();
968
		try {
969
			pm.beginTask(className, 4);
970
			final Object emitterArg = new Object[] {input, new ImportUtil(packageName)};
971
			String genText = emitter.generate(new SubProgressMonitor(pm, 1), new Object[] { emitterArg });
972
			IPackageFragment pf = myDestRoot.createPackageFragment(packageName, true, new SubProgressMonitor(pm, 1));
973
			ICompilationUnit cu = pf.getCompilationUnit(className + ".java"); //$NON-NLS-1$
974
			if (cu.exists()) {
975
				genText = merge(genText, cu.getSource(), new SubProgressMonitor(pm, 1));
976
			} else {
977
				pm.worked(1);
978
			}
979
			pf.createCompilationUnit(cu.getElementName(), formatCode(genText), true, new SubProgressMonitor(pm, 1));
980
		} catch (NullPointerException ex) {
981
			myExceptions.add(new Status(IStatus.ERROR, "org.eclipse.gmf.codegen", 0, ex.getMessage(), ex));
982
		} catch (JETException ex) {
983
			myExceptions.add(ex.getStatus());
984
		} catch (CoreException ex) {
985
			myExceptions.add(ex.getStatus());		
986
		} finally {
987
			pm.done();
988
		}
989
	}
990
991
	private String merge(String generatedText, String oldContents, IProgressMonitor pm) {
992
		pm.beginTask(Messages.merge, 1);
993
		JMerger jMerge = new JMerger();
994
		jMerge.setControlModel(getJControlModel());
995
		jMerge.setSourceCompilationUnit(jMerge.createCompilationUnitForContents(generatedText));
996
		jMerge.setTargetCompilationUnit(jMerge.createCompilationUnitForContents(oldContents));
997
		jMerge.merge();
998
		pm.done();
999
		return jMerge.getTargetCompilationUnitContents();
1000
	}
1001
1002
	private String formatCode(String text) {
1003
		IDocument doc = new Document(text);
1004
		TextEdit edit = getCodeFormatter().format(CodeFormatter.K_COMPILATION_UNIT, doc.get(), 0, doc.get().length(), 0, null);
1005
1006
		try {
1007
			// check if text formatted successfully 
1008
			if(edit != null) {
1009
				edit.apply(doc);
1010
				text = doc.get();				
1011
			}		
1012
		} catch (Exception ex) {
1013
			ex.printStackTrace();
1014
		}
1015
		return text;
1016
	}
1017
1018
	private CodeFormatter getCodeFormatter() {
1019
		if (myCodeFormatter == null) {
1020
			myCodeFormatter = ToolFactory.createCodeFormatter(null);
1021
		}
1022
		return myCodeFormatter;
1023
	}
1024
1025
	private JControlModel getJControlModel() {
1026
		if (myJControlModel == null) {
1027
			myJControlModel = new JControlModel(myEmitters.getJMergeControlFile().toString());
1028
		}
1029
		return myJControlModel;
1030
	}
1031
1032
	private static final class Counter {
817
	private static final class Counter {
1033
		private final GenDiagram myDiagram;
818
		private final GenDiagram myDiagram;
1034
		private int myOpsPerNode = 1;
819
		private int myOpsPerNode = 1;
(-)src/org/eclipse/gmf/codegen/util/messages.properties (-4 lines)
Lines 1-7 Link Here
1
start=Generation in progress...
1
start=Generation in progress...
2
initproject=Creating target plugin
2
initproject=Creating target plugin
3
merge=Merging contents...
4
3
5
interrupted=Code generation was interrupted.
6
unexpected=Unexpected state came across, have no idea how to deal with that
7
problems=Problems while generating code
(-)META-INF/MANIFEST.MF (-1 / +4 lines)
Lines 9-13 Link Here
9
 org.eclipse.gmf.internal.codegen.dispatch;x-friends:="org.eclipse.gmf.codegen,org.eclipse.gmf.graphdef.codegen"
9
 org.eclipse.gmf.internal.codegen.dispatch;x-friends:="org.eclipse.gmf.codegen,org.eclipse.gmf.graphdef.codegen"
10
Require-Bundle: org.eclipse.core.runtime,
10
Require-Bundle: org.eclipse.core.runtime,
11
 org.eclipse.emf.codegen,
11
 org.eclipse.emf.codegen,
12
 org.eclipse.emf.codegen.ecore
12
 org.eclipse.emf.codegen.ecore,
13
 org.eclipse.core.resources,
14
 org.eclipse.jdt.core,
15
 org.eclipse.jface.text
13
Bundle-Vendor: %providerName
16
Bundle-Vendor: %providerName
(-)src/org/eclipse/gmf/common/codegen/GeneratorBase.java (+341 lines)
Added Link Here
1
package org.eclipse.gmf.common.codegen;
2
3
import java.io.ByteArrayInputStream;
4
import java.net.URL;
5
import java.util.LinkedList;
6
import java.util.List;
7
8
import javax.xml.parsers.DocumentBuilderFactory;
9
import javax.xml.parsers.ParserConfigurationException;
10
11
import org.eclipse.core.resources.IFile;
12
import org.eclipse.core.resources.IProject;
13
import org.eclipse.core.resources.IResource;
14
import org.eclipse.core.resources.ResourcesPlugin;
15
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.IPath;
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.core.runtime.MultiStatus;
20
import org.eclipse.core.runtime.NullProgressMonitor;
21
import org.eclipse.core.runtime.Path;
22
import org.eclipse.core.runtime.Status;
23
import org.eclipse.core.runtime.SubProgressMonitor;
24
import org.eclipse.emf.codegen.jet.JETEmitter;
25
import org.eclipse.emf.codegen.jet.JETException;
26
import org.eclipse.emf.codegen.jmerge.JControlModel;
27
import org.eclipse.emf.codegen.jmerge.JMerger;
28
import org.eclipse.emf.codegen.util.CodeGenUtil;
29
import org.eclipse.gmf.common.UnexpectedBehaviourException;
30
import org.eclipse.jdt.core.ICompilationUnit;
31
import org.eclipse.jdt.core.IPackageFragment;
32
import org.eclipse.jdt.core.IPackageFragmentRoot;
33
import org.eclipse.jdt.core.JavaCore;
34
import org.eclipse.jdt.core.JavaModelException;
35
import org.eclipse.jdt.core.ToolFactory;
36
import org.eclipse.jdt.core.formatter.CodeFormatter;
37
import org.eclipse.jface.text.Document;
38
import org.eclipse.jface.text.IDocument;
39
import org.eclipse.text.edits.TextEdit;
40
import org.w3c.dom.Element;
41
42
public abstract class GeneratorBase implements Runnable {
43
	private JControlModel myJControlModel;
44
	private CodeFormatter myCodeFormatter;
45
	private IProgressMonitor myProgress = new NullProgressMonitor();
46
47
	// myDestRoot.getJavaProject().getElementName() == myDestProject.getName()
48
	private IPackageFragmentRoot myDestRoot;
49
	private IProject myDestProject;
50
	private final List/*<IStatus>*/ myExceptions;
51
	private IStatus myRunStatus = Status.CANCEL_STATUS;
52
53
	protected abstract URL getJMergeControlFile();
54
	
55
	protected abstract void customRun() throws InterruptedException, JETException, UnexpectedBehaviourException;
56
	
57
	protected abstract void setupProgressMonitor();
58
		
59
	public static interface Emitter {
60
		public String generate(IProgressMonitor monitor, Object arguments) throws JETException ;
61
	}
62
	
63
	public GeneratorBase(){
64
		myExceptions = new LinkedList/*<IStatus>*/();
65
	}
66
	
67
	public void run(IProgressMonitor progress) throws InterruptedException {
68
		setProgressMonitor(progress);
69
		doRun();
70
	}
71
	
72
	public void run() {
73
		clearExceptionsList();
74
		try {
75
			doRun();
76
		} catch (InterruptedException ex) {
77
			myRunStatus = new Status(IStatus.CANCEL, "org.eclipse.gmf.codegen", 0, GeneratorBaseMessages.interrupted, ex);
78
		}
79
	}
80
	
81
	/**
82
	 * Provides information about success/failures during {@link #run()}
83
	 * @return state of the generator run, or CANCEL if generator was not yet run.
84
	 */
85
	public IStatus getRunStatus() {
86
		return myRunStatus;
87
	}
88
89
	/**
90
	 * Optionally, specify progressMonitor to use. Should be called prior to {@link #run()}
91
	 * @param progress
92
	 */
93
	public void setProgressMonitor(IProgressMonitor progress) {
94
		myProgress = progress;
95
	}
96
97
	protected final void handleException(CoreException ex){
98
		handleException(ex.getStatus());
99
	}
100
	
101
	protected final void handleException(UnexpectedBehaviourException e){
102
		
103
	}
104
	
105
	protected final void handleException(IStatus status){
106
		myExceptions.add(status);
107
	}
108
	
109
	protected final IProject getDestProject() {
110
		return myDestProject;
111
	}
112
	
113
	protected final IProgressMonitor getProgress() {
114
		return myProgress;
115
	}
116
	
117
	protected final void setupProgressMonitor(String task, int total) {
118
		if (myProgress == null) {
119
			myProgress = new NullProgressMonitor();
120
			return;
121
			// no need to set it up
122
		}
123
		myProgress.beginTask(task, total);
124
	}
125
	
126
	protected final IProgressMonitor getNextStepMonitor() throws InterruptedException {
127
		if (myProgress.isCanceled()) {
128
			throw new InterruptedException();
129
		}
130
		return new SubProgressMonitor(myProgress, 1);
131
	}
132
	
133
	protected final void initializeEditorProject(String pluginId, List referencedProjects) throws UnexpectedBehaviourException, InterruptedException {
134
		myDestProject = ResourcesPlugin.getWorkspace().getRoot().getProject(pluginId);
135
		final Path srcPath = new Path('/' + myDestProject.getName() + "/src"); //$NON-NLS-1$
136
		final Path projectLocation = null; // use default
137
		final int style = org.eclipse.emf.codegen.ecore.Generator.EMF_PLUGIN_PROJECT_STYLE;
138
		// pluginVariables is NOT used when style is EMF_PLUGIN_PROJECT_STYLE
139
		final List pluginVariables = null;
140
		final IProgressMonitor pm = getNextStepMonitor();
141
142
		org.eclipse.emf.codegen.ecore.Generator.createEMFProject(srcPath, projectLocation, referencedProjects, pm, style, pluginVariables);
143
144
		try {
145
			myDestRoot = JavaCore.create(myDestProject).findPackageFragmentRoot(srcPath);
146
		} catch (JavaModelException ex) {
147
			throw new UnexpectedBehaviourException(ex.getMessage());
148
		}
149
		if (myDestRoot == null) {
150
			throw new UnexpectedBehaviourException("no source root can be found");
151
		}
152
	}
153
	
154
	protected final void doGenerateFile(JETEmitter emitter, IPath filePath, Object param) throws JETException, InterruptedException {
155
		doGenerateFile(new JetAdapter(emitter), filePath, param);
156
	}
157
	
158
	/**
159
	 * Generate ordinary file. No merge is performed at the moment.
160
	 * @param emitter template to use
161
	 * @param filePath - project-relative path to file, e.g. META-INF/MANIFEST.MF
162
	 * @param param TODO
163
	 * @throws JETException
164
	 * @throws InterruptedException
165
	 */
166
	protected final void doGenerateFile(Emitter emitter, IPath filePath, Object param) throws JETException, InterruptedException {
167
		assert !myDestProject.getName().equals(filePath.segment(0));
168
		IProgressMonitor pm = getNextStepMonitor();
169
		try {
170
			pm.beginTask(filePath.lastSegment(), 4);
171
			IPath containerPath = myDestProject.getFullPath().append(filePath.removeLastSegments(1));
172
			CodeGenUtil.findOrCreateContainer(containerPath, false, (IPath) null, new SubProgressMonitor(pm, 1));
173
			String genText = emitter.generate(new SubProgressMonitor(pm, 1), param);
174
			IFile f = myDestProject.getFile(filePath);
175
			// FIXME merge!
176
			if (f.exists()) {
177
				f.setContents(new ByteArrayInputStream(genText.getBytes()), true, true, new SubProgressMonitor(pm, 1));
178
			} else {
179
				f.create(new ByteArrayInputStream(genText.getBytes()), true, new SubProgressMonitor(pm, 1));
180
			}
181
			f.getParent().refreshLocal(IResource.DEPTH_ONE, new SubProgressMonitor(pm, 1));
182
		} catch (CoreException ex) {
183
			handleException(ex);
184
		} finally {
185
			pm.done();
186
		}
187
	}
188
	
189
	/**
190
	 * NOTE: potential problem - packageName and className should match those specified in 
191
	 * the template. Besides, getQualifiedXXX helpers in diagram GenModel should also correctly
192
	 * return qualified class names.  
193
	 */
194
	protected final void doGenerateJavaClass(JETEmitter emitter, String packageName, String className, Object input) throws InterruptedException {
195
		doGenerateJavaClass(new JetAdapter(emitter, packageName), packageName, className, input);
196
	}
197
	
198
	/**
199
	 * NOTE: potential problem - packageName and className should match those specified in 
200
	 * the template. Besides, getQualifiedXXX helpers in diagram GenModel should also correctly
201
	 * return qualified class names.  
202
	 */
203
	protected final void doGenerateJavaClass(Emitter emitter, String packageName, String className, Object input) throws InterruptedException {
204
		IProgressMonitor pm = getNextStepMonitor();
205
		try {
206
			pm.beginTask(className, 4);
207
			String genText = emitter.generate(new SubProgressMonitor(pm, 1), input);
208
			IPackageFragment pf = myDestRoot.createPackageFragment(packageName, true, new SubProgressMonitor(pm, 1));
209
			ICompilationUnit cu = pf.getCompilationUnit(className + ".java"); //$NON-NLS-1$
210
			if (cu.exists()) {
211
				genText = merge(genText, cu.getSource(), new SubProgressMonitor(pm, 1));
212
			} else {
213
				pm.worked(1);
214
			}
215
			pf.createCompilationUnit(cu.getElementName(), formatCode(genText), true, new SubProgressMonitor(pm, 1));
216
		} catch (NullPointerException ex) {
217
			handleException(new Status(IStatus.ERROR, "org.eclipse.gmf.codegen", 0, ex.getMessage(), ex));
218
		} catch (JETException ex) {
219
			handleException(ex.getStatus());
220
		} catch (CoreException ex) {
221
			handleException(ex);		
222
		} finally {
223
			pm.done();
224
		}
225
	}
226
227
	protected final String merge(String generatedText, String oldContents, IProgressMonitor pm) {
228
		pm.beginTask(GeneratorBaseMessages.merge, 1);
229
		JMerger jMerge = new JMerger();
230
		jMerge.setControlModel(getJControlModel());
231
		jMerge.setSourceCompilationUnit(jMerge.createCompilationUnitForContents(generatedText));
232
		jMerge.setTargetCompilationUnit(jMerge.createCompilationUnitForContents(oldContents));
233
		jMerge.merge();
234
		pm.done();
235
		return jMerge.getTargetCompilationUnitContents();
236
	}
237
238
	protected final String formatCode(String text) {
239
		IDocument doc = new Document(text);
240
		TextEdit edit = getCodeFormatter().format(CodeFormatter.K_COMPILATION_UNIT, doc.get(), 0, doc.get().length(), 0, null);
241
242
		try {
243
			// check if text formatted successfully 
244
			if(edit != null) {
245
				edit.apply(doc);
246
				text = doc.get();				
247
			}		
248
		} catch (Exception ex) {
249
			ex.printStackTrace();
250
		}
251
		return text;
252
	}
253
254
	private void doRun() throws InterruptedException {
255
		try {
256
			setupProgressMonitor();
257
			customRun();
258
			myRunStatus = getExceptionsStatus();
259
		} catch (NullPointerException ex) {
260
			myRunStatus = new Status(IStatus.ERROR, "org.eclipse.gmf.codegen", 0, NullPointerException.class.getName(), ex);
261
		} catch (JETException ex) {
262
			myRunStatus = ex.getStatus();
263
		} catch (UnexpectedBehaviourException ex) {
264
			myRunStatus = new Status(Status.ERROR, "org.eclipse.gmf.codegen", 0, GeneratorBaseMessages.unexpected, ex);
265
		} finally {
266
			getProgress().done();
267
			clearExceptionsList();
268
		}
269
	}
270
271
	private JControlModel getJControlModel() {
272
		if (myJControlModel == null) {
273
			URL controlFile = getJMergeControlFile();
274
			myJControlModel = controlFile == null ? createEmptyJControlModel() : new JControlModel(controlFile.toString());
275
		}
276
		return myJControlModel;
277
	}
278
279
	private JControlModel createEmptyJControlModel() {
280
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
281
		org.w3c.dom.Document document;
282
		try {
283
			document = factory.newDocumentBuilder().newDocument();
284
		} catch (ParserConfigurationException e) {
285
			throw new RuntimeException("Can not initialize DOM", e);
286
		}
287
		Element root = (Element)document.appendChild(document.createElement("fake"));
288
		return new JControlModel(root);
289
	}
290
291
	private CodeFormatter getCodeFormatter() {
292
		if (myCodeFormatter == null) {
293
			myCodeFormatter = ToolFactory.createCodeFormatter(null);
294
		}
295
		return myCodeFormatter;
296
	}
297
	
298
	private final void clearExceptionsList(){
299
		myExceptions.clear();
300
	}
301
	
302
	private final IStatus getExceptionsStatus(){
303
		if (myExceptions == null || myExceptions.isEmpty()){
304
			return Status.OK_STATUS;
305
		} else {
306
			IStatus[] s = (IStatus[]) myExceptions.toArray(new IStatus[myExceptions.size()]);
307
			return new MultiStatus("org.eclipse.gmf.codegen", 0, s, GeneratorBaseMessages.problems, null);
308
		}
309
	}
310
311
	private static class JetAdapter implements Emitter {
312
		private final JETEmitter myEmitter;
313
		private final ImportAssistant myImportAssistant;
314
315
		public JetAdapter(JETEmitter emitter, ImportAssistant importAssistant){
316
			myEmitter = emitter;
317
			myImportAssistant = importAssistant;
318
		}
319
		
320
		public JetAdapter(JETEmitter emitter){
321
			this(emitter, (ImportAssistant)null);
322
		}
323
		
324
		public JetAdapter(JETEmitter emitter, String packageName){
325
			this(emitter, new ImportUtil(packageName));
326
		}
327
		
328
		public String generate(IProgressMonitor monitor, Object param) throws JETException {
329
			Object[] jetArgs = shouldAddImports() ? 
330
					new Object[] {new Object[] {param, myImportAssistant}} :
331
					new Object[] {param};
332
			return myEmitter.generate(monitor, jetArgs);
333
		}
334
335
		private boolean shouldAddImports() {
336
			return myImportAssistant != null;
337
		}
338
	}
339
340
	
341
}
(-)src/org/eclipse/gmf/common/codegen/GeneratorBaseMessages.java (+27 lines)
Added Link Here
1
package org.eclipse.gmf.common.codegen;
2
3
import org.eclipse.osgi.util.NLS;
4
5
public class GeneratorBaseMessages extends NLS {
6
	private static final String BUNDLE_NAME = "org.eclipse.gmf.codegen.util.messages"; //$NON-NLS-1$
7
8
	private GeneratorBaseMessages() {
9
	}
10
11
	static {
12
		// initialize resource bundle
13
		NLS.initializeMessages(BUNDLE_NAME, GeneratorBaseMessages.class);
14
	}
15
16
//	public static String start;
17
//
18
//	public static String initproject;
19
20
	public static String merge;
21
22
	public static String interrupted;
23
24
	public static String unexpected;
25
26
	public static String problems; 
27
}
(-)src/org/eclipse/gmf/common/codegen/generatorBaseMessages.properties (+4 lines)
Added Link Here
1
interrupted=Code generation was interrupted.
2
merge=Merging contents...
3
unexpected=Unexpected state came across, have no idea how to deal with that
4
problems=Problems while generating code

Return to bug 128620