⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 .#flowrepositorybuilder.java.1.3

📁 一个java写的business process management系统
💻 3
字号:
/*
 * Copyright (c) 2003, 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.designer.builder;

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.orthanc.flow4j.base.PrettyPrinterUtils;
import net.orthanc.flow4j.designer.Flow4JDesignerException;
import net.orthanc.flow4j.designer.core.Flow4JPlugin;
import net.orthanc.flow4j.designer.core.Flow4JProject;
import net.orthanc.flow4j.model.codegen.javasrc.Consts;
import net.orthanc.flow4j.model.codegen.javasrc.structure.JavaClass;
import net.orthanc.flow4j.model.codegen.javasrc.structure.JavaFile;
import net.orthanc.flow4j.model.codegen.javasrc.structure.Method;
import net.orthanc.flow4j.model.codegen.structure.CodeLine;

import org.acm.seguin.util.FileSettings;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;

/**
 * Builds the class that implements <code>IFlowRepository</code> and
 * contains the code to register all flows in the project.
 * @author agreif
 */
public class FlowRepositoryBuilder extends IncrementalProjectBuilder {

	/**
	 * Always returns <code>null</code>
	 * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
		throws CoreException {
		try {
			monitor.subTask("Build flow repository");
			IProject project = getProject();
			if (!isBuildableProject(project))
				return null;

			Flow4JProject flow4jProject =
				Flow4JPlugin.getFlow4JProject(project);
			String flowRepositoryClasspath =
				flow4jProject.getFlowReposClassPath();
			FileDesc packageFolderDesc;
			try {
				//	get the folder where the class file should be stored
				packageFolderDesc =
					getSourceFolder(project, flowRepositoryClasspath);
				if (packageFolderDesc == null)
					return null;
			} catch (Flow4JDesignerException e) {
				throw e;
			} catch (Exception e) {
				Flow4JPlugin.log(e);
				return null;
			}

			List flowClassPaths = new ArrayList();
			//	collect the paths of the project's flow files
			getFlowClassPaths(project, flowClassPaths);
			try {
				//	generate source file
				buildFlowRepository(
				//folder.getProjectRelativePath().append(
				//	getClassName(flowRepositoryClasspath)),
				packageFolderDesc,
					getPackagePath(flowRepositoryClasspath).replace('/', '.'),
					getClassName(flowRepositoryClasspath),
					flowClassPaths,
					monitor);
			} catch (Exception e) {
				Flow4JPlugin.log(e);
			}
		} finally {
			monitor.done();
		}

		return null;
	}

	/**
	 * Returns the folder in which the FlowRepsoitory class should
	 * be stored.
	 * If the package of the class exists in one of the project's source folders
	 * then the package folder is returned.
	 * Otherwise the package folder in the project's <strong>first</strong>
	 * source folder is returned.
	 * @param project the project
	 * @param flowRepositoryClasspath the fully qualified class path of the Flow repository class
	 * @return the folder in which the FlowRepsoitory class should be stored.
	 * @throws JavaModelException
	 * @throws CoreException
	 * @throws Flow4JDesignerException
	 */
	private FileDesc getSourceFolder(
		IProject project,
		String flowRepositoryClasspath)
		throws JavaModelException, CoreException, Flow4JDesignerException {

		if (flowRepositoryClasspath == null
			|| flowRepositoryClasspath.trim().length() == 0)
			throw new Flow4JDesignerException("No flow repository class path specified");

		IPath[] sourceFolderPaths =
			Flow4JPlugin.getClasspathSourceFolders(project);
		if (sourceFolderPaths == null || sourceFolderPaths.length == 0)
			return null;

		int pos = flowRepositoryClasspath.lastIndexOf(".");
		if (pos == -1)
			return new FileDesc(
				Flow4JPlugin.getWorkspaceRoot().getFolder(sourceFolderPaths[0]),
				null);

		IJavaProject javaProject = Flow4JPlugin.getJavaProject(project);

		IPath packagePath = new Path(getPackagePath(flowRepositoryClasspath));
		for (int i = 0; i < sourceFolderPaths.length; i++) {
			IPath path = sourceFolderPaths[i].append(packagePath);
			IFolder folder = Flow4JPlugin.getWorkspaceRoot().getFolder(path);
			if (folder.exists())
				return new FileDesc(
					Flow4JPlugin.getWorkspaceRoot().getFolder(
						sourceFolderPaths[i]),
					packagePath);
		}

		return new FileDesc(
			Flow4JPlugin.getWorkspaceRoot().getFolder(sourceFolderPaths[0]),
			packagePath);
	}

	private String getPackagePath(String classpath) {
		int pos = classpath.lastIndexOf(".");
		if (pos == -1)
			return "";
		return classpath.substring(0, pos).replace('.', '/');
	}

	private String getClassName(String classpath) {
		int pos = classpath.lastIndexOf(".");
		if (pos == -1)
			return classpath;
		return classpath.substring(pos + 1);
	}

	/**
	 * Collects the <code>IPath</code> objects of the flow files in the given project.
	 * @param project the folder in which to look for flow files
	 * @param flowClassNames the container to collect the paths objects to
	 */
	private void getFlowClassPaths(IProject project, List flowClassPaths)
		throws JavaModelException {
		IPath[] sourceFolderPaths =
			Flow4JPlugin.getClasspathSourceFolders(project);
		List list = new ArrayList();
		for (int i = 0; i < sourceFolderPaths.length; i++) {
			IPath folderPath = sourceFolderPaths[i];
			IFolder folder =
				Flow4JPlugin.getWorkspaceRoot().getFolder(folderPath);
			if (folder.exists())
				getFlowClassPaths(folder, list);
			//	strip
			for (Iterator iter = list.iterator(); iter.hasNext();) {
				IPath path = (IPath) iter.next();
				path = path.removeFirstSegments(folderPath.segmentCount() - 1);
				flowClassPaths.add(path);
			}
			list.clear();
		}
	}

	/**
	 * Collects the <code>IPath</code> objects of the flow files in the given folder.
	 * Recurses into subfolders
	 * @param folder the folder in which to look for flow files
	 * @param flowClassNames the container to collect the paths objects to
	 */
	private void getFlowClassPaths(IFolder folder, List flowClassPaths) {
		try {
			IResource[] members = folder.members();
			for (int i = 0; i < members.length; i++) {
				IResource resource = members[i];
				if (resource.getType() == IResource.FILE
					&& Flow4JPlugin.isFlowFile((IFile) resource)) {
					flowClassPaths.add(
						((IFile) resource)
							.getFullPath()
							.removeFirstSegments(1)
							.removeTrailingSeparator()
							.removeFileExtension());
				} else if (resource.getType() == IResource.FOLDER) {
					getFlowClassPaths((IFolder) resource, flowClassPaths);
				}
			}
		} catch (CoreException e) {
			Flow4JPlugin.log(e);
		}
	}

	/**
	 * Creates the flow repository java source file in the given output path.
	 * The file name begins with the project name and ends with "FlowRepository".
	 * @param outputPath	the path where the sources should be written
	 * @param packageName	the name of the package
	 * @param className		the name of the class
	 * @param flowClassPaths	the <code>IPath</code> objects of the flows
	 * @param monitor		the progress monitor
	 * @throws IOException	if the file cannot be written
	 * @throws CoreException	
	 */
	private void buildFlowRepository(
	//IPath outputPath,
	FileDesc packageFolderDesc,
		String packageName,
		String className,
		List flowClassPaths,
		IProgressMonitor monitor)
		throws IOException, CoreException {
		JavaFile repositoryFile = new JavaFile();
		JavaClass repositoryClass = repositoryFile.getJavaClass();
		repositoryClass.setClassName(className);
		repositoryFile.setPackageName(packageName);
		repositoryClass.addInterface(
			"net.orthanc.flow4j.runtime.IFlowRepository");
		repositoryClass.addModifier(Consts.MODIFIER_PUBLIC);
		Method method = new Method("getFlowClasses");
		repositoryClass.addMethod(method);
		method.setReturnType("java.util.Collection");
		method.addModifier(Consts.MODIFIER_PUBLIC);
		method.addToCodeBlock(
			new CodeLine("java.util.List classes = new java.util.ArrayList();"));

		for (Iterator iter = flowClassPaths.iterator(); iter.hasNext();) {
			IPath flowClassPath = (IPath) iter.next();
			String classpathStr = flowClassPath.toString().replace('/', '.');
			method.addToCodeBlock(
				new CodeLine("classes.add(" + classpathStr + ".class);"));
		}
		method.addToCodeBlock(new CodeLine("return classes;"));
		//	serialize
		StringWriter stringWriter = new StringWriter();
		BufferedWriter writer = new BufferedWriter(stringWriter);
		repositoryFile.serialize(writer);
		writer.close();
		String source = stringWriter.toString();
		//	pretty printer
		FileSettings prettySettings = Flow4JPlugin.getPrettySettings();
		if (prettySettings != null)
			try {
				source = PrettyPrinterUtils.prettyPrintSource(source);
			} catch (Exception e) {
				Flow4JPlugin.log(e);
			}

		InputStream in = new ByteArrayInputStream(source.getBytes());

		//		IFile outputFile =
		//			getProject().getFile(outputPath.addFileExtension("java"));
		try {
			IFolder packageFolder = packageFolderDesc.getFolder();
			if (!packageFolder.exists())
				//	derived=true, means that resource is recreatable by build process
				//	and should not go into source control because the resource will change often
				Flow4JPlugin.createFolder(
					packageFolderDesc.getRoot(),
					packageFolderDesc.getPath(),
					false);
			IFile outputFile =
				packageFolder.getFile(
					new Path(className).addFileExtension("java"));
			if (!outputFile.exists()) {
				outputFile.create(in, true, monitor);
				outputFile.setDerived(true);
			}
			else
				outputFile.setContents(in, true, true, monitor);
		} finally {
			try {
				if (in != null)
					in.close();
			} catch (IOException e1) {
				Flow4JPlugin.log(e1);
			}
		}
	}

	/**
	 * Returns whether the project is buildable by the FlowBuilder.
	 * @param project
	 * @return true if the FlowBuilder can build the given project
	 */
	static boolean isBuildableProject(IProject project) {
		if (Flow4JPlugin.hasFlow4JNature(project))
			return true;

		return false;
	}

	private class FileDesc {
		IContainer root;
		IPath path;

		FileDesc(IContainer root, IPath path) {
			this.root = root;
			this.path = path;
		}
		/**
		 * @return
		 */
		public IPath getPath() {
			return path;
		}

		/**
		 * @return
		 */
		public IContainer getRoot() {
			return root;
		}

		public IFolder getFolder() {
			return root.getFolder(path);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -