/*
* Copyright (c) 2006, 2008 Borland Software Corporation
*
* 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:
* Michael Golubev (Borland) - initial API and implementation
*/
package org.eclipse.gmf.graphdef.codegen;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.codegen.merge.java.JControlModel;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.gmf.common.UnexpectedBehaviourException;
import org.eclipse.gmf.gmfgraph.FigureDescriptor;
import org.eclipse.gmf.internal.common.codegen.DefaultTextMerger;
import org.eclipse.gmf.internal.common.codegen.GeneratorBase;
import org.eclipse.gmf.internal.common.codegen.ImportUtil;
import org.eclipse.gmf.internal.common.codegen.TextEmitter;
import org.eclipse.gmf.internal.common.codegen.TextMerger;
/**
* FIXME move to internal package as it's not necessary to expose this class to public
*/
public class StandaloneGenerator extends GeneratorBase {
protected final Config myArgs;
private final TextEmitter myFigureGenerator;
private final StandaloneEmitters myAuxiliaryGenerators;
private boolean mySkipPluginStructire;
protected Processor myProcessor;
private final Map<String, FigureDescriptor> myCallbackFigures = new LinkedHashMap<String, FigureDescriptor>();
public interface Config {
public String getPluginID();
public String getPluginFriendlyName();
public String getPluginProviderName();
public String getMainPackageName();
public String getPluginActivatorClassName();
public String getPluginActivatorPackageName();
public MapModeCodeGenStrategy getMapMode();
public String getRuntimeToken();
}
public static class ConfigImpl implements Config {
private final String myPluginId;
private final String myMainPackageName;
private final String myPluginFriendlyName;
private final String myPluginProviderName;
private final String myPluginActivatorClassName;
private final String myPluginActivatorPackageName;
private final MapModeCodeGenStrategy myMapMode;
private final String myRuntimeToken;
public ConfigImpl(String pluginId, String mainPackageName){
this(pluginId, mainPackageName, MapModeCodeGenStrategy.DYNAMIC, null);
}
public ConfigImpl(String pluginId, String mainPackageName, MapModeCodeGenStrategy mapMode, String runtimeToken) {
this(pluginId, mainPackageName, pluginId, "", "PluginActivator", (mainPackageName == null ? "" : mainPackageName + ".") + "activator", mapMode, runtimeToken);
}
public ConfigImpl(String pluginId, String mainPackageName, String pluginFriendlyName, String pluginProviderName, String pluginActivatorClassName, String pluginActivatorPackageName, MapModeCodeGenStrategy mapMode, String runtimeToken){
myPluginId = pluginId;
myMainPackageName = mainPackageName == null ? "" : mainPackageName;
myPluginFriendlyName = pluginFriendlyName;
myPluginProviderName = pluginProviderName;
myPluginActivatorClassName = pluginActivatorClassName;
myPluginActivatorPackageName = pluginActivatorPackageName;
myMapMode = mapMode;
myRuntimeToken = runtimeToken;
}
public String getMainPackageName() {
return myMainPackageName;
}
public String getPluginFriendlyName() {
return myPluginFriendlyName;
}
public String getPluginID() {
return myPluginId;
}
public String getPluginProviderName() {
return myPluginProviderName;
}
public String getPluginActivatorClassName() {
return myPluginActivatorClassName;
}
public String getPluginActivatorPackageName() {
return myPluginActivatorPackageName;
}
public MapModeCodeGenStrategy getMapMode() {
return myMapMode;
}
public String getRuntimeToken() {
return myRuntimeToken;
}
}
public static abstract class Processor {
public abstract void go(ProcessorCallback callback, Config config) throws InterruptedException ;
public String[] getRequiredBundles() {
return new String[0];
}
}
public interface ProcessorCallback {
public String visitFigure(FigureDescriptor f) throws InterruptedException;
}
public StandaloneGenerator(Processor p, Config config) {
this(p, config, null);
}
public StandaloneGenerator(Processor p, Config config, URL[] dynamicTemplates) {
assert p != null && config != null;
myArgs = config;
myProcessor = p;
String pluginActivatorFQN = composePluginActivatorClassFQN(config);
final MapModeCodeGenStrategy strategy;
String accessor;
if (config.getMapMode() == MapModeCodeGenStrategy.DYNAMIC) {
strategy = MapModeCodeGenStrategy.DYNAMIC;
accessor = pluginActivatorFQN + ".getDefault().";
} else {
strategy = config.getMapMode() == null ? MapModeCodeGenStrategy.STATIC : config.getMapMode();
accessor = null;
}
myFigureGenerator = new FigureGenerator(config.getRuntimeToken(), getPackageName(), strategy, accessor, false, dynamicTemplates);
myAuxiliaryGenerators = new StandaloneEmitters(strategy, dynamicTemplates);
}
/**
* Allows clients to skip generating of manifest.mf, pligin and build properties files.
* "New-plugin-by-template" generator uses this feature because it delegates this generation to PDE defaults.
*/
public void setSkipPluginStructure(boolean skipManifest){
mySkipPluginStructire = skipManifest;
}
protected void setupProgressMonitor() {
//setupProgressMonitor("Generating GMFGraph plugin", 100);
}
@Override
protected TextMerger createMergeService() {
// jcontrol model that is not initialized can't merge, hence java merging won't happen
return new DefaultTextMerger(new JControlModel());
}
protected void customRun() throws InterruptedException, UnexpectedBehaviourException {
initializeEditorProject(myArgs.getPluginID(), null /*support only workspace project with figures*/);
if (!mySkipPluginStructire){
generatePluginStructure();
}
try {
generateTopLevelFigures();
generatePluginActivator();
} catch (IllegalStateException e){
throw new UnexpectedBehaviourException(e);
}
}
protected void generatePluginActivator() throws UnexpectedBehaviourException, InterruptedException{
Object[] args = new Object[] {myArgs, new ImportUtil(myArgs.getPluginActivatorPackageName(), myArgs.getPluginActivatorClassName()), new ArrayList<String>(myCallbackFigures.keySet())};
doGenerateJavaClass(myAuxiliaryGenerators.getPluginActivatorEmitter(), myArgs.getPluginActivatorPackageName(), myArgs.getPluginActivatorClassName(), args);
}
protected void generatePluginStructure() throws UnexpectedBehaviourException, InterruptedException {
doGenerateFile(myAuxiliaryGenerators.getBuildPropertiesEmitter(), new Path("build.properties"), myArgs);
doGenerateFile(myAuxiliaryGenerators.getManifestMFEmitter(), new Path("META-INF/MANIFEST.MF"), myArgs, myProcessor.getRequiredBundles());
doGenerateFile(myAuxiliaryGenerators.getPluginPropertiesEmitter(), new Path("plugin.properties"), myArgs);
}
private void generateTopLevelFigures() throws InterruptedException {
myCallbackFigures.clear(); // just in case
myProcessor.go(new ProcessorCallback() {
public String visitFigure(FigureDescriptor f) throws InterruptedException {
return StandaloneGenerator.this.visitFigure(f);
}
}, myArgs);
}
private String visitFigure(FigureDescriptor figureDescriptor) throws InterruptedException {
// XXX either use compilationUnitName from Util.ext or pass cu name as template argument
if (figureDescriptor.getName() == null) {
throw new IllegalArgumentException("FigureDescriptor needs a name");
}
final String compilationUnitName = CodeGenUtil.validJavaIdentifier(CodeGenUtil.capName(figureDescriptor.getName()));
doGenerateJavaClass(myFigureGenerator, getPackageName(), compilationUnitName, figureDescriptor);
final String qualifiedName = composeFQN(getPackageName(), compilationUnitName);
myCallbackFigures.put(qualifiedName, figureDescriptor);
return qualifiedName;
}
private String getPackageName(){
return myArgs.getMainPackageName();
}
private static String composePluginActivatorClassFQN(Config config) {
String packageName = config.getPluginActivatorPackageName();
String className = config.getPluginActivatorClassName();
return composeFQN(packageName, className);
}
private static String composeFQN(String packageName, String className){
return packageName == null || "".equals(packageName) ? className : packageName + "." + className;
}
}