/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */

package org.apache.openaz.xacml.admin.view.windows;

import java.util.Map;

import javax.xml.bind.JAXBElement;

import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.FunctionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.openaz.xacml.admin.jpa.Attribute;
import org.apache.openaz.xacml.admin.jpa.Datatype;
import org.apache.openaz.xacml.admin.jpa.FunctionArgument;
import org.apache.openaz.xacml.admin.jpa.FunctionDefinition;
import org.apache.openaz.xacml.admin.model.ExpressionContainer;
import org.apache.openaz.xacml.admin.util.AdminNotification;
import org.apache.openaz.xacml.admin.util.JPAUtils;
import org.apache.openaz.xacml.admin.util.XACMLFunctionValidator;
import org.apache.openaz.xacml.admin.view.events.ApplyParametersChangedListener;
import org.apache.openaz.xacml.util.XACMLObjectCopy;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.data.Container.ItemSetChangeListener;
import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class ExpressionBuilderComponent extends Window implements ApplyParametersChangedListener {
	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Button buttonSave;
	@AutoGenerated
	private TreeTable treeExpressions;
	@AutoGenerated
	private HorizontalLayout horizontalLayout_1;
	@AutoGenerated
	private CheckBox checkBoxShortName;
	@AutoGenerated
	private Button buttonClearAll;
	@AutoGenerated
	private Button buttonDeleteExpression;
	@AutoGenerated
	private Button buttonAddExpression;
	/*
	 * 
	 * 
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Log logger	= LogFactory.getLog(ExpressionBuilderComponent.class);
	
	private static final Action ADD_EXPRESSION = 	new Action ("Add Expression");
	private static final Action EDIT_EXPRESSION = 	new Action ("Edit Expression");
	private static final Action DELETE_EXPRESSION = new Action ("Delete Expression");
	private static final Action ADD_ARGUMENT = 	new Action ("Add Argument");
	private static final Action EDIT_ARGUMENT = 	new Action ("Edit Argument");
	private static final Action DELETE_ARGUMENT = new Action ("Delete Argument");
	
	private final Object[] visibleColumns = new Object[] {ExpressionContainer.PROPERTY_NAME, ExpressionContainer.PROPERTY_ID, ExpressionContainer.PROPERTY_ID_SHORT, ExpressionContainer.PROPERTY_DATATYPE, ExpressionContainer.PROPERTY_DATATYPE_SHORT};
	private final String[] columnHeaders = new String[] {"Name", "XCAML ID or Value", "XCAML ID or Value", "Data Type ID", "Data Type ID"};
	
	private final ExpressionBuilderComponent self = this;
	private final Object parent;
	private final Map<VariableDefinitionType, PolicyType> variables;
	private final ExpressionContainer container;
	private boolean isSaved = false;
	/**
	 * The constructor should first build the main layout, set the
	 * composition root and then do any custom initialization.
	 *
	 * The constructor will not be automatically regenerated by the
	 * visual editor.
	 */
	public ExpressionBuilderComponent(Object parent, Object root, FunctionArgument argument, Map<VariableDefinitionType, PolicyType> variables) {
		buildMainLayout();
//		setCompositionRoot(mainLayout);
		setContent(mainLayout);
		//
		// Save our data
		//
		this.parent = parent;
		this.variables = variables;
		this.container = new ExpressionContainer(parent, root, argument);
		//
		// Make sure we support the parent object
		//
		if (this.isSupported() == false) {
			throw new IllegalArgumentException("Unsupported object type");
		}
		//
		// Set our shortcuts
		//
		this.setCloseShortcut(KeyCode.ESCAPE);
		//
		// Finish our GUI initialization
		//
		this.initializeTree();
		this.initializeButtons();
		this.initializeCheckbox();
		//
		// Setup the buttons
		//
		this.setupButtons();
	}
	
	private boolean isSupported() {
		return this.isParentACondition() ||
					this.isParentAVariable() ||
					this.isParentAAssignment();
	}
	
	private boolean	isParentACondition() {
		return this.parent instanceof ConditionType;
	}
	
	private boolean isParentAVariable() {
		return this.parent instanceof VariableDefinitionType;
	}
	
	private boolean isParentAAssignment() {
		return this.parent instanceof AttributeAssignmentExpressionType;
	}
	
	private void initializeTree() {
		//
		// Initialize GUI properties
		//
		this.treeExpressions.setImmediate(true);
		this.treeExpressions.setSelectable(true);
		//
		// Initialize the data source
		//
		this.treeExpressions.setContainerDataSource(this.container);
		this.treeExpressions.setItemCaptionMode(ItemCaptionMode.PROPERTY);
		this.treeExpressions.setVisibleColumns(this.visibleColumns);
		this.treeExpressions.setColumnHeaders(this.columnHeaders);
		this.treeExpressions.setColumnCollapsingAllowed(true);
		this.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_ID, true);
		this.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_DATATYPE, true);
		//
		// Add our action handler
		//
		this.treeExpressions.addActionHandler(new Handler() {
			private static final long serialVersionUID = 1L;

			@Override
			public Action[] getActions(Object target, Object sender) {
				if (target == null) {
					if (self.container.size() == 0) {
						return new Action[] {ADD_EXPRESSION};
					}
					return null;
				}
				if (target instanceof ApplyType && XACMLFunctionValidator.canHaveMoreArguments((ApplyType) target)) {
					return new Action[] {ADD_ARGUMENT, EDIT_EXPRESSION, DELETE_EXPRESSION};
				}
				return new Action[] {EDIT_ARGUMENT, DELETE_ARGUMENT};
			}

			@Override
			public void handleAction(Action action, Object sender, Object target) {
				if (action == ADD_EXPRESSION && target == null) {
					self.addExpression(null, null);
				}
				if (action == EDIT_EXPRESSION && target != null) {
					self.editExpression(target, (ApplyType) self.container.getParent(target), (FunctionArgument) self.container.getArgument(target));
				}
				if (action == DELETE_EXPRESSION && target != null) {
					self.deleteExpression(target);
				}
				if (action == ADD_ARGUMENT && target != null && target instanceof ApplyType) {
					self.addArgument((ApplyType) target);
				}
				if (action == EDIT_ARGUMENT && target != null) {
					self.editExpression(target, (ApplyType) self.container.getParent(target), (FunctionArgument) self.container.getArgument(target));
				}
				if (action == DELETE_ARGUMENT && target != null) {
					self.deleteExpression(target);
				}
			}
		});
		//
		// Listen to double-click item selections
		//
		this.treeExpressions.addItemClickListener(new ItemClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void itemClick(ItemClickEvent event) {
				if (event.isDoubleClick()) {
					Object target = event.getItemId();//self.treeExpressions.getValue();
					if (target == null) {
						return;
					}
					self.editExpression(target, (ApplyType) self.container.getParent(target), (FunctionArgument) self.container.getArgument(target));
				}
			}
		});
		//
		// Listen when the user selects a row
		//
		this.treeExpressions.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.setupButtons();
			}			
		});
		//
		// Listen to when the table contents change
		//
		this.treeExpressions.addItemSetChangeListener(new ItemSetChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void containerItemSetChange(ItemSetChangeEvent event) {
				self.validateExpression();
			}
		});
		//
		// Expand columns automatically
		//
		this.treeExpressions.setColumnExpandRatio(ExpressionContainer.PROPERTY_NAME, 1.0f);
		this.treeExpressions.setColumnExpandRatio(ExpressionContainer.PROPERTY_ID, 1.0f);
		this.treeExpressions.setColumnExpandRatio(ExpressionContainer.PROPERTY_DATATYPE, 1.0f);
		//
		// Expand all the children
		//
		for (Object id : this.treeExpressions.getItemIds()) {
			this.treeExpressions.setCollapsed(id, false);
		}
		//
		// Have a description generator
		//
		this.treeExpressions.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
			private static final long serialVersionUID = 1L;

			@Override
			public String generateDescription(Component source, Object itemId, Object propertyId) {
				if (propertyId != null && propertyId.equals(ExpressionContainer.PROPERTY_NAME) && itemId instanceof ApplyType) {
					return ((ApplyType) itemId).getDescription();
				}
				return null;
			}
		});
	}
	
	private void initializeButtons() {
		this.buttonClearAll.setImmediate(true);
		this.buttonClearAll.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				self.clearAllExpressions();
			}
			
		});
		
		this.buttonAddExpression.setImmediate(true);
		this.buttonAddExpression.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Object selected = self.treeExpressions.getValue();
				if (selected == null) {
					//
					// Adding a root expression
					//
					self.addExpression(null, null);
				} else {
					//
					// Adding an argument
					//
					if (selected instanceof ApplyType) {
						//
						// Get the function
						//
						self.addArgument((ApplyType) selected);
					}
				}
			}			
		});
		
		this.buttonDeleteExpression.setImmediate(true);
		this.buttonDeleteExpression.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Object id = self.treeExpressions.getValue();
				if (id == null) {
					logger.error("Delete button clicked on null selection");
					return;
				}
				self.deleteExpression(id);
			}
			
		});
		
		this.buttonSave.setImmediate(true);
		this.buttonSave.setClickShortcut(KeyCode.ENTER);
		this.buttonSave.setEnabled(false);
		this.buttonSave.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				//
				// TODO validate
				//
				//
				// Mark that we are saved
				//
				self.isSaved = true;
				//
				// Close the window
				//
				self.close();
			}
		});		
	}
	
	protected void initializeCheckbox() {
		this.checkBoxShortName.setValue(true);
		this.checkBoxShortName.setImmediate(true);
		this.checkBoxShortName.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_ID, self.checkBoxShortName.getValue());
				self.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_DATATYPE, self.checkBoxShortName.getValue());
				self.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_ID_SHORT, ! self.checkBoxShortName.getValue());
				self.treeExpressions.setColumnCollapsed(ExpressionContainer.PROPERTY_DATATYPE_SHORT, ! self.checkBoxShortName.getValue());
			}
		});
	}
	
	protected void setupButtons() {
		if (this.treeExpressions.size() == 0) {
			this.buttonAddExpression.setEnabled(true);
			this.buttonClearAll.setEnabled(false);
			this.buttonSave.setEnabled(false);
		} else {
			this.validateExpression();
			this.buttonAddExpression.setEnabled(false);
			this.buttonClearAll.setEnabled(true);
		}
		Object value = this.treeExpressions.getValue();
		if (value == null) {
			this.buttonDeleteExpression.setEnabled(false);
		} else {
			this.buttonDeleteExpression.setEnabled(true);
		}
	}
	
	protected void validateExpression() {
		boolean valid = false;
		boolean canHaveMore = false;
		if (this.isParentACondition()) {
			valid = XACMLFunctionValidator.validateCondition((ConditionType) this.parent);
			canHaveMore = XACMLFunctionValidator.canHaveMoreArguments((ConditionType) this.parent);
		} else if (this.isParentAVariable()) {
			valid = XACMLFunctionValidator.validateVariable((VariableDefinitionType) this.parent);
			canHaveMore = XACMLFunctionValidator.canHaveMoreArguments((VariableDefinitionType) this.parent);
		} else if (this.isParentAAssignment()) {
			valid = XACMLFunctionValidator.validateAssignment((AttributeAssignmentExpressionType)this.parent);
			canHaveMore = XACMLFunctionValidator.canHaveMoreArguments((AttributeAssignmentExpressionType) this.parent);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("valid: " + valid + " canHaveMore: " + canHaveMore);
		}
//		this.buttonAddExpression.setEnabled(canHaveMore);
		this.buttonSave.setEnabled(valid);
	}
	
	protected void addArgument(final ApplyType parentApply) {
		//
		// Get the function
		//
		FunctionDefinition function = JPAUtils.findFunction(parentApply.getFunctionId());
		if (function != null) {
			FunctionArgument argument = XACMLFunctionValidator.getFunctionArgument(parentApply.getExpression().size() + 1, function);
			if (logger.isDebugEnabled()) {
				logger.debug("Add Argument: " + argument);
			}
			assert argument != null;
			//
			// Is this a high order bag function? And it's data type not defined? (most likely)
			//
			if (function.isHigherOrder() && argument.getDatatypeBean() == null) {
				if (logger.isDebugEnabled()) {
					logger.debug("isHighOrder and a null datatype bean");
				}
				//
				// Get what the data type restriction should be
				//
				try {
					assert parentApply.getExpression().size() > 0;
					JAXBElement<?> element = parentApply.getExpression().get(0);
					assert element != null && element.getValue() != null;
					Object declaredFunction = element.getValue();
					assert declaredFunction instanceof FunctionType;
					FunctionDefinition declaredFunctionDefinition = JPAUtils.findFunction(((FunctionType) declaredFunction).getFunctionId());
					assert declaredFunctionDefinition != null;
					if (logger.isDebugEnabled()) {
						logger.debug("declaredFunction is: " + declaredFunctionDefinition);
					}
					FunctionArgument declaredFunctionArgument = XACMLFunctionValidator.getFunctionArgument(parentApply.getExpression().size(), declaredFunctionDefinition);
					assert declaredFunctionArgument != null;
					if (logger.isDebugEnabled()) {
						logger.debug("declaredFunctionArgument is: " + declaredFunctionArgument);
					}
					//
					// Copy the argument
					//
					argument = new FunctionArgument(argument);
					argument.setDatatypeBean(declaredFunctionArgument.getDatatypeBean());
				} catch (Exception e) {
					logger.error("Exception while determining parent apply's FunctionType argument datatype.");
				}
				
			}
			self.addExpression(parentApply, argument);
		} else {
			AdminNotification.error("ApplyType does not have a function defined. Please define that first.");
		}

	}

	protected void addExpression(final ApplyType parentApply, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("Adding Expression: " + parentApply + " arg: " + argument);
		}
		//
		// First we need to select what Expression They want
		//
		final ExpressionSelectionWindow selector = new ExpressionSelectionWindow(parentApply,
																		this.isParentAAssignment(),
																		(argument != null ? argument.isBag() : false),
																		(argument != null ? ! argument.isBag() : false));
		selector.setCaption("Select the Expression Type");
		selector.setModal(true);
		selector.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Was something selected?
				//
				String selection = selector.getSelection();
				if (selection == null) {
					return;
				}
				//
				// What did the user select?
				//
				if (selection.equals(ExpressionSelectionWindow.OPTION_APPLY)) {
					//
					self.editApply(new ApplyType(), parentApply, argument);
					//
				} else if (selection.equals(ExpressionSelectionWindow.OPTION_DESIGNATOR)) {
					//
					self.editAttribute(new AttributeDesignatorType(), parentApply, argument);
					//
				} else if (selection.equals(ExpressionSelectionWindow.OPTION_SELECTOR) ) {
					//
					self.editAttribute(new AttributeSelectorType(), parentApply, argument);
					//
				} else if (selection.equals(ExpressionSelectionWindow.OPTION_VALUE)) {
					//
					self.editValue(new AttributeValueType(), parentApply, argument);
					//
				} else if (selection.equals(ExpressionSelectionWindow.OPTION_VARIABLE)) {
					//
					self.editVariable(new VariableReferenceType(), parentApply, argument);
					//
				}
			}
		});
		selector.center();
		UI.getCurrent().addWindow(selector);
	}

	protected void editApply(final ApplyType apply, final ApplyType parent, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("editApply: " + apply + " parent: " + parent + " :" + argument);
		}
		//
		// Copy the apply and create its window
		//
		final ApplyType copyApply = XACMLObjectCopy.copy(apply);
		final ApplyEditorWindow window = new ApplyEditorWindow(copyApply, parent, argument, self.parent);
		window.setCaption("Edit The Apply Expression");
		window.setModal(true);
		//
		// Set ourselves as an ApplyParametersChanged listener
		//
		window.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user save?
				//
				if (window.isSaved() == false) {
					return;
				}
				//
				// Copy back the apply
				//
				apply.setDescription(copyApply.getDescription());
				apply.setFunctionId(copyApply.getFunctionId());
				//
				// Get the function information
				//
				FunctionDefinition function = JPAUtils.findFunction(apply.getFunctionId());
				assert function != null;
				//
				// Is this a new Apply?
				//
				if (self.container.containsId(apply)) {
					//
					// No - we are updating
					//
					self.container.updateItem(apply);
				} else {
					//
					// Is this a higher-order bag function?
					//
					if (function.isHigherOrder()) {
						//
						// Have the user select a function for it
						//
						final FunctionSelectionWindow functionSelection = new FunctionSelectionWindow(null);
						functionSelection.setCaption("Select Function");
						functionSelection.setModal(true);
						functionSelection.addCloseListener(new CloseListener() {
							private static final long serialVersionUID = 1L;

							@Override
							public void windowClose(CloseEvent e) {
								//
								// Did the user save?
								//
								if (functionSelection.isSaved() == false) {
									return;
								}
								//
								// Get the function
								//
								String function = functionSelection.getSelectedFunction();
								if (function == null || function.isEmpty()) {
									logger.error("Function window said it was saved, but there was no function.");
									return;
								}
								//
								// Create the function object
								//
								FunctionType hoFunction = new FunctionType();
								hoFunction.setFunctionId(function);
								//
								// Add it into the apply
								//
								apply.getExpression().add(new ObjectFactory().createFunction(hoFunction));
								//
								// New Item
								//
								Item item = self.container.addItem(apply, parent, argument);
								assert item != null;
								self.treeExpressions.setCollapsed(apply, false);
								self.treeExpressions.select(apply);
							}
						});
						functionSelection.center();
						UI.getCurrent().addWindow(functionSelection);
					} else {
						//
						// New Item
						//
						Item item = self.container.addItem(apply, parent, argument);
						assert item != null;
						self.treeExpressions.setCollapsed(apply, false);
						self.treeExpressions.select(apply);
					}
				}
			}
		});
		window.center();
		UI.getCurrent().addWindow(window);
	}
	
	protected void editAttribute(final Object target, final ApplyType parent, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("editAttribute: " + target + " parent: " + parent + " :" + argument);
		}
		//
		// Determine what the data type needs to be
		//
		Datatype datatype = null;
		if (parent == null && this.isParentACondition()) {
			datatype = JPAUtils.getBooleanDatatype();
		} else {
			if (argument != null) {
				datatype = argument.getDatatypeBean();
			}
		}
		//
		// Copy the attribute
		//
		final Object copyAttribute = XACMLObjectCopy.deepCopy(target);
		//
		// Create the window
		//
		final AttributeSelectionWindow window = new AttributeSelectionWindow(datatype, copyAttribute);
		if (target instanceof AttributeDesignatorType) {
			window.setCaption("Edit Designator " + (((AttributeDesignatorType) target).getAttributeId() != null ? ((AttributeDesignatorType) target).getAttributeId() : ""));
		} else {
			window.setCaption("Edit Selector " + (((AttributeSelectorType) target).getContextSelectorId() != null ? ((AttributeSelectorType) target).getContextSelectorId() : ""));
		}
		window.setModal(true);
		window.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user hit save?
				//
				if (window.isSaved() == false) {
					return;
				}
				//
				// Grab the attribute
				//
				Attribute attribute = window.getAttribute();
				if (attribute == null) {
					return;
				}
				//
				// Save it back into the original
				//
				if (target instanceof AttributeDesignatorType) {
					((AttributeDesignatorType)target).setAttributeId(attribute.getXacmlId());
					((AttributeDesignatorType)target).setCategory(attribute.getCategoryBean().getXacmlId());
					((AttributeDesignatorType)target).setDataType(attribute.getDatatypeBean().getXacmlId());
					((AttributeDesignatorType)target).setIssuer(attribute.getIssuer());
					((AttributeDesignatorType)target).setMustBePresent(attribute.isMustBePresent());
				} else {
					((AttributeSelectorType)target).setContextSelectorId(attribute.getXacmlId());
					((AttributeSelectorType)target).setCategory(attribute.getCategoryBean().getXacmlId());
					((AttributeSelectorType)target).setDataType(attribute.getDatatypeBean().getXacmlId());
					((AttributeSelectorType)target).setPath(attribute.getSelectorPath());
					((AttributeSelectorType)target).setMustBePresent(attribute.isMustBePresent());
				}
				//
				// Is this a new item?
				//
				if (self.container.containsId(target)) {
					//
					// No, just update the container
					//
					self.container.updateItem(target);
				} else {
					//
					// Yes a new item, add it in
					//
					//assert(self.container.addItem(JPAUtils.createDesignator(attribute), parent, argument) != null);
					Item item = self.container.addItem(target, parent, argument);
					assert item != null;
					self.treeExpressions.select(target);
				}
			}
		});
		window.center();
		UI.getCurrent().addWindow(window);
	}

	protected void editValue(final AttributeValueType value, final ApplyType parent, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("editvalue: " + value + " parent: " + parent + " :" + argument);
		}
		//
		// Copy the attribute value
		//
		final AttributeValueType copyValue = XACMLObjectCopy.copy(value);
		//
		// Get what the datatype should be
		//
		Datatype datatypeRestriction = null;
		//
		// Is this a root?
		//
		if (parent == null) {
			//
			// Check if our parent container is a condition
			//
			if (self.isParentACondition()) {
				//
				// We are only allowed to return boolean's
				//
				datatypeRestriction = JPAUtils.getBooleanDatatype();
			}
		} else {
			//
			// Are we an argument?
			//
			if (argument != null) {
				//
				// Yes - we are restricted to that argument's datatype
				//
				datatypeRestriction = argument.getDatatypeBean();
			}
		}
		//
		// Create the window
		//
		final AttributeValueEditorWindow window = new AttributeValueEditorWindow(copyValue, datatypeRestriction);
		window.setCaption("Edit Attribute Value");
		window.setModal(true);
		window.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user click save?
				//
				if (window.isSaved() == false) {
					return;
				}
				//
				// Yes - get the value
				//
				value.getContent().clear();
				for (Object o : copyValue.getContent()) {
					value.getContent().add(o);
				}
				value.setDataType(copyValue.getDataType());
				//
				// Was this a new value?
				//
				if (self.container.containsId(value)) {
					//
					// No - update it
					//
					self.container.updateItem(value);
				} else {
					//
					// Yes - add it in
					//
					Item item = self.container.addItem(value, parent, argument);
					assert item != null;
				}
			}
		});
		window.center();
		UI.getCurrent().addWindow(window);
	}

	protected void editVariable(final VariableReferenceType variable, final ApplyType parent, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("editVariable: " + variable + " parent: " + parent + " :" + argument);
		}
		//
		// Copy the variable
		//
		final VariableReferenceType copyVariable = XACMLObjectCopy.copy(variable);
		//
		// Create the window
		//
		final VariableReferenceEditorWindow window = new VariableReferenceEditorWindow(copyVariable, this.variables);
		window.setCaption("Edit Variable Reference");
		window.setModal(true);
		window.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user click save?
				//
				if (window.isSaved() == false) {
					return;
				}
				//
				// Copy the variable changes back
				//
				variable.setVariableId(copyVariable.getVariableId());
				//
				// Is this a new one?
				//
				if (self.container.containsId(variable)) {
					//
					// No - update it
					//
					self.container.updateItem(variable);
				} else {
					//
					// Yes - add it
					//
					Item item = self.container.addItem(variable, parent, argument);
					assert item != null;
				}
			}
		});
		window.center();
		UI.getCurrent().addWindow(window);
	}
	
	protected void editFunction(final FunctionType func, final ApplyType parent, final FunctionArgument argument) {
		if (logger.isDebugEnabled()) {
			logger.debug("editFunction: " + func + " parent: " + parent + " :" + argument);
		}

		final FunctionSelectionWindow functionSelection = new FunctionSelectionWindow((func != null ? func.getFunctionId() : null));
		functionSelection.setCaption("Edit Function");
		functionSelection.setModal(true);
		functionSelection.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user save?
				//
				if (functionSelection.isSaved() == false) {
					return;
				}
				//
				// Get the function
				//
				String function = functionSelection.getSelectedFunction();
				if (function == null || function.isEmpty()) {
					logger.error("Function window said it was saved, but there was no function.");
					return;
				}
				//
				// New one?
				//
				if (func == null) {
					//
					// Create the function object
					//
					FunctionType hoFunction = new FunctionType();
					hoFunction.setFunctionId(function);
					//
					// Add it into the apply
					//
					assert parent.getExpression().size() == 0;
					parent.getExpression().add(new ObjectFactory().createFunction(hoFunction));
					//
					// New Item
					//
					Item item = self.container.addItem(func, parent, argument);
					assert item != null;
					self.treeExpressions.setCollapsed(parent, false);
					self.treeExpressions.select(func);
				} else {
					//
					// Editing an existing
					//
					func.setFunctionId(function);
					self.container.updateItem(func);
					//
					// Warn user
					//
					if (parent.getExpression().size() > 1) {
						AdminNotification.warn("You have updated the function ID. The rest of the arguments may be invalid for the function. Please verify the other arguments.");
					}
				}
			}
		});
		functionSelection.center();
		UI.getCurrent().addWindow(functionSelection);
	}
	
	protected void editExpression(final Object target, final ApplyType parent, final FunctionArgument argument) {
		if (target instanceof ApplyType) {
			//
			this.editApply((ApplyType) target, parent, argument);
			//
		} else if (target instanceof AttributeValueType) {
			//
			this.editValue((AttributeValueType) target,parent, argument);
			//
		} else if (target instanceof AttributeDesignatorType || target instanceof AttributeSelectorType) {
			//
			this.editAttribute(target, parent, argument);
			//
		} else if (target instanceof VariableReferenceType) {
			//
			this.editVariable((VariableReferenceType) target, parent, argument);
			//
		} else if (target instanceof FunctionType) {
			//
			this.editFunction((FunctionType) target, parent, argument);
			//
		}
	}

	protected void deleteExpression(Object target) {
		if (this.container.isRoot(target)) {
			if (this.treeExpressions.removeAllItems() == false) {
				logger.error("Failed to remove everything.");
			}
		} else {
			if (this.treeExpressions.removeItem(target) == false) {
				logger.error("Failed to remove " + target);
			}
		}
		this.setupButtons();
	}
	
	protected void clearAllExpressions() {
		if (this.treeExpressions.removeAllItems() == false) {
			logger.error("Failed to remove everything.");
		}
		this.setupButtons();
	}
		
	@Override
	public void applyParameterChanged(ApplyType apply, ApplyType parent, FunctionArgument argument, Object container) {
		logger.info("applyParameterChanged: " + apply + " " + parent + " " + argument + " " + container);
		//
		// TODO - figure out if this something being edited, or a new one
		//
	}
	
	public boolean isSaved() {
		return this.isSaved;
	}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("100%");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(true);
		mainLayout.setSpacing(true);
		
		// top-level component properties
		setWidth("-1px");
		setHeight("-1px");
		
		// horizontalLayout_1
		horizontalLayout_1 = buildHorizontalLayout_1();
		mainLayout.addComponent(horizontalLayout_1);
		mainLayout.setExpandRatio(horizontalLayout_1, 1.0f);
		
		// treeExpressions
		treeExpressions = new TreeTable();
		treeExpressions.setImmediate(false);
		treeExpressions.setWidth("100.0%");
		treeExpressions.setHeight("-1px");
		mainLayout.addComponent(treeExpressions);
		mainLayout.setExpandRatio(treeExpressions, 1.0f);
		
		// buttonSave
		buttonSave = new Button();
		buttonSave.setCaption("Save");
		buttonSave.setImmediate(true);
		buttonSave.setWidth("-1px");
		buttonSave.setHeight("-1px");
		mainLayout.addComponent(buttonSave);
		mainLayout.setComponentAlignment(buttonSave, new Alignment(48));
		
		return mainLayout;
	}

	@AutoGenerated
	private HorizontalLayout buildHorizontalLayout_1() {
		// common part: create layout
		horizontalLayout_1 = new HorizontalLayout();
		horizontalLayout_1.setImmediate(false);
		horizontalLayout_1.setWidth("-1px");
		horizontalLayout_1.setHeight("-1px");
		horizontalLayout_1.setMargin(false);
		horizontalLayout_1.setSpacing(true);
		
		// buttonAddExpression
		buttonAddExpression = new Button();
		buttonAddExpression.setCaption("Add Expression");
		buttonAddExpression.setImmediate(true);
		buttonAddExpression.setWidth("-1px");
		buttonAddExpression.setHeight("-1px");
		horizontalLayout_1.addComponent(buttonAddExpression);
		
		// buttonDeleteExpression
		buttonDeleteExpression = new Button();
		buttonDeleteExpression.setCaption("Delete Expression");
		buttonDeleteExpression.setImmediate(true);
		buttonDeleteExpression.setWidth("-1px");
		buttonDeleteExpression.setHeight("-1px");
		horizontalLayout_1.addComponent(buttonDeleteExpression);
		
		// buttonClearAll
		buttonClearAll = new Button();
		buttonClearAll.setCaption("Clear All");
		buttonClearAll.setImmediate(true);
		buttonClearAll.setDescription("Clears all the expressions.");
		buttonClearAll.setWidth("-1px");
		buttonClearAll.setHeight("-1px");
		horizontalLayout_1.addComponent(buttonClearAll);
		
		// checkBoxShortName
		checkBoxShortName = new CheckBox();
		checkBoxShortName.setCaption("Display Short XACML ID's");
		checkBoxShortName.setImmediate(false);
		checkBoxShortName
				.setDescription("If checked, the right-most string of the function and datatype URI's will only be displayed.");
		checkBoxShortName.setWidth("-1px");
		checkBoxShortName.setHeight("-1px");
		horizontalLayout_1.addComponent(checkBoxShortName);
		
		return horizontalLayout_1;
	}

}
