All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.officefloor.eclipse.section.FunctionNamespaceItem Maven / Gradle / Ivy

/*
 * OfficeFloor - http://www.officefloor.net
 * Copyright (C) 2005-2018 Daniel Sagenschneider
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */
package net.officefloor.eclipse.section;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import net.officefloor.compile.OfficeFloorCompiler;
import net.officefloor.compile.managedfunction.FunctionNamespaceType;
import net.officefloor.compile.managedfunction.ManagedFunctionLoader;
import net.officefloor.compile.managedfunction.ManagedFunctionType;
import net.officefloor.compile.properties.PropertyList;
import net.officefloor.compile.spi.managedfunction.source.ManagedFunctionSource;
import net.officefloor.compile.spi.officefloor.DeployedOffice;
import net.officefloor.eclipse.configurer.ChoiceBuilder;
import net.officefloor.eclipse.configurer.ConfigurationBuilder;
import net.officefloor.eclipse.configurer.ListBuilder;
import net.officefloor.eclipse.configurer.ValueValidator;
import net.officefloor.eclipse.editor.AdaptedChildVisualFactoryContext;
import net.officefloor.eclipse.ide.editor.AbstractConfigurableItem;
import net.officefloor.eclipse.osgi.OfficeFloorOsgiBridge;
import net.officefloor.model.section.FunctionNamespaceModel;
import net.officefloor.model.section.FunctionNamespaceModel.FunctionNamespaceEvent;
import net.officefloor.model.section.ManagedFunctionModel;
import net.officefloor.model.section.PropertyModel;
import net.officefloor.model.section.SectionChanges;
import net.officefloor.model.section.SectionModel;
import net.officefloor.model.section.SectionModel.SectionEvent;
import net.officefloor.plugin.managedfunction.clazz.ClassManagedFunctionSource;

/**
 * Configuration for {@link FunctionNamespaceModel}.
 * 
 * @author Daniel Sagenschneider
 */
public class FunctionNamespaceItem extends
		AbstractConfigurableItem {

	/**
	 * Test configuration.
	 * 
	 * @param args
	 *            Command line arguments.
	 */
	public static void main(String[] args) {
		SectionEditor.launchConfigurer(new FunctionNamespaceItem(), (model) -> {
			model.setManagedFunctionSourceClassName(ClassManagedFunctionSource.class.getName());
			model.addProperty(new PropertyModel(ClassManagedFunctionSource.CLASS_NAME_PROPERTY_NAME,
					FunctionNamespaceItem.class.getName()));
			model.addManagedFunction(new ManagedFunctionModel("main"));
		});
	}

	/**
	 * Loads the {@link FunctionNamespaceType} for the
	 * {@link FunctionNamespaceItem}.
	 * 
	 * @param item
	 *            {@link FunctionNamespaceItem}.
	 * @param osgiBridge
	 *            {@link OfficeFloorOsgiBridge}.
	 * @return {@link FunctionNamespaceType}.
	 * @throws Exception
	 *             If fails to load the {@link FunctionNamespaceType}.
	 */
	public static FunctionNamespaceType loadFunctionNamespaceType(FunctionNamespaceItem item,
			OfficeFloorOsgiBridge osgiBridge) throws Exception {
		ManagedFunctionLoader loader = osgiBridge.getOfficeFloorCompiler().getManagedFunctionLoader();
		Class sourceClass = osgiBridge.loadClass(item.sourceClassName,
				ManagedFunctionSource.class);
		return loader.loadManagedFunctionType(sourceClass, item.properties);
	}

	/**
	 * Choice {@link Class}.
	 */
	private static final int CHOICE_CLASS = 0;

	/**
	 * Name of the {@link DeployedOffice}.
	 */
	private String name;

	/**
	 * Choice.
	 */
	private Integer choice = null;

	/**
	 * {@link ManagedFunctionSource} {@link Class} name.
	 */
	private String sourceClassName;

	/**
	 * {@link PropertyList}.
	 */
	private PropertyList properties = OfficeFloorCompiler.newPropertyList();

	/**
	 * {@link FunctionNamespaceType}.
	 */
	private FunctionNamespaceType functionNamespaceType;

	/**
	 * Function names.
	 */
	private List functionNames = new ArrayList<>();

	/**
	 * Function name.
	 */
	private static class FunctionName {

		/**
		 * Name of the function.
		 */
		private final String name;

		/**
		 * Indicates if function is used.
		 */
		private boolean isUsed = false;

		/**
		 * Instantiate.
		 * 
		 * @param name
		 *            Name of the function.
		 * @param isUsed
		 *            Indicates if used.
		 */
		private FunctionName(String name, boolean isUsed) {
			this.name = name;
			this.isUsed = isUsed;
		}
	}

	/*
	 * ================= AbstractParentConfigurableItem ======================
	 */

	@Override
	public FunctionNamespaceModel prototype() {
		return new FunctionNamespaceModel("Functions", null);
	}

	@Override
	public IdeExtractor extract() {
		return new IdeExtractor((parent) -> parent.getFunctionNamespaces(), SectionEvent.ADD_FUNCTION_NAMESPACE,
				SectionEvent.REMOVE_FUNCTION_NAMESPACE);
	}

	@Override
	public void loadToParent(SectionModel parentModel, FunctionNamespaceModel itemModel) {
		parentModel.addFunctionNamespace(itemModel);
	}

	@Override
	public Pane visual(FunctionNamespaceModel model, AdaptedChildVisualFactoryContext context) {
		VBox container = new VBox();
		context.label(container).getStyleClass().add("title");
		context.addNode(container, context.childGroup(ManagedFunctionItem.class.getSimpleName(), new VBox()));
		return container;
	}

	@Override
	public IdeLabeller label() {
		return new IdeLabeller((model) -> model.getFunctionNamespaceName(),
				FunctionNamespaceEvent.CHANGE_FUNCTION_NAMESPACE_NAME);
	}

	@Override
	public String style() {
		IdeStyle background = new IdeStyle().rule("-fx-background-color",
				"radial-gradient(radius 50.0%, blue, lightblue)");
		IdeStyle text = new IdeStyle(".${model} .title").rule("-fx-text-fill", "white");
		return background.toString() + text.toString();
	}

	@Override
	protected FunctionNamespaceItem item(FunctionNamespaceModel model) {
		FunctionNamespaceItem item = new FunctionNamespaceItem();
		if (model != null) {
			item.name = model.getFunctionNamespaceName();
			item.sourceClassName = model.getManagedFunctionSourceClassName();
			if (ClassManagedFunctionSource.class.getName().equals(item.sourceClassName)) {
				item.choice = CHOICE_CLASS;
			}
			item.properties = this.translateToPropertyList(model.getProperties(), (property) -> property.getName(),
					(property) -> property.getValue());

			// Load the functions (keep previous selected)
			Set existingFunctions = new HashSet<>();
			for (ManagedFunctionModel managedFunction : model.getManagedFunctions()) {
				existingFunctions.add(managedFunction.getManagedFunctionName());
			}
			for (ManagedFunctionModel function : model.getManagedFunctions()) {
				String functionName = function.getManagedFunctionName();
				item.functionNames.add(new FunctionName(functionName, existingFunctions.contains(functionName)));
			}
		}
		return item;
	}

	@Override
	public IdeConfigurer configure() {
		return new IdeConfigurer().addAndRefactor((builder, context) -> {
			builder.title("Functions");
			builder.text("Name").init((item) -> item.name).validate(ValueValidator.notEmptyString("Must specify name"))
					.setValue((item, value) -> item.name = value);
			ChoiceBuilder choices = builder.choices("").init((item) -> item.choice)
					.validate(ValueValidator.notNull("Must select")).setValue((item, value) -> {
						if (value == CHOICE_CLASS) {
							item.sourceClassName = ClassManagedFunctionSource.class.getName();
						}
					});

			// Choice: class
			ConfigurationBuilder classBuilder = choices.choice("Class");
			classBuilder.clazz("Class")
					.init((item) -> item.properties
							.getOrAddProperty(ClassManagedFunctionSource.CLASS_NAME_PROPERTY_NAME).getValue())
					.validate((ctx) -> {
						FunctionNamespaceItem item = ctx.getModel();
						String className = item.properties
								.getOrAddProperty(ClassManagedFunctionSource.CLASS_NAME_PROPERTY_NAME).getValue();
						ValueValidator.notEmptyString(className, "Must specify class", ctx);
					}).setValue((item, value) -> item.properties
							.getOrAddProperty(ClassManagedFunctionSource.CLASS_NAME_PROPERTY_NAME).setValue(value));

			// Choice: source
			ConfigurationBuilder sourceBuilder = choices.choice("Source");
			sourceBuilder.clazz("Source").init((item) -> item.sourceClassName).superType(ManagedFunctionSource.class)
					.validate(ValueValidator.notEmptyString("Must specify source"))
					.setValue((item, value) -> item.sourceClassName = value);
			sourceBuilder.properties("Properties").init((item) -> item.properties)
					.setValue((item, value) -> item.properties = value);

			// Function names
			ListBuilder functionsBuilder = builder
					.list("Functions", FunctionName.class).init((item) -> item.functionNames);
			functionsBuilder.text("Function").init((item) -> item.name);
			functionsBuilder.flag("Include").init((item) -> item.isUsed).setValue((item, value) -> item.isUsed = value);

			// Validate (ensure loads type)
			builder.validate((ctx) -> {
				OfficeFloorOsgiBridge osgiBridge = this.getConfigurableContext().getOsgiBridge();

				// Validate the type
				FunctionNamespaceItem item = ctx.getModel();

				// Attempt to load the function name space type
				item.functionNamespaceType = loadFunctionNamespaceType(item, osgiBridge);

				// Load the managed functions (keeping track of existing)
				Map existingNames = new HashMap<>();
				for (FunctionName function : item.functionNames) {
					existingNames.put(function.name, function);
				}
				item.functionNames = new ArrayList<>();
				for (ManagedFunctionType managedFunctionType : item.functionNamespaceType
						.getManagedFunctionTypes()) {
					String functionName = managedFunctionType.getFunctionName();
					FunctionName function = existingNames.get(functionName);
					if (function == null) {
						function = new FunctionName(functionName, false);
					}
					item.functionNames.add(function);
				}
				ctx.reload(functionsBuilder);

				// Ensure at least one function is selected
				if (!item.functionNames.stream().anyMatch((functionName) -> functionName.isUsed)) {
					ctx.setError("Must select at least one function");
				}
			});

		}).add((builder, context) -> {
			builder.apply("Add", (item) -> {

				// Create listing of function names
				List functions = new ArrayList<>(item.functionNames.size());
				for (FunctionName functionName : item.functionNames) {
					if (functionName.isUsed) {
						functions.add(functionName.name);
					}
				}

				// Add
				context.execute(context.getOperations().addFunctionNamespace(item.name, item.sourceClassName,
						item.properties, item.functionNamespaceType, functions.toArray(new String[functions.size()])));
			});

		}).refactor((builder, context) -> {
			builder.apply("Refactor", (item) -> {

				// Create listing of function names
				List functions = new ArrayList<>(item.functionNames.size());
				for (FunctionName functionName : item.functionNames) {
					if (functionName.isUsed) {
						functions.add(functionName.name);
					}
				}

				// TODO implement mapping configuration
				Map managedFunctionNameMapping = new HashMap<>();
				Map> managedFunctionToObjectNameMapping = new HashMap<>();
				Map> functionToFlowNameMapping = new HashMap<>();
				Map> functionToEscalationTypeMapping = new HashMap<>();

				// Refactor
				context.execute(context.getOperations().refactorFunctionNamespace(context.getModel(), item.name,
						item.sourceClassName, item.properties, item.functionNamespaceType, managedFunctionNameMapping,
						managedFunctionToObjectNameMapping, functionToFlowNameMapping, functionToEscalationTypeMapping,
						functions.toArray(new String[functions.size()])));
			});

		}).delete((context) -> {
			context.execute(context.getOperations().removeFunctionNamespace(context.getModel()));
		});
	}

	@Override
	protected void children(List children) {
		children.add(new IdeChildrenGroup(new ManagedFunctionItem()));
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy