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

net.officefloor.eclipse.wizard.template.HttpTemplateWizardPage Maven / Gradle / Ivy

There is a newer version: 3.12.0
Show newest version
/*
 * OfficeFloor - http://www.officefloor.net
 * Copyright (C) 2005-2013 Daniel Sagenschneider
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package net.officefloor.eclipse.wizard.template;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.officefloor.compile.OfficeFloorCompiler;
import net.officefloor.compile.issues.CompilerIssues;
import net.officefloor.compile.properties.Property;
import net.officefloor.compile.properties.PropertyList;
import net.officefloor.compile.section.SectionLoader;
import net.officefloor.compile.section.SectionType;
import net.officefloor.eclipse.classpath.ProjectClassLoader;
import net.officefloor.eclipse.common.dialog.input.InputHandler;
import net.officefloor.eclipse.common.dialog.input.InputListener;
import net.officefloor.eclipse.common.dialog.input.impl.BeanListInput;
import net.officefloor.eclipse.common.editparts.AbstractOfficeFloorEditPart;
import net.officefloor.eclipse.dialog.input.WoofFileInput;
import net.officefloor.eclipse.extension.ExtensionUtil;
import net.officefloor.eclipse.extension.WoofExtensionUtil;
import net.officefloor.eclipse.extension.sectionsource.SectionSourceExtensionContext;
import net.officefloor.eclipse.extension.template.WoofTemplateExtensionSourceExtension;
import net.officefloor.eclipse.extension.template.WoofTemplateExtensionSourceExtensionContext;
import net.officefloor.eclipse.extension.util.SourceExtensionUtil;
import net.officefloor.eclipse.util.EclipseUtil;
import net.officefloor.eclipse.util.JavaUtil;
import net.officefloor.eclipse.util.LogUtil;
import net.officefloor.frame.api.build.OfficeFloorIssues.AssetType;
import net.officefloor.frame.spi.source.ResourceSource;
import net.officefloor.model.woof.WoofTemplateInheritance;
import net.officefloor.model.woof.WoofTemplateLinkModel;
import net.officefloor.model.woof.WoofTemplateModel;
import net.officefloor.plugin.socket.server.http.ServerHttpConnection;
import net.officefloor.plugin.web.http.template.HttpTemplateWorkSource;
import net.officefloor.plugin.web.http.template.parse.HttpTemplate;
import net.officefloor.plugin.web.http.template.section.HttpTemplateInitialWorkSource;
import net.officefloor.plugin.web.http.template.section.HttpTemplateSectionSource;
import net.officefloor.plugin.woof.WoofContextConfigurable;
import net.officefloor.plugin.woof.WoofOfficeFloorSource;
import net.officefloor.plugin.woof.template.WoofTemplateExtensionSource;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jdt.core.IType;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;

/**
 * Wizard page providing the details of the {@link HttpTemplate}.
 * 
 * @author Daniel Sagenschneider
 */
public class HttpTemplateWizardPage extends WizardPage implements
		CompilerIssues, SectionSourceExtensionContext {

	/**
	 * {@link Property} specifying the super {@link WoofTemplateModel} name.
	 */
	private static final String SUPER_TEMPLATE_NAME = "super.template.name";

	/**
	 * {@link Property} indicating whether may continue rendering.
	 */
	private static final String PROPERTY_IS_CONTINUE_RENDERING = "is.continue.rendering";

	/**
	 * Creates the mapping of {@link WoofTemplateExtensionSource} class name to
	 * its {@link HttpTemplateExtensionInstance}.
	 * 
	 * @param classLoader
	 *            {@link ClassLoader}.
	 * @param project
	 *            {@link IProject}.
	 * @return Mapping of {@link WoofTemplateExtensionSource} class name to its
	 *         {@link HttpTemplateExtensionInstance}.
	 */
	public static Map createHttpTemplateExtensionSourceInstanceMap(
			ClassLoader classLoader, IProject project) {

		// Obtain extension source instances (by class name for unique set)
		Map extensionSourceInstances = new HashMap();

		// Obtain from project class path
		try {
			// Obtain the types on the class path
			IType[] types = JavaUtil.getSubTypes(project,
					WoofTemplateExtensionSource.class.getName());
			for (IType type : types) {
				String className = type.getFullyQualifiedName();
				if (ExtensionUtil.isIgnoreSource(className, classLoader)) {
					continue; // ignore source
				}
				extensionSourceInstances.put(className,
						new HttpTemplateExtensionSourceInstance(className,
								null, project));
			}
		} catch (Throwable ex) {
			LogUtil.logError(
					"Failed to obtain java types from project class path", ex);
		}

		// Obtain via extension point second to override
		for (WoofTemplateExtensionSourceExtension woofTemplateExtensionSourceExtension : WoofExtensionUtil
				.createWoofTemplateExtensionSourceExtensionList()) {
			try {
				Class woofTemplateExtensionSourceClass = woofTemplateExtensionSourceExtension
						.getWoofTemplateExtensionSourceClass();
				String woofTemplateExtensionSourceClassName = woofTemplateExtensionSourceClass
						.getName();
				extensionSourceInstances.put(
						woofTemplateExtensionSourceClassName,
						new HttpTemplateExtensionSourceInstance(
								woofTemplateExtensionSourceClassName,
								woofTemplateExtensionSourceExtension, project));
			} catch (Throwable ex) {
				LogUtil.logError("Failed to create source instance for "
						+ woofTemplateExtensionSourceExtension.getClass()
								.getName(), ex);
			}
		}

		// Return HTTP template extension source instances by class name
		return extensionSourceInstances;
	}

	/**
	 * Obtains the text value.
	 * 
	 * @param value
	 *            Value that may be null.
	 * @return Text value with blank string for null value.
	 */
	private static String getTextValue(String value) {
		return (value == null ? "" : value);
	}

	/**
	 * {@link HttpTemplateInstance} to base decisions. May be null
	 * if creating new {@link HttpTemplateInstance}.
	 */
	private final HttpTemplateInstance templateInstance;

	/**
	 * {@link IProject}.
	 */
	private final IProject project;

	/**
	 * {@link ClassLoader}.
	 */
	private final ClassLoader classLoader;

	/**
	 * {@link OfficeFloorCompiler}.
	 */
	private final OfficeFloorCompiler compiler;

	/**
	 * {@link SectionLoader}.
	 */
	private final SectionLoader sectionLoader;

	/**
	 * {@link ResourceSource} instances.
	 */
	private final ResourceSource[] resourceSources;

	/**
	 * Initial URI path for the {@link HttpTemplate}.
	 */
	private final String initialUriPath;

	/**
	 * {@link PropertyList}.
	 */
	private final PropertyList properties;

	/**
	 * URI path for the {@link HttpTemplate}.
	 */
	private final Property uriPath;

	/**
	 * Path to the {@link HttpTemplate}.
	 */
	private String templatePath;

	/**
	 * Logic class name.
	 */
	private final Property logicClassName;

	/**
	 * Super {@link WoofTemplateModel} name.
	 */
	private final Property superTemplateName;

	/**
	 * Inherited template paths.
	 */
	private final Property inheritedTemplatePaths;

	/**
	 * Content-Type for the {@link WoofTemplateModel}.
	 */
	private final Property contentType;

	/**
	 * Indicates if the template is secure.
	 */
	private final Property isTemplateSecure;

	/**
	 * Listing of {@link WoofTemplateLinkModel} instances.
	 */
	private WoofTemplateLinkModel[] linksSecure = new WoofTemplateLinkModel[0];

	/**
	 * HTTP methods that trigger a redirect on rendering the
	 * {@link HttpTemplate}.
	 */
	private final Property renderRedirectHttpMethods;

	/**
	 * Indicates whether allow continue rendering.
	 */
	private final Property isContinueRendering;

	/**
	 * {@link WoofTemplateInheritance} for the super {@link WoofTemplateModel}.
	 */
	private WoofTemplateInheritance superTemplateInheritance;

	/**
	 * {@link WoofTemplateInheritance} instances by their
	 * {@link WoofTemplateModel} name.
	 */
	private final Map templateInheritances;

	/**
	 * {@link SectionType} for the {@link HttpTemplateInstance}.
	 */
	private SectionType sectionType = null;

	/**
	 * Available {@link HttpTemplateExtensionSourceInstance} listing.
	 */
	private HttpTemplateExtensionSourceInstance[] availableHttpTemplateExtensionSourceInstances;

	/**
	 * {@link HttpTemplateExtensionStruct} instances.
	 */
	private final List templateExtensions = new LinkedList();

	/**
	 * Initiate.
	 * 
	 * @param project
	 *            {@link IProject}.
	 * @param editPart
	 *            {@link AbstractOfficeFloorEditPart}.
	 * @param templateInstance
	 *            {@link HttpTemplateInstance}.
	 * @param templateInheritances
	 *            {@link WoofTemplateInheritance} instances by their
	 *            {@link WoofTemplateModel} name.
	 */
	protected HttpTemplateWizardPage(final IProject project,
			final AbstractOfficeFloorEditPart editPart,
			HttpTemplateInstance templateInstance,
			Map templateInheritances) {
		super("HTTP Template");
		this.project = project;
		this.templateInstance = templateInstance;

		// Obtain the class loader for the project
		this.classLoader = ProjectClassLoader.create(project);

		// Configure the OfficeFloor compiler to obtain the section loader
		this.compiler = OfficeFloorCompiler
				.newOfficeFloorCompiler(this.classLoader);
		this.compiler.setCompilerIssues(this);

		// Provide configuration of WoOF context
		final List resourceSources = new LinkedList();
		WoofContextConfigurable configurable = new WoofContextConfigurable() {

			@Override
			public void addProperty(String name, String value) {
				HttpTemplateWizardPage.this.compiler.addProperty(name, value);
			}

			@Override
			public void setWebAppDirectory(File webAppDir) {
				// Do nothing
			}

			@Override
			public void addResources(ResourceSource resourceSource) {
				HttpTemplateWizardPage.this.compiler
						.addResources(resourceSource);
				resourceSources.add(resourceSource);
			}
		};
		this.resourceSources = resourceSources
				.toArray(new ResourceSource[resourceSources.size()]);

		// Load access to web resources
		File projectDir = project.getLocation().toFile();
		WoofOfficeFloorSource.loadWebResourcesFromMavenProject(configurable,
				projectDir);

		// Obtain the section loader
		this.sectionLoader = this.compiler.getSectionLoader();

		// Obtain template inheritances copy (as may remove refactor instance)
		this.templateInheritances = new HashMap();
		this.templateInheritances.putAll(templateInheritances);

		// Create the property list (and load existing properties)
		this.properties = this.compiler.createPropertyList();
		String initialUriPath = null;
		String initialLogicClassName = null;
		String initialSuperTemplateName = null;
		String initialInheritedTemplatePaths = null;
		String initialContentType = null;
		String initialIsTemplateSecure = null;
		String initialRenderRedirectHttpMethods = null;
		String initialIsContinueRendering = null;
		if (this.templateInstance != null) {
			// Provide initial values from existing configuration
			initialUriPath = this.templateInstance.getUri();
			initialLogicClassName = this.templateInstance.getLogicClassName();
			initialContentType = this.templateInstance.getContentType();
			initialIsTemplateSecure = String.valueOf(this.templateInstance
					.isTemplateSecure());
			initialIsContinueRendering = String.valueOf(this.templateInstance
					.isContinueRendering());

			// Remove the template from inheriting itself
			String woofTemplateName = this.templateInstance
					.getWoofTemplateName();
			this.templateInheritances.remove(woofTemplateName);

			// Provide the initial super template (if inheriting)
			WoofTemplateModel superTemplate = this.templateInstance
					.getSuperTemplate();
			if (superTemplate != null) {
				// Specify the initial super template
				initialSuperTemplateName = superTemplate.getWoofTemplateName();
				this.superTemplateInheritance = this.templateInheritances
						.get(initialSuperTemplateName);

				// Specify initial inheriting template paths
				if (this.superTemplateInheritance != null) {
					initialInheritedTemplatePaths = this.superTemplateInheritance
							.getInheritedTemplatePathsPropertyValue();
				}
			}

			// Create the render redirect HTTP methods value
			String[] initialRenderRedirectHttpMethodsList = this.templateInstance
					.getRenderRedirectHttpMethods();
			if (initialRenderRedirectHttpMethodsList != null) {
				StringBuilder httpMethods = new StringBuilder();
				boolean isFirst = true;
				for (String httpMethod : initialRenderRedirectHttpMethodsList) {
					if (!isFirst) {
						httpMethods.append(", ");
					}
					isFirst = false;
					httpMethods.append(httpMethod);
				}
				initialRenderRedirectHttpMethods = httpMethods.toString();
			}

			// Configure the links secure (ensure consistent order)
			Map configuredLinks = this.templateInstance
					.getLinksSecure();
			List linkNames = new ArrayList(
					configuredLinks.keySet());
			Collections.sort(linkNames, String.CASE_INSENSITIVE_ORDER);
			this.linksSecure = new WoofTemplateLinkModel[linkNames.size()];
			int linkIndex = 0;
			for (String linkName : linkNames) {
				this.linksSecure[linkIndex++] = new WoofTemplateLinkModel(
						linkName, configuredLinks.get(linkName).booleanValue());
			}
		}

		// Specify the initial URI path
		this.initialUriPath = initialUriPath;

		// Add the properties
		this.uriPath = this
				.addProperty(HttpTemplateSectionSource.PROPERTY_TEMPLATE_URI,
						initialUriPath);
		this.logicClassName = this.addProperty(
				HttpTemplateSectionSource.PROPERTY_CLASS_NAME,
				initialLogicClassName);
		this.superTemplateName = this.addProperty(SUPER_TEMPLATE_NAME,
				initialSuperTemplateName);
		this.inheritedTemplatePaths = this.addProperty(
				HttpTemplateSectionSource.PROPERTY_INHERITED_TEMPLATES,
				initialInheritedTemplatePaths);
		this.contentType = this.addProperty(
				HttpTemplateSectionSource.PROPERTY_CONTENT_TYPE,
				initialContentType);
		this.isTemplateSecure = this.addProperty(
				HttpTemplateWorkSource.PROPERTY_TEMPLATE_SECURE,
				initialIsTemplateSecure);
		this.renderRedirectHttpMethods = this
				.addProperty(
						HttpTemplateInitialWorkSource.PROPERTY_RENDER_REDIRECT_HTTP_METHODS,
						initialRenderRedirectHttpMethods);
		this.isContinueRendering = this.addProperty(
				PROPERTY_IS_CONTINUE_RENDERING, initialIsContinueRendering);

		// Obtain the map of HTTP template extension source instances
		Map httpTemplateExtensionSourceInstanceMap = createHttpTemplateExtensionSourceInstanceMap(
				this.classLoader, project);

		// Obtain the HTTP template extension source instances (in order)
		this.availableHttpTemplateExtensionSourceInstances = httpTemplateExtensionSourceInstanceMap
				.values().toArray(new HttpTemplateExtensionSourceInstance[0]);
		Arrays.sort(this.availableHttpTemplateExtensionSourceInstances,
				new Comparator() {
					@Override
					public int compare(HttpTemplateExtensionSourceInstance a,
							HttpTemplateExtensionSourceInstance b) {
						return String.CASE_INSENSITIVE_ORDER.compare(
								a.getWoofTemplateExtensionSourceClassName(),
								b.getWoofTemplateExtensionSourceClassName());
					}
				});

		// Specify the title
		this.setTitle("Add Template");
	}

	/**
	 * Adds a {@link Property}.
	 * 
	 * @param propertyName
	 *            Name of the {@link Property}.
	 * @param propertyValue
	 *            Value for the {@link Property}.
	 * @return Added {@link Property}.
	 */
	private Property addProperty(String propertyName, String propertyValue) {
		Property property = this.properties.addProperty(propertyName);
		property.setValue(propertyValue);
		return property;
	}

	/**
	 * Obtains the URI path.
	 * 
	 * @return URI path.
	 */
	public String getUriPath() {
		return this.uriPath.getValue();
	}

	/**
	 * Obtains the template path.
	 * 
	 * @return Template path.
	 */
	public String getTemplatePath() {
		return this.templatePath;
	}

	/**
	 * Obtains the logic class name.
	 * 
	 * @return Logic class name.
	 */
	public String getLogicClassName() {
		String className = this.logicClassName.getValue();
		return EclipseUtil.isBlank(className) ? null : className;
	}

	/**
	 * Obtains the {@link SectionType} for the {@link HttpTemplateInstance}.
	 * 
	 * @return {@link SectionType} for the {@link HttpTemplateInstance}.
	 */
	public SectionType getSectionType() {
		return this.sectionType;
	}

	/**
	 * Obtains the {@link WoofTemplateInheritance} for the super
	 * {@link WoofTemplateModel}.
	 * 
	 * @return {@link WoofTemplateInheritance} for the super
	 *         {@link WoofTemplateModel}.
	 */
	public WoofTemplateInheritance getSuperTemplateInheritance() {
		return this.superTemplateInheritance;
	}

	/**
	 * Obtains the Content-Type for the {@link WoofTemplateModel}.
	 * 
	 * @return Content-Type for the {@link WoofTemplateModel}.
	 */
	public String getContentType() {
		return this.contentType.getValue();
	}

	/**
	 * Indicates if the {@link HttpTemplate} requires a secure
	 * {@link ServerHttpConnection}.
	 * 
	 * @return true should the {@link HttpTemplate} requires a
	 *         secure {@link ServerHttpConnection}.
	 */
	public boolean isTemplateSecure() {
		return Boolean.parseBoolean(this.isTemplateSecure.getValue());
	}

	/**
	 * Obtains the {@link HttpTemplate} link override secure configuration.
	 * 
	 * @return {@link HttpTemplate} link override secure configuration.
	 */
	public Map getLinksSecure() {
		Map results = new HashMap();
		for (WoofTemplateLinkModel link : this.linksSecure) {
			String linkName = link.getWoofTemplateLinkName();
			if (!(EclipseUtil.isBlank(linkName))) {
				Boolean isLinkSecure = Boolean.valueOf(link.getIsLinkSecure());
				results.put(linkName, isLinkSecure);
			}
		}
		return results;
	}

	/**
	 * Obtains the HTTP methods that are to trigger a redirect on rendering the
	 * {@link HttpTemplate}.
	 * 
	 * @return HTTP methods that are to trigger a redirect on rendering the
	 *         {@link HttpTemplate}.
	 */
	public String[] getRenderRedirectHttpMethods() {
		String[] httpMethods = null;
		String httpMethodsValue = this.renderRedirectHttpMethods.getValue();
		if (!(EclipseUtil.isBlank(httpMethodsValue))) {
			httpMethods = httpMethodsValue.split(",");
			for (int i = 0; i < httpMethods.length; i++) {
				httpMethods[i] = httpMethods[i].trim();
			}
		}
		return httpMethods;
	}

	/**
	 * Indicates if allow continue rendering.
	 * 
	 * @return true to allow continue rendering.
	 */
	public boolean isContinueRendering() {
		return Boolean.parseBoolean(this.isContinueRendering.getValue());
	}

	/**
	 * Obtains the {@link HttpTemplateExtensionInstance} listing.
	 * 
	 * @return {@link HttpTemplateExtensionInstance} listing.
	 */
	public HttpTemplateExtensionInstance[] getHttpTemplateExtensionInstances() {

		// Create the listing of template extension instances
		List instances = new ArrayList(
				this.templateExtensions.size());
		for (HttpTemplateExtensionStruct struct : this.templateExtensions) {

			// Obtain the details
			String woofTemplateExtensionSourceClassName = struct.source
					.getWoofTemplateExtensionSourceClassName();
			PropertyList properties = struct.properties;

			// Add the extension instance
			instances.add(new HttpTemplateExtensionInstance(
					woofTemplateExtensionSourceClassName, properties));
		}

		// Return the listing of template extensions
		return instances.toArray(new HttpTemplateExtensionInstance[instances
				.size()]);
	}

	/*
	 * ====================== WizardPage =========================
	 */

	@Override
	public void createControl(Composite parent) {

		// Initiate the page
		final Composite page = new Composite(parent, SWT.NONE);
		page.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
		page.setLayout(new GridLayout(2, false));

		// Obtain initial values
		String initialTemplatePath = "";
		String initialSuperTemplateName = "";
		if (this.templateInstance != null) {
			initialTemplatePath = getTextValue(this.templateInstance
					.getTemplatePath());
			initialSuperTemplateName = getTextValue(this.superTemplateName
					.getValue());
		}

		// Determine if valid src/main/webapp directory
		IFolder webappDirectory = this.project
				.getFolder(WoofOfficeFloorSource.WEBAPP_PATH);
		IFile webXmlFile = webappDirectory
				.getFile(WoofOfficeFloorSource.WEBXML_FILE_PATH);
		if ((webappDirectory != null && webappDirectory.exists())
				&& (!(webXmlFile.exists()))) {
			// Invalid webapp directory
			new Label(page, SWT.NONE);
			Label webappInvalid = new Label(page, SWT.NONE);
			webappInvalid.setForeground(ColorConstants.red);
			webappInvalid.setText("WARNING: "
					+ WoofOfficeFloorSource.WEBAPP_PATH
					+ " resources unavailable as missing "
					+ WoofOfficeFloorSource.WEBXML_FILE_PATH);
		}

		// Provide means to specify URI path
		SourceExtensionUtil.createPropertyText("URI path",
				HttpTemplateSectionSource.PROPERTY_TEMPLATE_URI, null, page,
				this, null);

		// Provide means to specify template location
		new Label(page, SWT.NONE).setText("Template path: ");
		this.templatePath = initialTemplatePath;
		InputHandler path = new InputHandler(page,
				new WoofFileInput(this.project, page.getShell()),
				this.templatePath, new InputListener() {
					@Override
					public void notifyValueChanged(Object value) {
						// Specify the location and indicate changed
						HttpTemplateWizardPage.this.templatePath = (value == null ? ""
								: value.toString());
						HttpTemplateWizardPage.this.handleChange();
					}

					@Override
					public void notifyValueInvalid(String message) {
						HttpTemplateWizardPage.this.setErrorMessage(message);
					}
				});
		path.getControl().setLayoutData(
				new GridData(SWT.FILL, SWT.BEGINNING, true, false));

		// Provide means to specify logic class
		SourceExtensionUtil
				.createPropertyClass("Logic class",
						HttpTemplateSectionSource.PROPERTY_CLASS_NAME, page,
						this, null);

		// Provide ability to specify super template
		String[] inheritableSuperTemplateNames = this.templateInheritances
				.keySet().toArray(new String[0]);
		Arrays.sort(inheritableSuperTemplateNames,
				String.CASE_INSENSITIVE_ORDER);
		SourceExtensionUtil.createPropertyCombo("Extend template",
				SUPER_TEMPLATE_NAME, initialSuperTemplateName,
				inheritableSuperTemplateNames, page, this, null);

		// Provide means to specify Content-Type
		SourceExtensionUtil.createPropertyText("Content type",
				HttpTemplateSectionSource.PROPERTY_CONTENT_TYPE, null, page,
				this, null);

		// Provide means to specify if secure
		SourceExtensionUtil.createPropertyCheckbox("Template secure",
				HttpTemplateWorkSource.PROPERTY_TEMPLATE_SECURE, false,
				String.valueOf(true), String.valueOf(false), page, this, null);

		// Provide means to configure the links
		new Label(page, SWT.NONE).setText("Links secure: ");
		BeanListInput linksInput = new BeanListInput(
				WoofTemplateLinkModel.class, true);
		linksInput.addProperty("WoofTemplateLinkName", 3, "Link");
		linksInput.addProperty("IsLinkSecure", 1, "Secure");
		for (WoofTemplateLinkModel link : this.linksSecure) {
			linksInput.addBean(link);
		}
		InputHandler links = new InputHandler(
				page, linksInput, null, new InputListener() {
					@Override
					@SuppressWarnings("unchecked")
					public void notifyValueChanged(Object value) {
						// Specify the links and indicate changed
						List list = (List) value;
						HttpTemplateWizardPage.this.linksSecure = list
								.toArray(new WoofTemplateLinkModel[list.size()]);
						HttpTemplateWizardPage.this.handleChange();
					}

					@Override
					public void notifyValueInvalid(String message) {
						HttpTemplateWizardPage.this.setErrorMessage(message);
					}
				});
		links.getControl().setLayoutData(
				new GridData(SWT.FILL, SWT.BEGINNING, true, false));

		// Provide means to specify render redirect HTTP methods
		SourceExtensionUtil
				.createPropertyText(
						"Render Redirect HTTP methods",
						HttpTemplateInitialWorkSource.PROPERTY_RENDER_REDIRECT_HTTP_METHODS,
						null, page, this, null);

		// Provide means to specify if may continue rendering
		SourceExtensionUtil.createPropertyCheckbox("Continue Rendering",
				PROPERTY_IS_CONTINUE_RENDERING, false, String.valueOf(true),
				String.valueOf(false), page, this, null);

		// Configure the template extensions
		new Label(page, SWT.NONE).setText("Extensions");
		final TabFolder extensionTabs = new TabFolder(page, SWT.NONE);
		extensionTabs.setLayout(new GridLayout(1, false));
		extensionTabs
				.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		// Provide the extension add button
		final TabItem addExtensionTab = new TabItem(extensionTabs, SWT.NONE);
		addExtensionTab.setText("+");
		Label addExtensionLabel = new Label(extensionTabs, SWT.NONE);
		addExtensionLabel.setText("Press '+' to add an extension");
		addExtensionTab.setControl(addExtensionLabel);

		// Add the existing extensions (possibly being refactored)
		if (this.templateInstance != null) {
			for (HttpTemplateExtensionInstance instance : this.templateInstance
					.getTemplateExtensionInstances()) {

				// Find the matching source
				HttpTemplateExtensionSourceInstance source = null;
				for (HttpTemplateExtensionSourceInstance availableSource : this.availableHttpTemplateExtensionSourceInstances) {
					if (availableSource
							.getWoofTemplateExtensionSourceClassName().equals(
									instance.getTemplateExtensionClassName())) {
						source = availableSource;
					}
				}

				// Add the template extension
				this.addTemplateExtension(source, extensionTabs, instance);
			}
		}

		// Listen for click on add extension tab
		extensionTabs.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				TabFolder curFolder = (TabFolder) e.widget;
				Point eventLocation = new Point(e.x, e.y);
				TabItem clickedTab = curFolder.getItem(eventLocation);
				if (clickedTab == addExtensionTab) {

					// Provide dialog to select extension
					HttpTemplateExtensionSourceInstance source = SelectHttpTemplateExtensionSourceInstanceDialog.getHttpTemplateExtensionSourceInstance(
							extensionTabs.getShell(),
							HttpTemplateWizardPage.this.availableHttpTemplateExtensionSourceInstances);
					if (source == null) {
						return; // not add extension
					}

					// Add the extension
					HttpTemplateWizardPage.this.addTemplateExtension(source,
							extensionTabs, null);
				}
			}
		});

		// Indicate initial state
		this.handleChange();

		// Specify page control
		this.setControl(page);
	}

	/**
	 * Adds the {@link HttpTemplateExtensionInstance}.
	 * 
	 * @param source
	 *            {@link HttpTemplateExtensionSourceInstance}.
	 * @param extensionTabs
	 *            {@link TabFolder} displaying the
	 *            {@link HttpTemplateExtensionInstance} listing.
	 * @param instance
	 *            {@link HttpTemplateExtensionInstance}. May be
	 *            null.
	 */
	private void addTemplateExtension(
			HttpTemplateExtensionSourceInstance source,
			TabFolder extensionTabs, HttpTemplateExtensionInstance instance) {

		// Obtain the class name of the extension
		String extensionClassName = "Unknown";
		if (source != null) {
			// Provide details from source
			extensionClassName = source
					.getWoofTemplateExtensionSourceClassName();
		} else if (instance != null) {
			// Provide details from instance
			extensionClassName = instance.getTemplateExtensionClassName();
		}

		// Provide unknown source if no source
		if (source == null) {
			source = new UnknownHttpTemplateExtensionSourceInstance(
					extensionClassName, this.project);
		}

		// Add a tab (as second last item)
		int tabIndex = Math.max(0, (extensionTabs.getItemCount() - 1));
		final TabItem extraTab = new TabItem(extensionTabs, SWT.NONE, tabIndex);
		extraTab.setText(source.getWoofTemplateExtensionLabel());

		// Obtain the properties
		PropertyList properties;
		if (instance != null) {
			// Use existing properties (taking copy so as not to alter original)
			properties = this.compiler.createPropertyList();
			for (Property property : instance.getProperties()) {
				properties.addProperty(property.getName(), property.getLabel())
						.setValue(property.getValue());
			}

		} else {
			// Seed properties from specification
			properties = source
					.createSpecification(HttpTemplateWizardPage.this);
		}

		// Create the context
		WoofTemplateExtensionSourceExtensionContext context = new WoofTemplateExtensionSourceExtensionContextImpl(
				properties, HttpTemplateWizardPage.this);

		// Create the panel for the controls
		Composite panel = new Composite(extensionTabs, SWT.NONE);
		Composite controls = new Composite(panel, SWT.NONE);
		source.createControl(controls, context);
		extraTab.setControl(panel);

		// Configure the layout (after to override)
		panel.setLayout(new GridLayout(1, false));
		panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		// Add extension to listing (ensuring have properties)
		final HttpTemplateExtensionStruct templateExtension = new HttpTemplateExtensionStruct(
				source, properties);
		this.templateExtensions.add(templateExtension);

		// Add button to remove extension
		Button removeButton = new Button(panel, SWT.PUSH);
		removeButton.setText("Remove extension");
		removeButton.setLayoutData(new GridData(SWT.RIGHT, SWT.BOTTOM, false,
				false));
		removeButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				// Remove the template extension
				HttpTemplateWizardPage.this.templateExtensions
						.remove(templateExtension);

				// Remove from display
				extraTab.dispose();

				// Handle change of removing the extension
				HttpTemplateWizardPage.this.handleChange();
			}
		});

		// Provide focus to new tab
		extensionTabs.setSelection(tabIndex);

		// Handle change of adding the extension
		this.handleChange();
	}

	/**
	 * Handles the change.
	 */
	private void handleChange() {

		// Clear error message (as change may have corrected it)
		this.setErrorMessage(null);

		// Clear section type (as potentially changing)
		this.sectionType = null;

		// Ensure have appropriate super template inheritance
		this.superTemplateInheritance = this.templateInheritances
				.get(this.superTemplateName.getValue());
		if (this.superTemplateInheritance == null) {
			// No inherited template paths
			this.inheritedTemplatePaths.setValue(null);
		} else {
			// Specify the inherited template paths
			this.inheritedTemplatePaths.setValue(this.superTemplateInheritance
					.getInheritedTemplatePathsPropertyValue());
		}

		// Ensure have template URI path
		if (EclipseUtil.isBlank(this.uriPath.getValue())) {
			this.setErrorMessage("Must specify URI path");
			this.setPageComplete(false);
			return;
		}

		// Ensure have template path
		if (EclipseUtil.isBlank(this.templatePath)) {
			this.setErrorMessage("Must specify location of template");
			this.setPageComplete(false);
			return;
		}

		// Load the Section Type
		this.isIssue = false; // reset to determine if issue
		this.sectionType = this.sectionLoader.loadSectionType(
				HttpTemplateSectionSource.class, this.templatePath,
				this.properties);
		if ((this.sectionType == null) || (this.isIssue)) {
			// Must have section (issue reported as error message)
			this.setPageComplete(false);
			return;
		}

		// Validate the template extensions
		for (HttpTemplateExtensionStruct extension : this.templateExtensions) {

			// Obtain the extension source class name
			String extensionSourceClassName = extension.source
					.getWoofTemplateExtensionSourceClassName();

			// Match against old extensions to find old properties
			PropertyList oldProperties = null;
			if (this.templateInstance != null) {
				for (HttpTemplateExtensionInstance instance : this.templateInstance
						.getTemplateExtensionInstances()) {
					if (extensionSourceClassName.equals(instance
							.getTemplateExtensionClassName())) {
						oldProperties = instance.getProperties();
					}
				}
			}
			if (oldProperties == null) {
				// Ensure have old properties
				oldProperties = this.compiler.createPropertyList();
			}

			// Obtain the remaining details
			String oldUri = this.initialUriPath;
			String newUri = this.uriPath.getValue();
			PropertyList newProperties = extension.properties;

			// Validate the change
			extension.source.validateChange(oldUri, oldProperties, newUri,
					newProperties, this.resourceSources, this);
			if (this.isIssue) {
				// Issue reported as error
				this.setPageComplete(false);
				return;
			}
		}

		// Specification of template details complete
		this.setErrorMessage(null);
		this.setPageComplete(true);
	}

	/*
	 * ===================== CompilerIssues ===============================
	 */

	/**
	 * Allows determining if an issue occurred. Reset this to false
	 * before undertaking operation to determine if causes an issue.
	 */
	private boolean isIssue = false;

	@Override
	public void addIssue(LocationType locationType, String location,
			AssetType assetType, String assetName, String issueDescription) {
		// Provide as error message
		this.setErrorMessage(issueDescription);
		this.isIssue = true;
	}

	@Override
	public void addIssue(LocationType locationType, String location,
			AssetType assetType, String assetName, String issueDescription,
			Throwable cause) {
		// Provide as error message
		this.setErrorMessage(issueDescription + " ("
				+ cause.getClass().getSimpleName() + ": " + cause.getMessage()
				+ ")");
		this.isIssue = true;
	}

	/*
	 * ================= SectionSourceExtensionContext ======================
	 */

	@Override
	public IProject getProject() {
		return this.project;
	}

	@Override
	public PropertyList getPropertyList() {
		return this.properties;
	}

	@Override
	public void notifyPropertiesChanged() {
		this.handleChange();
	}

	/**
	 * Details of the {@link WoofTemplateExtensionSource}.
	 */
	private static class HttpTemplateExtensionStruct {

		/**
		 * {@link HttpTemplateExtensionSourceInstance}.
		 */
		public final HttpTemplateExtensionSourceInstance source;

		/**
		 * {@link PropertyList}.
		 */
		public final PropertyList properties;

		/**
		 * Initiate.
		 * 
		 * @param source
		 *            {@link HttpTemplateExtensionSourceInstance}.
		 * @param properties
		 *            {@link PropertyList}.
		 */
		public HttpTemplateExtensionStruct(
				HttpTemplateExtensionSourceInstance source,
				PropertyList properties) {
			this.source = source;
			this.properties = properties;
		}
	}

	/**
	 * Unknown {@link HttpTemplateExtensionSourceInstance}.
	 */
	private class UnknownHttpTemplateExtensionSourceInstance extends
			HttpTemplateExtensionSourceInstance {

		/**
		 * Initiate.
		 * 
		 * @param woofTemplateExtensionSourceClassName
		 *            {@link WoofTemplateExtensionSource} class name.
		 * @param project
		 *            {@link IProject}.
		 */
		public UnknownHttpTemplateExtensionSourceInstance(
				String woofTemplateExtensionSourceClassName, IProject project) {
			super(woofTemplateExtensionSourceClassName, null, project);
		}

		/**
		 * Obtains the error message.
		 * 
		 * @return Error message.
		 */
		private String getErrorMessage() {
			return "Could not find extension source "
					+ this.getWoofTemplateExtensionSourceClassName()
					+ ". Please ensure it is on the project's class path.";
		}

		/*
		 * ================ HttpTemplateExtensionSourceInstance ===============
		 */

		@Override
		public PropertyList createSpecification(CompilerIssues issues) {
			// Provide empty properties
			return HttpTemplateWizardPage.this.compiler.createPropertyList();
		}

		@Override
		public void createControl(Composite page,
				WoofTemplateExtensionSourceExtensionContext context) {

			// No source so provide error
			page.setLayout(new GridLayout(1, false));
			Label errorLabel = new Label(page, SWT.NONE);
			errorLabel.setForeground(ColorConstants.red);
			errorLabel.setText(this.getErrorMessage());
		}

		@Override
		public void validateChange(String oldUri, PropertyList oldProperties,
				String newUri, PropertyList newProperties,
				ResourceSource[] resourceSources, CompilerIssues issues) {

			// Indicate unknown extension source class name
			issues.addIssue(null, null, null, null, this.getErrorMessage());
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy