📄 javasrcmodeldigester.java
字号:
/*
* Copyright (c) 2003-2004, Alexander Greif
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Flow4J-Eclipse project nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.orthanc.flow4j.model.codegen.javasrc;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import net.orthanc.flow4j.Flow4JException;
import net.orthanc.flow4j.base.IOUtils;
import net.orthanc.flow4j.base.PrettyPrinterUtils;
import net.orthanc.flow4j.base.Util;
import net.orthanc.flow4j.bsf.BSFEngineDescriptor;
import net.orthanc.flow4j.bsf.Flow4JBSFManager;
import net.orthanc.flow4j.model.FlowStructureModelDigester;
import net.orthanc.flow4j.model.IFlowVisitor;
import net.orthanc.flow4j.model.bind.BindingHandler;
import net.orthanc.flow4j.model.bind.CallFlowletBind;
import net.orthanc.flow4j.model.bind.DecisionFlowletBind;
import net.orthanc.flow4j.model.bind.EndFlowletBind;
import net.orthanc.flow4j.model.bind.FlowModelBind;
import net.orthanc.flow4j.model.bind.IFlowletBind;
import net.orthanc.flow4j.model.bind.IPropertyHolderBind;
import net.orthanc.flow4j.model.bind.JavaTaskFlowletBind;
import net.orthanc.flow4j.model.bind.JoinFlowletBind;
import net.orthanc.flow4j.model.bind.JumpFlowletBind;
import net.orthanc.flow4j.model.bind.PropertyBind;
import net.orthanc.flow4j.model.bind.ScriptTaskFlowletBind;
import net.orthanc.flow4j.model.bind.StartFlowletBind;
import net.orthanc.flow4j.model.bind.TemplateFlowletBind;
import net.orthanc.flow4j.model.codegen.javasrc.structure.CatchBlock;
import net.orthanc.flow4j.model.codegen.javasrc.structure.CodeBlock;
import net.orthanc.flow4j.model.codegen.javasrc.structure.Field;
import net.orthanc.flow4j.model.codegen.javasrc.structure.IfThenElse;
import net.orthanc.flow4j.model.codegen.javasrc.structure.JavaFile;
import net.orthanc.flow4j.model.codegen.javasrc.structure.JavadocBlock;
import net.orthanc.flow4j.model.codegen.javasrc.structure.Method;
import net.orthanc.flow4j.model.codegen.javasrc.structure.MethodParameter;
import net.orthanc.flow4j.model.codegen.javasrc.structure.TryCatch;
import net.orthanc.flow4j.model.codegen.structure.CodeLine;
import net.orthanc.flow4j.runtime.Flow4JRuntimeConsts;
import net.orthanc.flow4j.runtime.ITaskFlowlet;
import net.orthanc.flow4j.runtime.descriptors.TaskParameterDescriptor;
import net.orthanc.flow4j.runtime.descriptors.TaskParameterDescriptors;
import net.orthanc.flow4j.runtime.descriptors.TaskPropertyDescriptor;
import net.orthanc.flow4j.runtime.descriptors.TaskPropertyDescriptors;
import org.acm.seguin.util.FileSettings;
/**
* @author greifa
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class JavaSrcModelDigester extends FlowStructureModelDigester {
public static final String PRETTY_SETTINGS_FILENAME = "pretty.settings";
private static final String FLOW4J_XDOCLET_PREFIX = "flow4j.";
private static FileSettings prettySettings;
private File scriptRootFolder;
private JavaFile javaFile;
private FlowModelBind flowModelBind;
private ClassLoader taskClassLoader;
//private String flowName;
private boolean bsfNeeded;
//private Set scriptLanguageNames;
private static DecisionStatementCompletion decisionStmntCompl
= new DecisionStatementCompletion();
/**
* Crates this Digester and also a JavaClass instance
* @param className the name of the class
* @param packageName the package name or null if the default package
*/
private JavaSrcModelDigester(String className, String packageName, File scriptRootFolder) {
super();
javaFile = new JavaFile();
javaFile.getJavaClass().setClassName(className);
javaFile.setPackageName(packageName);
javaFile.addImport("net.orthanc.flow4j.runtime.*");
javaFile.getJavaClass().setJavadoc(new JavadocBlock());
this.scriptRootFolder = scriptRootFolder;
}
/**
* Loads the pretty printer settings.
* If the specified file is <code>null</code> then nothing happens.
* @param settingsFile
*/
static public void setPrettySettings(FileSettings prettySettings) {
JavaSrcModelDigester.prettySettings = prettySettings;
}
/**
* Used by the FlowRepository builder
* @return
*/
public static FileSettings getPrettySettings() {
return prettySettings;
}
/**
* Generates the flow's java source code and stores it in the output file
* @param flowFile
* @param packagePath
* @param destDir
* @param scriptRootFolder
* @throws IOException
* @throws MappingException
* @throws MarshalException
* @throws ValidationException
*/
public static void generateCode(File flowFile, String packagePath, File destDir, File scriptRootFolder)
throws IOException {
// generate java surce code
InputStream javaSrcIn = generateCode(flowFile, packagePath, scriptRootFolder);
File outputFolder = new File(destDir, packagePath.replace('.', File.separatorChar));
String fileName = flowFile.getName();
fileName = fileName.substring(0, fileName.lastIndexOf(".")+1) + Consts.FILE_EXTENSION_JAVA;
File outputFile = new File(outputFolder, fileName);
OutputStream javaSrcOut = new FileOutputStream(outputFile);
IOUtils.copyBufferedStream(javaSrcIn, javaSrcOut);
javaSrcIn.close();
javaSrcOut.close();
}
/**
* Returns a stream on the generated java source code.
* Creates an instancce of this class that builds the JavaClass object.
* Then the JavaClass object is serialized and a stream to the source
* code is returned
* @param flowFile
* @param packagePath
* @param scriptRootFolder
* @return a stream on the generated java source code.
* @throws IOException
* @throws MappingException
* @throws MarshalException
* @throws ValidationException
*/
private static InputStream generateCode(File flowFile, String packagePath, File scriptRootFolder)
throws IOException {
return generateCode(
flowFile,
packagePath,
scriptRootFolder,
new String().getClass().getClassLoader());
}
/**
* Returns a stream on the generated java source code.
* Creates an instancce of this class that builds the JavaClass object.
* Then the JavaClass object is serialized and a stream to the source
* code is returned
* @param flowFile
* @param packagePath
* @param taskClassLoader
* @return a stream on the generated java source code.
* @throws IOException
* @throws MappingException
* @throws MarshalException
* @throws ValidationException
*/
public static InputStream generateCode(
File flowFile,
String packagePath,
File scriptRootFolder,
ClassLoader taskClassLoader)
throws IOException {
String fileName = flowFile.getName();
String className = fileName.substring(0, fileName.lastIndexOf("."));
FlowModelBind flowModelBind = BindingHandler.getInstance().loadFlowModel(flowFile, taskClassLoader);
JavaSrcModelDigester digester =
new JavaSrcModelDigester(className, packagePath, scriptRootFolder);
digester.taskClassLoader = taskClassLoader;
// digest all parts of the flow model
digester.digest(flowModelBind);
// generate the java class
digester.generateClassSrc(flowModelBind);
// serialize sources
StringWriter stringWriter = new StringWriter();
BufferedWriter writer = new BufferedWriter(stringWriter);
digester.serialize(writer);
writer.close();
String source = stringWriter.toString();
// pretty print sources
try {
if (prettySettings != null)
source = PrettyPrinterUtils.prettyPrintSource(source);
} catch(Throwable e) {
e.printStackTrace();
}
return new ByteArrayInputStream(source.getBytes());
}
/**
* Generates the class's source, all fields and methods.
*/
public void generateClassSrc(FlowModelBind flowModelBind) {
javaFile.getJavaClass().addModifier(Consts.MODIFIER_PUBLIC);
javaFile.getJavaClass().addModifier(Consts.MODIFIER_FINAL);
javaFile.getJavaClass().addInterface("IFlow");
// generate getStartFlowlets() method and the corresponding code
generateGetStartFlowletsBlock(flowModelBind);
// generate execute() method
generateExecuteMethodSrc(flowModelBind);
// generate the class's javadoc
generateClassJavadoc();
// generate BSF Manager
//generateBSFComponents();
}
private void generateGetStartFlowletsBlock(FlowModelBind flowModelBind) {
String startFlowletsVarName = "startFlowlets";
Field startFlowletsField = new Field(startFlowletsVarName);
startFlowletsField.addModifier(Consts.MODIFIER_PRIVATE);
startFlowletsField.addModifier(Consts.MODIFIER_STATIC);
startFlowletsField.setType("StartFlowlet[]");
startFlowletsField.setValue("new StartFlowlet[" + getStartFlowletNodes().size() + "]");
javaFile.getJavaClass().addField(startFlowletsField);
CodeBlock staticInitializer = javaFile.getJavaClass().getStaticInitializer();
// visit all start flowlets
int counter = 0;
for (Iterator iter = getStartFlowletNodes().iterator(); iter.hasNext(); counter++) {
IFlowNode startFlowletNode = (IFlowNode)iter.next();
StartFlowletBind flowletBind = (StartFlowletBind)((AbstractFlowletNode)startFlowletNode).getFlowletBind();
String labelText = flowletBind.getLabel().getText();
String variableName = flowletBind.getId(flowModelBind) + "_" + labelText;
staticInitializer.addFragment(new CodeLine("StartFlowlet " + variableName + " = new StartFlowlet(\"" + labelText + "\");"));
staticInitializer.addFragment(new CodeLine(startFlowletsVarName + "[" + counter + "] = " + variableName + ";"));
// here comes the code that adds properties
generatePropertySetterCalls(flowletBind, staticInitializer, variableName);
}
// the interfaces getter method
Method getStartFlowletsMethod = new Method("getStartFlowlets");
javaFile.getJavaClass().addMethod(getStartFlowletsMethod);
getStartFlowletsMethod.addModifier(Consts.MODIFIER_PUBLIC);
getStartFlowletsMethod.addModifier(Consts.MODIFIER_FINAL);
getStartFlowletsMethod.setReturnType("StartFlowlet[]");
getStartFlowletsMethod.addToCodeBlock(new CodeLine("return " + startFlowletsVarName + ";"));
}
/**
* Generates the source code of the flow's <code>execute()</code> method
*/
private void generateExecuteMethodSrc(FlowModelBind flowModelBind) {
Method executeMethod = new Method("execute");
executeMethod.addModifier(Consts.MODIFIER_PUBLIC);
executeMethod.addModifier(Consts.MODIFIER_FINAL);
executeMethod.addMethodParameter(new MethodParameter("String", "startFlowletName"));
executeMethod.addMethodParameter(new MethodParameter("FlowDictionary", "dictionary"));
javaFile.getJavaClass().addMethod(executeMethod);
IFlowVisitor visitor = new JavaSrcVisitor(executeMethod.getCodeBlock());
// visit all start flowlets
for (Iterator iter = getStartFlowletNodes().iterator(); iter.hasNext();) {
IFlowNode startFlowletNode = (IFlowNode)iter.next();
IfThenElse ifThenElse = new IfThenElse();
((JavaSrcVisitor)visitor).getCodeBlock().addFragment(ifThenElse);
StartFlowletBind flowletBind = (StartFlowletBind)((AbstractFlowletNode)startFlowletNode).getFlowletBind();
String labelText = flowletBind.getLabel().getText();
String methodName = flowletBind.getId(flowModelBind) + "_" + labelText;
ifThenElse.setBooleanStatement("\"" + labelText + "\".equals(startFlowletName)");
ifThenElse.addTrueFragment(new CodeLine("\t" + methodName + "(dictionary);"));
((JavaSrcVisitor)visitor).setCodeBlock(ifThenElse.getTrueBlock());
// visit others
startFlowletNode.visit(visitor);
((JavaSrcVisitor)visitor).setCodeBlock(ifThenElse.getFalseBlock());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -