You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openaz.apache.org by pd...@apache.org on 2016/03/17 02:15:38 UTC

[16/23] incubator-openaz git commit: Ported original att source to openaz This Closes #3

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/RuleAlgorithms.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/RuleAlgorithms.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/RuleAlgorithms.java
new file mode 100644
index 0000000..961984e
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/RuleAlgorithms.java
@@ -0,0 +1,115 @@
+/*
+ *  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.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.apache.openaz.xacml.api.Identifier;
+
+@Entity
+@Table(name="RuleAlgorithms")
+@NamedQuery(name="RuleAlgorithms.findAll", query="SELECT d FROM RuleAlgorithms d")
+public class RuleAlgorithms implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	public static final char STANDARD = 'S';
+	public static final char CUSTOM = 'C';
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	@Column(name="id")
+	private int id;
+
+	@Column(name="is_standard", nullable=false)
+	private char isStandard;
+
+	@Column(name="xacml_id", nullable=false, unique=true, length=255)
+	private String xacmlId;
+	
+	@Column(name="short_name", nullable=false, length=64)
+	private String shortName;
+
+	public RuleAlgorithms(Identifier id, char standard) {
+		if (id != null) {
+			this.xacmlId = id.stringValue();
+		}
+		this.isStandard = standard;
+	}
+	public RuleAlgorithms(Identifier id) {
+		this(id, RuleAlgorithms.STANDARD);
+	}
+
+	public RuleAlgorithms() {
+		this(null, RuleAlgorithms.STANDARD);
+	}
+
+	public int getId() {
+		return this.id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public char getIsStandard() {
+		return this.isStandard;
+	}
+
+	public void setIsStandard(char isStandard) {
+		this.isStandard = isStandard;
+	}
+	
+	@Transient
+	public boolean isStandard() {
+		return this.isStandard == RuleAlgorithms.STANDARD;
+	}
+	
+	@Transient
+	public boolean isCustom() {
+		return this.isStandard == RuleAlgorithms.CUSTOM;
+	}
+
+	public String getXacmlId() {
+		return this.xacmlId;
+	}
+
+	public void setXacmlId(String xacmlId) {
+		this.xacmlId = xacmlId;
+	}
+
+	public String getShortName() {
+		return shortName;
+	}
+
+	public void setShortName(String shortName) {
+		this.shortName = shortName;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/package-info.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/package-info.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/package-info.java
new file mode 100644
index 0000000..85d06f5
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/package-info.java
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ *
+ */
+
+/**
+ * 
+ */
+/**
+ * @author pameladragosh
+ *
+ */
+package org.apache.openaz.xacml.admin.jpa;

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeContainer.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeContainer.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeContainer.java
new file mode 100644
index 0000000..37d2fd4
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeContainer.java
@@ -0,0 +1,500 @@
+/*
+ *  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.model;
+
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.util.JPAUtils;
+import org.apache.openaz.xacml.api.AttributeValue;
+import org.apache.openaz.xacml.api.Identifier;
+import org.apache.openaz.xacml.util.XACMLPolicyAggregator;
+import org.apache.openaz.xacml.util.XACMLPolicyScanner;
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.MethodProperty;
+import com.vaadin.ui.Table;
+
+public class AttributeContainer extends ItemSetChangeNotifier implements Container.Hierarchical, Container.ItemSetChangeNotifier {
+	private static final long serialVersionUID = 1L;
+	private static Log logger	= LogFactory.getLog(AttributeContainer.class);
+	//private final AttributeContainer self = this;
+	private final Map<Category, Map<Datatype, Map<String, Set<ContainerAttribute>>>> mapAttributes = new HashMap<Category, Map<Datatype, Map<String, Set<ContainerAttribute>>>>();
+
+	class ContainerAttribute {
+		Path				policy;
+		boolean				isRoot;
+		AttributeValue<?>	value;
+		
+		public ContainerAttribute(Path policy, boolean isRoot, AttributeValue<?> value) {
+			this.policy = policy;
+			this.isRoot = isRoot;
+			this.value = value;
+		}
+
+		public Path getPolicy() {
+			return policy;
+		}
+
+		public boolean isRoot() {
+			return isRoot;
+		}
+
+		public AttributeValue<?> getValue() {
+			return value;
+		}
+		
+		public boolean isCustom() {
+			return this.policy == null;
+		}
+	}
+    /**
+     * String identifier of an object's "id" property.
+     */
+    public static String PROPERTY_ID = "Id";
+
+    /**
+     * String identifier of an object's "category" property.
+     */
+    public static String PROPERTY_CATEGORY = "Category";
+
+    /**
+     * String identifier of an object's "datatype" property.
+     */
+    public static String PROPERTY_DATATYPE = "Datatype";
+
+    /**
+     * String identifier of an object's "value" property.
+     */
+    public static String PROPERTY_VALUES = "Values";
+
+    /**
+     * List of the string identifiers for the available properties.
+     */
+    public static Collection<String> ATTRIBUTE_PROPERTIES;
+
+    private final static Method ATTRIBUTEITEM_ID;
+    private final static Method ATTRIBUTEITEM_CATEGORY;
+    private final static Method ATTRIBUTEITEM_DATATYPE;
+    private final static Method ATTRIBUTEITEM_VALUES;
+    static {
+    	ATTRIBUTE_PROPERTIES = new ArrayList<String>();
+    	ATTRIBUTE_PROPERTIES.add(PROPERTY_ID);
+    	ATTRIBUTE_PROPERTIES.add(PROPERTY_CATEGORY);
+    	ATTRIBUTE_PROPERTIES.add(PROPERTY_DATATYPE);
+    	ATTRIBUTE_PROPERTIES.add(PROPERTY_VALUES);
+    	ATTRIBUTE_PROPERTIES =  Collections.unmodifiableCollection(ATTRIBUTE_PROPERTIES);
+    	try {
+    		ATTRIBUTEITEM_ID = AttributeItem.class.getMethod("getId", new Class[]{});
+    		ATTRIBUTEITEM_CATEGORY = AttributeItem.class.getMethod("getCategory", new Class[]{});
+    		ATTRIBUTEITEM_DATATYPE = AttributeItem.class.getMethod("getDatatype", new Class[]{});
+    		ATTRIBUTEITEM_VALUES = AttributeItem.class.getMethod("getValues", new Class[]{});
+    	} catch (final NoSuchMethodException e) {
+            throw new RuntimeException("Internal error finding methods in AttributeContainer");
+        }
+    }
+    
+	public AttributeContainer(Path rootPolicy, Collection<Path> referencedPolicies) {
+		super();
+		this.setContainer(this);
+		this.initialize(rootPolicy, referencedPolicies);
+	}
+	
+	protected void initialize(Path rootPolicy, Collection<Path> referencedPolicies) {
+		XACMLPolicyAggregator aggregator = new XACMLPolicyAggregator();
+		//
+		// Scan the policy
+		//
+		new XACMLPolicyScanner(rootPolicy, aggregator).scan();
+		this.addAttributes(aggregator, rootPolicy, true);
+		aggregator = new XACMLPolicyAggregator();
+		//
+		// Scan the referenced policies
+		//
+		for (Path policy : referencedPolicies) {
+			new XACMLPolicyScanner(policy, aggregator).scan();
+			this.addAttributes(aggregator, policy, false);
+			aggregator = new XACMLPolicyAggregator();
+		}
+	}
+	
+	protected void addAttributes(XACMLPolicyAggregator aggregator, Path policy, boolean isRoot) {
+		for (Identifier cat : aggregator.getAttributeMap().keySet()) {
+			Category category = JPAUtils.findCategory(cat);
+			if (category == null) {
+				logger.warn("Could not find category: " + cat);
+				continue;
+			}
+			if (this.mapAttributes.containsKey(category) == false) {
+				this.mapAttributes.put(category, new HashMap<Datatype, Map<String, Set<ContainerAttribute>>>());
+			}
+			Map<Datatype, Map<String, Set<ContainerAttribute>>> datatypeMap = this.mapAttributes.get(category);
+			for (Identifier dt : aggregator.getAttributeMap().get(cat).keySet()) {
+				Datatype datatype = JPAUtils.findDatatype(dt);
+				if (datatype == null) {
+					logger.warn("Could not find datatype: " + dt);
+				}
+				//
+				// Need a unique datatype object
+				//
+				datatype = new Datatype((int) System.currentTimeMillis(), datatype);
+				if (datatypeMap.containsKey(datatype) == false) {
+					datatypeMap.put(datatype, new HashMap<String, Set<ContainerAttribute>>());
+				}
+				Map<String, Set<ContainerAttribute>> attributeMap = datatypeMap.get(datatype);
+				for (Identifier id : aggregator.getAttributeMap().get(cat).get(dt).keySet()) {
+					if (attributeMap.containsKey(id.stringValue()) == false) {
+						attributeMap.put(id.stringValue(), new HashSet<ContainerAttribute>());
+					}
+					for (AttributeValue<?> attribute : aggregator.getAttributeMap().get(cat).get(dt).get(id)) {
+						attributeMap.get(id.stringValue()).add(new ContainerAttribute(policy, isRoot, attribute));
+					}
+				}
+			}
+		}
+	}
+	
+	protected boolean isObjectSupported(Object itemId) {
+		if (itemId instanceof Category ||
+			itemId instanceof Datatype ||
+			itemId instanceof String ||
+			itemId instanceof ContainerAttribute) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public Item getItem(Object itemId) {
+		if (this.isObjectSupported(itemId)) {
+			return new AttributeItem(itemId);
+		}
+		return null;
+	}
+
+	@Override
+	public Collection<?> getContainerPropertyIds() {
+		return ATTRIBUTE_PROPERTIES;
+	}
+
+	@Override
+	public Collection<?> getItemIds() {
+		final Collection<Object> items = new ArrayList<Object>();
+		for (Category category : this.mapAttributes.keySet()) {
+			items.add(category);
+			for (Datatype datatype : this.mapAttributes.get(category).keySet()) {
+				items.add(datatype);
+				for (String id : this.mapAttributes.get(category).get(datatype).keySet()) {
+					items.add(id);
+					for (ContainerAttribute attribute : this.mapAttributes.get(category).get(datatype).get(id)) {
+						items.add(attribute);
+					}
+				}
+			}
+		}
+		return Collections.unmodifiableCollection(items);
+	}
+
+	@Override
+	public Property<?> getContainerProperty(Object itemId, Object propertyId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+        if (propertyId.equals(PROPERTY_ID)) {
+            return new MethodProperty<Object>(getType(propertyId), 
+            						new AttributeItem(itemId), ATTRIBUTEITEM_ID, null);
+        }
+        if (propertyId.equals(PROPERTY_CATEGORY)) {
+            return new MethodProperty<Object>(getType(propertyId), 
+            						new AttributeItem(itemId), ATTRIBUTEITEM_CATEGORY, null);
+        }
+        if (propertyId.equals(PROPERTY_DATATYPE)) {
+            return new MethodProperty<Object>(getType(propertyId), 
+            						new AttributeItem(itemId), ATTRIBUTEITEM_DATATYPE, null);
+        }
+        if (propertyId.equals(PROPERTY_VALUES)) {
+            return new MethodProperty<Object>(getType(propertyId), 
+            						new AttributeItem(itemId), ATTRIBUTEITEM_VALUES, null);
+        }
+		return null;
+	}
+
+	@Override
+	public Class<?> getType(Object propertyId) {
+        if (propertyId.equals(PROPERTY_ID)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_CATEGORY)) {
+            return Category.class;
+        }
+        if (propertyId.equals(PROPERTY_DATATYPE)) {
+            return Datatype.class;
+        }
+        if (propertyId.equals(PROPERTY_VALUES)) {
+            return Table.class;
+        }
+		return null;
+	}
+
+	@Override
+	public int size() {
+		return this.mapAttributes.size();
+	}
+
+	@Override
+	public boolean containsId(Object itemId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return false;
+		}
+		if (itemId instanceof Category) {
+			return this.mapAttributes.containsKey(itemId);
+		}
+		for (Category category : this.mapAttributes.keySet()) {
+			if (itemId instanceof Datatype) {
+				return this.mapAttributes.get(category).containsKey(itemId);
+			}
+			for (Datatype datatype : this.mapAttributes.get(category).keySet()) {
+				if (itemId instanceof String) {
+					return this.mapAttributes.get(category).get(datatype).containsKey(itemId);
+				}
+				for (String id : this.mapAttributes.get(category).get(datatype).keySet()) {
+					if (itemId instanceof ContainerAttribute) {
+						return this.mapAttributes.get(category).get(datatype).get(id).contains(itemId);
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public Item addItem(Object itemId) throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Use addItem(Category, Datatype, AttributeValue<?>) instead.");
+	}
+
+	@Override
+	public Object addItem() throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Use addItem(Category, Datatype, AttributeValue<?>) instead.");
+	}
+
+	@Override
+	public boolean addContainerProperty(Object propertyId, Class<?> type,
+			Object defaultValue) throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeContainerProperty(Object propertyId)
+			throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeAllItems() throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Can't remove all the items. You can remove custom user attributes.");
+	}
+
+	@Override
+	public Collection<?> getChildren(Object itemId) {
+		//
+		// PLD TODO - this may not work for Datatype
+		//
+		final Collection<Object> items = new ArrayList<Object>();
+		for (Category category : this.mapAttributes.keySet()) {
+			for (Datatype datatype : this.mapAttributes.get(category).keySet()) {
+				if (itemId instanceof Category) {
+					items.add(datatype);
+				}
+				for (String id : this.mapAttributes.get(category).get(datatype).keySet()) {
+					if (itemId instanceof Category ||
+						itemId instanceof Datatype) {
+						items.add(id);
+						items.addAll(this.mapAttributes.get(category).get(datatype).get(id));
+					} else if (itemId instanceof String) {
+						items.addAll(this.mapAttributes.get(category).get(datatype).get(id));
+					}
+				}
+			}
+		}
+		return Collections.unmodifiableCollection(items);
+	}
+
+	@Override
+	public Object getParent(Object itemId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Collection<?> rootItemIds() {
+		final Collection<Object> items = new ArrayList<Object>();
+		items.add(this.mapAttributes.keySet());
+		return Collections.unmodifiableCollection(items);
+	}
+
+	@Override
+	public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Can't move attributes around. Use addItem(Category, Datatype, Attribute).");
+	}
+
+	@Override
+	public boolean areChildrenAllowed(Object itemId) {
+		if (itemId instanceof Category ||
+			itemId instanceof Datatype ||
+			itemId instanceof String) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed)
+			throws UnsupportedOperationException {
+		if (itemId instanceof Category ||
+			itemId instanceof Datatype ||
+			itemId instanceof String) {
+			if (areChildrenAllowed) {
+				return true;
+			}
+			return false;
+		}
+		if (areChildrenAllowed == false) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean isRoot(Object itemId) {
+		return this.mapAttributes.containsKey(itemId);
+	}
+
+	@Override
+	public boolean hasChildren(Object itemId) {
+		if (itemId instanceof ContainerAttribute) {
+			return false;
+		}
+		if (itemId instanceof Category) {
+			if (this.mapAttributes.containsKey(itemId)) {
+				return this.mapAttributes.get(itemId).size() > 0;
+			}
+			return false;
+		}
+		//
+		// PLD TODO - this may not work. Datatype may prove difficult
+		// to distinguish which category it is in.
+		//
+		for (Category category : this.mapAttributes.keySet()) {
+			if (itemId instanceof Datatype) {
+				if (this.mapAttributes.get(category).containsKey(itemId)) {
+					return this.mapAttributes.get(category).get(itemId).size() > 0;
+				}
+				continue;
+			}
+			for (Datatype datatype : this.mapAttributes.get(category).keySet()) {
+				if (itemId instanceof String) {
+					if (this.mapAttributes.get(category).get(datatype).containsKey(itemId)) {
+						return this.mapAttributes.get(category).get(datatype).get(itemId).size() > 0;
+					}
+					continue;
+				}
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public boolean removeItem(Object itemId) throws UnsupportedOperationException {
+		if (! (itemId instanceof ContainerAttribute)) {
+			return false;
+		}
+		for (Category category : this.mapAttributes.keySet()) {
+			for (Datatype datatype : this.mapAttributes.get(category).keySet()) {
+				for (String id : this.mapAttributes.get(category).get(datatype).keySet()) {
+					if (this.mapAttributes.get(category).get(datatype).get(id).contains(itemId)) {
+						return this.mapAttributes.get(category).get(datatype).get(id).remove(itemId);
+					}
+				}
+			}
+		}
+		return false;
+	}
+	
+	public class AttributeItem implements Item {
+		private static final long serialVersionUID = 1L;
+		private final Object data;
+		
+		public AttributeItem(Object data) {
+			this.data = data;
+		}
+		
+		public String getId() {
+			return null;
+		}
+		
+		public Category getCategory() {
+			return null;
+		}
+		
+		public Datatype getDatatype() {
+			return null;
+		}
+		
+		public Table	getValues() {
+			return null;
+		}
+
+		@Override
+		public Property<?> getItemProperty(Object id) {
+            return getContainerProperty(this.data, id);
+		}
+
+		@Override
+		public Collection<?> getItemPropertyIds() {
+	          return getContainerPropertyIds();
+		}
+
+		@Override
+		public boolean addItemProperty(Object id, @SuppressWarnings("rawtypes") Property property) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Attribute container does not support adding new properties");
+		}
+		@Override
+		public boolean removeItemProperty(Object id) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Attribute container does not support removing properties");
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeValueContainer.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeValueContainer.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeValueContainer.java
new file mode 100644
index 0000000..1074936
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/AttributeValueContainer.java
@@ -0,0 +1,300 @@
+/*
+ *  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.model;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.model.AttributeContainer.ContainerAttribute;
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.MethodProperty;
+
+public class AttributeValueContainer extends ItemSetChangeNotifier implements Container.Ordered, Container.ItemSetChangeNotifier {
+	private static final long serialVersionUID = 1L;
+	private final Datatype datatype; //NOPMD
+	private final List<ContainerAttribute> attributes;
+
+    /**
+     * String identifier of an object's "Value" property.
+     */
+    public static String PROPERTY_VALUE = "Value";
+
+    /**
+     * String identifier of an object's "Source" property.
+     */
+    public static String PROPERTY_SOURCE = "Source";
+
+    /**
+     * List of the string identifiers for the available properties.
+     */
+    public static Collection<String> ATTRIBUTEVALUE_PROPERTIES;
+
+    private final static Method ATTRIBUTEVALUEITEM_VALUE;
+    private final static Method ATTRIBUTEVALUEITEM_SOURCE;
+    static {
+    	ATTRIBUTEVALUE_PROPERTIES = new ArrayList<String>();
+    	ATTRIBUTEVALUE_PROPERTIES.add(PROPERTY_VALUE);
+    	ATTRIBUTEVALUE_PROPERTIES.add(PROPERTY_SOURCE);
+    	ATTRIBUTEVALUE_PROPERTIES =  Collections.unmodifiableCollection(ATTRIBUTEVALUE_PROPERTIES);
+    	try {
+    		ATTRIBUTEVALUEITEM_VALUE = AttributeValueItem.class.getMethod("getValue", new Class[]{});
+    		ATTRIBUTEVALUEITEM_SOURCE = AttributeValueItem.class.getMethod("getSource", new Class[]{});
+    	} catch (final NoSuchMethodException e) {
+            throw new RuntimeException("Internal error finding methods in AttributeValueContainer");
+        }
+    }
+    
+    public AttributeValueContainer(Datatype datatype, List<ContainerAttribute> attributes) {
+		this.datatype = datatype;
+		this.attributes = attributes;
+	}
+    
+    public boolean isObjectSupported(Object itemId) {
+    	return itemId instanceof ContainerAttribute;
+    }
+
+	@Override
+	public Item getItem(Object itemId) {
+		if (itemId instanceof ContainerAttribute) {
+			return new AttributeValueItem((ContainerAttribute) itemId);
+		}
+		return null;
+	}
+
+	@Override
+	public Collection<?> getContainerPropertyIds() {
+		return ATTRIBUTEVALUE_PROPERTIES;
+	}
+
+	@Override
+	public Collection<?> getItemIds() {
+		return Collections.unmodifiableList(this.attributes);
+	}
+
+	@Override
+	public Property<?> getContainerProperty(Object itemId, Object propertyId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+        if (propertyId.equals(PROPERTY_VALUE)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new AttributeValueItem((ContainerAttribute) itemId), ATTRIBUTEVALUEITEM_VALUE, null);
+        }
+
+        if (propertyId.equals(PROPERTY_SOURCE)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new AttributeValueItem((ContainerAttribute) itemId), ATTRIBUTEVALUEITEM_SOURCE, null);
+        }
+		return null;
+	}
+
+	@Override
+	public Class<?> getType(Object propertyId) {
+        if (propertyId.equals(PROPERTY_VALUE)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_SOURCE)) {
+            return String.class;
+        }
+		return null;
+	}
+
+	@Override
+	public int size() {
+		return this.attributes.size();
+	}
+
+	@Override
+	public boolean containsId(Object itemId) {
+		return this.attributes.contains(itemId);
+	}
+
+	@Override
+	public Item addItem(Object itemId) throws UnsupportedOperationException {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		return new AttributeValueItem((ContainerAttribute) itemId);
+	}
+
+	@Override
+	public Object addItem() throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Please use addItem(Object itemId) - setup the container attribute first.");
+	}
+
+	@Override
+	public boolean removeItem(Object itemId) throws UnsupportedOperationException {
+		if (this.isObjectSupported(itemId) == false) {
+			return false;
+		}
+		throw new UnsupportedOperationException("TODO");
+//		return this.attributes.remove(itemId);
+	}
+
+	@Override
+	public boolean addContainerProperty(Object propertyId, Class<?> type,
+			Object defaultValue) throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeContainerProperty(Object propertyId)
+			throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeAllItems() throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("TODO");
+//		this.attributes.clear();
+//		return true;
+	}
+
+	@Override
+	public Object nextItemId(Object itemId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		int index = this.getItemIndex((ContainerAttribute) itemId);
+		if (index == -1 || index >= this.attributes.size()) {
+			return null;
+		}
+		return this.attributes.get(index + 1);
+	}
+
+	@Override
+	public Object prevItemId(Object itemId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		int index = this.getItemIndex((ContainerAttribute) itemId);
+		if (index == -1 || index == 0) {
+			return null;
+		}
+		return this.attributes.get(index - 1);
+	}
+
+	@Override
+	public Object firstItemId() {
+		if (this.attributes.size() > 0) {
+			return this.attributes.get(0);
+		}
+		return null;
+	}
+
+	@Override
+	public Object lastItemId() {
+		if (this.attributes.size() > 0) {
+			return this.attributes.get(this.attributes.size() - 1);
+		}
+		return null;
+	}
+
+	@Override
+	public boolean isFirstId(Object itemId) {
+		if (this.attributes.size() > 0) {
+			return this.attributes.get(0).equals(itemId);
+		}
+		return false;
+	}
+
+	@Override
+	public boolean isLastId(Object itemId) {
+		if (this.attributes.size() > 0) {
+			return this.attributes.get(this.attributes.size() - 1).equals(itemId);
+		}
+		return false;
+	}
+
+	@Override
+	public Object addItemAfter(Object previousItemId) throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Use addItemAfter(Object previousItemId, Object newItemId) - please create the object yourself.");
+	}
+
+	@Override
+	public Item addItemAfter(Object previousItemId, Object newItemId) throws UnsupportedOperationException {
+		if (this.isObjectSupported(previousItemId) == false || this.isObjectSupported(newItemId) == false) {
+			return null;
+		}
+		int index = this.getItemIndex((ContainerAttribute) previousItemId);
+		if (index >= 0) {
+			this.attributes.add(index, (ContainerAttribute) newItemId);
+		}
+		return null;
+	}
+	
+	protected int	getItemIndex(ContainerAttribute itemId) {
+		int index;
+		for (index = 0; index < this.attributes.size(); index++) {
+			if (this.attributes.get(index).equals(itemId)) {
+				return index;
+			}
+		}
+		return -1;
+	}
+	
+	public class AttributeValueItem implements Item {
+		private static final long serialVersionUID = 1L;
+		private final ContainerAttribute attribute;
+		
+		public AttributeValueItem(ContainerAttribute attribute) {
+			this.attribute = attribute;
+		}
+
+		public String getValue() {
+			if (this.attribute == null) {
+				return null;
+			}
+			return this.attribute.value.toString();
+		}
+
+		public String getSource() {
+			if (this.attribute == null) {
+				return null;
+			}
+			return this.attribute.value.toString();
+		}
+
+		@Override
+		public Property<?> getItemProperty(Object id) {
+            return getContainerProperty(this.attribute, id);
+		}
+		@Override
+		public Collection<?> getItemPropertyIds() {
+           return getContainerPropertyIds();
+		}
+		@Override
+		public boolean addItemProperty(Object id, @SuppressWarnings("rawtypes") Property property) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Attribute Value container does not support adding new properties");
+		}
+		@Override
+		public boolean removeItemProperty(Object id) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Attribute Value container does not support removing properties");
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/ExpressionContainer.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/ExpressionContainer.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/ExpressionContainer.java
new file mode 100644
index 0000000..30c8670
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/model/ExpressionContainer.java
@@ -0,0 +1,1215 @@
+/*
+ *  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.model;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+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.ExpressionType;
+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.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.FunctionArgument;
+import org.apache.openaz.xacml.admin.jpa.FunctionDefinition;
+import org.apache.openaz.xacml.admin.util.JPAUtils;
+import org.apache.openaz.xacml.admin.util.XACMLFunctionValidator;
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.MethodProperty;
+
+public class ExpressionContainer extends ItemSetChangeNotifier implements Container.Hierarchical, Container.ItemSetChangeNotifier {
+	private static final long serialVersionUID = 1L;
+	private static Log logger	= LogFactory.getLog(ExpressionContainer.class);
+	
+	/**
+     * String identifier of a file's "name" property.
+     */
+    public static String PROPERTY_NAME = "Name";
+
+    /**
+     * String identifier of an object's "id" property.
+     */
+    public static String PROPERTY_ID = "Id";
+
+    /**
+     * String identifier of an object's "datatype" property.
+     */
+    public static String PROPERTY_DATATYPE_SHORT = "shortDatatype";
+
+    /**
+     * String identifier of an object's "id" property.
+     */
+    public static String PROPERTY_ID_SHORT = "shortId";
+
+    /**
+     * String identifier of an object's "datatype" property.
+     */
+    public static String PROPERTY_DATATYPE = "Datatype";
+
+    /**
+     * List of the string identifiers for the available properties.
+     */
+    public static Collection<String> EXPRESSION_PROPERTIES;
+
+    private final static Method EXPRESSIONITEM_NAME;
+    
+    private final static Method EXPRESSIONITEM_ID;
+
+    private final static Method EXPRESSIONITEM_DATATYPE;
+
+    private final static Method EXPRESSIONITEM_ID_SHORT;
+
+    private final static Method EXPRESSIONITEM_DATATYPE_SHORT;
+
+    static {
+    	EXPRESSION_PROPERTIES = new ArrayList<String>();
+    	EXPRESSION_PROPERTIES.add(PROPERTY_NAME);
+    	EXPRESSION_PROPERTIES.add(PROPERTY_ID);
+    	EXPRESSION_PROPERTIES.add(PROPERTY_DATATYPE);
+    	EXPRESSION_PROPERTIES.add(PROPERTY_ID_SHORT);
+    	EXPRESSION_PROPERTIES.add(PROPERTY_DATATYPE_SHORT);
+    	EXPRESSION_PROPERTIES = Collections.unmodifiableCollection(EXPRESSION_PROPERTIES);
+    	try {
+    		EXPRESSIONITEM_NAME = ExpressionItem.class.getMethod("getName", new Class[]{});
+    		EXPRESSIONITEM_ID = ExpressionItem.class.getMethod("getId", new Class[]{});
+    		EXPRESSIONITEM_DATATYPE = ExpressionItem.class.getMethod("getDatatype", new Class[]{});
+    		EXPRESSIONITEM_ID_SHORT = ExpressionItem.class.getMethod("getIdShort", new Class[]{});
+    		EXPRESSIONITEM_DATATYPE_SHORT = ExpressionItem.class.getMethod("getDatatypeShort", new Class[]{});
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(
+                    "Internal error finding methods in PolicyContainer");
+        }
+    }
+    
+    protected class ApplyParent {
+    	ApplyType apply;
+    	FunctionArgument argument;
+    	
+    	public ApplyParent(ApplyType apply, FunctionArgument argument) {
+    		this.apply = apply;
+    		this.argument = argument;
+    	}
+
+		public ApplyType getApply() {
+			return apply;
+		}
+
+		public void setApply(ApplyType apply) {
+			this.apply = apply;
+		}
+
+		public FunctionArgument getArgument() {
+			return argument;
+		}
+
+		public void setArgument(FunctionArgument argument) {
+			this.argument = argument;
+		}
+    }
+    //
+    // Our parent object information and which argument we are
+    // from our parent (relevant to the Apply).
+    //
+    private final Object parent;
+    private final FunctionArgument argument;
+    //
+    // The root object of the expression
+    //
+    private Object root;
+    //
+    // Our helper tables for organization purposes and to
+    // make sure the correct functions/datatypes are being
+    // setup.
+    //
+    private Map<ApplyType, ApplyParent>					applys = new HashMap<ApplyType, ApplyParent>();
+    private Map<FunctionType, ApplyParent>				functions = new HashMap<FunctionType, ApplyParent>();
+    private Map<AttributeValueType, ApplyParent>		values = new HashMap<AttributeValueType, ApplyParent>();
+    private Map<AttributeDesignatorType, ApplyParent>	designators = new HashMap<AttributeDesignatorType, ApplyParent>();
+    private Map<AttributeSelectorType, ApplyParent>		selectors = new HashMap<AttributeSelectorType, ApplyParent>();
+    private Map<VariableReferenceType, ApplyParent>		variables = new HashMap<VariableReferenceType, ApplyParent>();
+    private Map<ExpressionType, ApplyParent>			expressions = new HashMap<ExpressionType, ApplyParent>();
+    	
+    public ExpressionContainer(Object parent, Object root, FunctionArgument argument) {
+		super();
+		this.setContainer(this);
+		this.parent = parent;
+		this.root = root;
+		this.argument = argument;
+		this.initialize();
+	}
+    
+    private void initialize() {
+    	if (logger.isTraceEnabled()) {
+    		logger.trace("Initializing: " + this.parent + " " + this.argument + " " + this.root);
+    	}
+    	//
+    	// Make sure we support the parent object
+    	//
+    	@SuppressWarnings("unused")
+		JAXBElement<?> rootElement = null;
+    	if (this.parent instanceof ConditionType) {
+    		rootElement = ((ConditionType) this.parent).getExpression();
+    	} else if (this.parent instanceof VariableDefinitionType) {
+    		rootElement = ((VariableDefinitionType) this.parent).getExpression();
+    	} else if (this.parent instanceof AttributeAssignmentExpressionType) {
+    		rootElement = ((AttributeAssignmentExpressionType) this.parent).getExpression();
+    	} else if (this.parent instanceof ApplyType) {
+    		//
+    		// They must tell us which argument we are
+    		//
+    		if (this.argument == null) {
+        		throw new IllegalArgumentException("Must supply Argument object when editing a parent ApplyType's child node");
+    		}
+    		//
+    		// Finish the initialization
+    		//
+    		this.initializeRoot();
+    	} else {
+    		throw new IllegalArgumentException("Unsupported Parent Object: " + this.parent.getClass().getCanonicalName());
+    	}
+    	/*
+    	//
+    	// Check if there actually is a root
+    	//
+    	if (rootElement == null || rootElement.getValue() == null) {
+    		//
+    		// Creating a new one
+    		//
+    		return;
+    	}
+		//
+		// Save the root
+		//
+		this.root = rootElement.getValue();
+		*/
+		//
+		// Finish initializing
+		//
+		this.initializeRoot();
+   }
+
+    private void initializeRoot() {
+    	//
+    	// Sanity check
+    	//
+    	if (this.root == null) {
+    		return;
+    	}
+		//
+		// Figure out the expression type
+		//
+		if (this.root instanceof ApplyType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Apply");
+		   	}
+		   	//
+			// Save it
+			//
+			this.applys.put((ApplyType) this.root, null);
+			//
+			// Determine the function for this Apply
+			//
+			Map<String, FunctionDefinition> functions = JPAUtils.getFunctionIDMap();
+			FunctionDefinition function  = functions.get(((ApplyType) this.root).getFunctionId());
+			if (function == null) {
+				logger.warn("root apply does not have a function defined");
+				return;
+			}
+			//
+			// Bring in its children
+			//
+			this.initializeChildren((ApplyType) this.root, function);
+		} else if (this.root instanceof AttributeValueType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Attribute Value");
+		   	}
+			//
+			// Save it
+			//
+			this.values.put((AttributeValueType) this.root, null);
+		} else if (this.root instanceof AttributeDesignatorType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Attribute Designator");
+		   	}
+			//
+			// Save it
+			//
+			this.designators.put((AttributeDesignatorType) this.root, null);
+		} else if (this.root instanceof AttributeSelectorType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Attribute Selector");
+		   	}
+			//
+			// Save it
+			//
+			this.selectors.put((AttributeSelectorType) this.root, null);
+		} else if (this.root instanceof VariableReferenceType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Variable Reference");
+		   	}
+			//
+			// Save it
+			//
+			this.variables.put((VariableReferenceType) this.root, null);
+		} else if (this.root instanceof FunctionType) {
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Root Is Function");
+		   	}
+			//
+			// Save it - Really? I don't think the root would ever be a function.
+			//
+			this.functions.put((FunctionType) this.root, null);
+		} else {
+			throw new IllegalArgumentException("Unsupported Expression Root Item: " + this.root.getClass().getCanonicalName());
+		}
+    }
+    
+    private void initializeChildren(ApplyType apply, FunctionDefinition function) {
+    	int index = 1;
+    	for (JAXBElement<?> child : apply.getExpression()) {
+    		//
+    		// Validate the child
+    		//
+    		if (child.getValue() == null) {
+    			logger.warn("child element " + index + "has a null object.");
+    			index++;
+    			continue;
+    		}
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Child " + index + " is " + child.getValue());
+		   	}
+    		//
+    		// Get the argument for this child
+    		//
+    		if (function == null) {
+    			throw new IllegalArgumentException("Apply has children but no function defined.");
+    		}
+    		FunctionArgument argument = XACMLFunctionValidator.getFunctionArgument(index, function);
+		   	if (logger.isTraceEnabled()) {
+		   		logger.trace("Child's argument is: " + argument);
+		   	}
+    		if (argument == null) {
+    			//throw new Exception("Unable to find function argument: " + index + " " + function.getId() + " " + function.getShortname());
+    			return;
+    		}
+			//
+			// See if its another apply type
+			//
+    		if (child.getValue() instanceof ApplyType) {
+    			//
+    			// Save it
+    			//
+    			this.applys.put((ApplyType) child.getValue(), new ApplyParent(apply, argument));
+    			//
+    			// Get its function information
+    			//
+    			Map<String, FunctionDefinition> functions = JPAUtils.getFunctionIDMap();
+    			FunctionDefinition childFunction  = functions.get(((ApplyType) child.getValue()).getFunctionId());
+    			if (childFunction == null) {
+    				logger.warn("Apply object " + index + " does not have a function defined");
+    			} else {
+	    			//
+	    			// Bring in its children
+	    			//
+	    			this.initializeChildren((ApplyType) child.getValue(), childFunction);
+    			}
+    		} else if (child.getValue() instanceof AttributeValueType) {
+    			//
+    			// Save it
+    			//
+    			this.values.put((AttributeValueType) child.getValue(), new ApplyParent(apply, argument));
+    		} else if (child.getValue() instanceof AttributeDesignatorType) {
+    			//
+    			// Save it
+    			//
+    			this.designators.put((AttributeDesignatorType) child.getValue(), new ApplyParent(apply, argument));
+    		} else if (child.getValue() instanceof AttributeSelectorType) {
+    			//
+    			// Save it
+    			//
+    			this.selectors.put((AttributeSelectorType) child.getValue(), new ApplyParent(apply, argument));
+    		} else if (child.getValue() instanceof VariableReferenceType) {
+    			//
+    			// Save it
+    			//
+    			this.variables.put((VariableReferenceType) child.getValue(), new ApplyParent(apply, argument));
+    		} else if (child.getValue() instanceof FunctionType) {
+    			//
+    			// Save it
+    			//
+    			this.functions.put((FunctionType) child.getValue(), new ApplyParent(apply, argument));
+    		} else if (child.getValue() instanceof ExpressionType) {
+    			//
+    			// Save it
+    			//
+    			this.expressions.put((ExpressionType) child.getValue(), new ApplyParent(apply, argument));
+    		} else {
+    			logger.error("Unknown child type: " + child.getClass().getCanonicalName());
+    		}
+    		index++;
+    	}
+    }
+    
+    protected boolean	isObjectSupported(Object itemId) {
+		if (itemId instanceof ApplyType ||
+			itemId instanceof AttributeValueType ||
+			itemId instanceof AttributeDesignatorType ||
+			itemId instanceof AttributeSelectorType ||
+			itemId instanceof VariableReferenceType ||
+			itemId instanceof FunctionType ||
+			itemId instanceof ExpressionType) {
+			return true;
+		}
+		return false;
+    }
+    
+    protected boolean isParentObjectSupport(Object parent) {
+		if (parent instanceof ApplyType ||
+			parent instanceof ConditionType ||
+			parent instanceof VariableDefinitionType ||
+			parent instanceof AttributeAssignmentExpressionType) {
+			return true;
+		}
+		return false;
+    }
+    
+	public void updateItem(Object itemId) {
+		//
+		// Sanity check
+		//
+		if (this.isObjectSupported(itemId) == false) {
+			return;// null;
+		}
+		//
+		// Notify - the real reason for this function
+		//
+		this.fireItemSetChange();
+		//
+		// Return the item
+		//
+		//return new ExpressionItem(itemId);
+	}
+
+	@Override
+	public Item getItem(Object itemId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		return new ExpressionItem(itemId);
+	}
+
+	@Override
+	public Collection<?> getContainerPropertyIds() {
+		return EXPRESSION_PROPERTIES;
+	}
+
+	@Override
+	public Collection<?> getItemIds() {
+		final Collection<Object> items = new ArrayList<Object>();
+		if (this.root != null) {
+			//
+			// Add the root object
+			//
+			items.add(this.root);
+			//
+			// If its an apply, it could have children
+			//
+			if (this.root instanceof ApplyType) {
+				items.add(this.getChildrenIds((ApplyType) this.root, true));
+			}
+		}
+		if (logger.isTraceEnabled()) {
+			logger.trace("getItemIds (" + items.size() + "):" + items);
+		}
+		return Collections.unmodifiableCollection(items);
+	}
+	
+	protected Collection<?> getChildrenIds(ApplyType apply, boolean recursive) {
+		Collection<Object> items = new ArrayList<Object>();
+    	for (JAXBElement<?> child : apply.getExpression()) {
+    		//
+    		// Make sure there's a value
+    		//
+    		if (child.getValue() == null) {
+    			continue;
+    		}
+    		//
+    		// What kind is it?
+    		//
+    		if (child.getValue() instanceof ApplyType) {
+    			items.add(child.getValue());
+    			//
+    			// Do we add its children?
+    			//
+    			if (recursive) {
+        			items.addAll(this.getChildrenIds((ApplyType) child.getValue(), true));
+    			}
+    		} else if (child.getValue() instanceof AttributeValueType) {
+    			items.add(child.getValue());
+    		} else if (child.getValue() instanceof AttributeDesignatorType) {
+    			items.add(child.getValue());
+    		} else if (child.getValue() instanceof AttributeSelectorType) {
+    			items.add(child.getValue());
+    		} else if (child.getValue() instanceof VariableReferenceType) {
+    			items.add(child.getValue());
+    		} else if (child.getValue() instanceof FunctionType) {
+    			items.add(child.getValue());
+    		} else if (child.getValue() instanceof ExpressionType) {
+    			items.add(child.getValue());
+    		}
+    	}		
+		if (logger.isTraceEnabled()) {
+			logger.trace("getChildrenIds " + apply.getFunctionId() + " (" + items.size() + "):" + items);
+		}
+		return items;
+	}
+
+	@Override
+	public Property<?> getContainerProperty(Object itemId, Object propertyId) {
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+        if (propertyId.equals(PROPERTY_NAME)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new ExpressionItem(itemId), EXPRESSIONITEM_NAME, null);
+        }
+
+        if (propertyId.equals(PROPERTY_ID)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new ExpressionItem(itemId), EXPRESSIONITEM_ID, null);
+        }
+		
+        if (propertyId.equals(PROPERTY_DATATYPE)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new ExpressionItem(itemId), EXPRESSIONITEM_DATATYPE, null);
+        }
+		
+        if (propertyId.equals(PROPERTY_ID_SHORT)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new ExpressionItem(itemId), EXPRESSIONITEM_ID_SHORT, null);
+        }
+		
+        if (propertyId.equals(PROPERTY_DATATYPE_SHORT)) {
+            return new MethodProperty<Object>(getType(propertyId),
+                    new ExpressionItem(itemId), EXPRESSIONITEM_DATATYPE_SHORT, null);
+        }
+		
+		return null;
+	}
+
+	@Override
+	public Class<?> getType(Object propertyId) {
+        if (propertyId.equals(PROPERTY_NAME)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_ID)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_DATATYPE)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_ID_SHORT)) {
+            return String.class;
+        }
+        if (propertyId.equals(PROPERTY_DATATYPE_SHORT)) {
+            return String.class;
+        }
+		return null;
+	}
+
+	@Override
+	public int size() {
+		int size = 0;
+		size += this.applys.size();
+		size += this.designators.size();
+		size += this.functions.size();
+		size += this.selectors.size();
+		size += this.values.size();
+		size += this.variables.size();
+		size += this.expressions.size();
+		return size;
+	}
+
+	@Override
+	public boolean containsId(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("containsId: " + itemId);
+		}
+		if (itemId instanceof ApplyType) {
+			return this.applys.containsKey(itemId);
+		}
+		if (itemId instanceof AttributeValueType) {
+			return this.values.containsKey(itemId);
+		}
+		if (itemId instanceof AttributeDesignatorType) {
+			return this.designators.containsKey(itemId);
+		}
+		if (itemId instanceof AttributeSelectorType) {
+			return this.selectors.containsKey(itemId);
+		}
+		if (itemId instanceof VariableReferenceType) {
+			return this.variables.containsKey(itemId);
+		}
+		if (itemId instanceof FunctionType) {
+			return this.functions.containsKey(itemId);
+		}
+		if (itemId instanceof ExpressionType) {
+			return this.expressions.containsKey(itemId);
+		}
+		return false;
+	}
+
+	@Override
+	public Item addItem(Object itemId) throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("Please use the addItem(Object, Object) method instead.");
+	}
+
+	@Override
+	public Object addItem() throws UnsupportedOperationException {
+		throw new UnsupportedOperationException("use addItem(Object itemId)");
+	}
+	
+	public Item addItem(Object itemId, ApplyType parent, FunctionArgument argument) throws UnsupportedOperationException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("addItem: " + itemId + " " + parent + " " + argument);
+		}
+		//
+		// Make sure we support the object
+		//
+		if (this.isObjectSupported(itemId) == false) {
+			return null;
+		}
+		//
+		// Is is a root?
+		//
+		if (parent == null) {
+			//
+			// Setting root
+			//
+			if (this.root != null) {
+				throw new UnsupportedOperationException("Cannot add another root item. Remove the current root first.");
+			}
+			//
+			// Save the root information
+			//
+			this.root = itemId;
+			//
+			// Add its children
+			//
+			this.initializeRoot();
+			//
+			// Add it to our root container
+			//
+			if (this.parent instanceof ApplyType) {
+				((ApplyType) this.parent).getExpression().add(this.createElement(this.root));
+			} else if (this.parent instanceof ConditionType) {
+				((ConditionType) this.parent).setExpression(this.createElement(this.root));
+			} else if (this.parent instanceof VariableDefinitionType) {
+				((VariableDefinitionType) this.parent).setExpression(this.createElement(this.root));
+			} else if (this.parent instanceof AttributeAssignmentExpressionType) {
+				((AttributeAssignmentExpressionType) this.parent).setExpression(this.createElement(this.root));
+			} else {
+				logger.error("unknown parent class: " + this.parent.getClass().getCanonicalName());
+			}
+			//
+			// Notify that we changed
+			//
+			this.fireItemSetChange();
+			//
+			// Return new item
+			//
+			return new ExpressionItem(this.root);
+		}
+		//
+		// Check what kind of item this is
+		//
+		if (itemId instanceof ApplyType) {
+			//
+			this.applys.put((ApplyType) itemId, new ApplyParent(parent, argument));
+			((ApplyType) parent).getExpression().add(new ObjectFactory().createApply((ApplyType) itemId));
+			//
+			// Get its function information
+			//
+			Map<String, FunctionDefinition> functions = JPAUtils.getFunctionIDMap();
+			FunctionDefinition childFunction  = functions.get(((ApplyType) itemId).getFunctionId());
+			if (childFunction == null) {
+				//
+				// NO function defined
+				//
+				logger.warn("no function defined for apply being added.");
+			} else {
+				//
+				// Add its children
+				//
+				this.initializeChildren((ApplyType) itemId, childFunction);
+			}
+		} else if (itemId instanceof AttributeValueType) {
+			//
+			this.values.put((AttributeValueType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createAttributeValue((AttributeValueType) itemId));
+			//
+		} else if (itemId instanceof AttributeDesignatorType) {
+			//
+			this.designators.put((AttributeDesignatorType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createAttributeDesignator((AttributeDesignatorType) itemId));
+			//
+		} else if (itemId instanceof AttributeSelectorType) {
+			//
+			this.selectors.put((AttributeSelectorType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createAttributeSelector((AttributeSelectorType) itemId));
+			//
+		} else if (itemId instanceof VariableReferenceType) {
+			//
+			this.variables.put((VariableReferenceType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createVariableReference((VariableReferenceType) itemId));
+			//
+		} else if (itemId instanceof FunctionType) {
+			//
+			this.functions.put((FunctionType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createFunction((FunctionType) itemId));
+			//
+		} else if (itemId instanceof ExpressionType) {
+			//
+			this.expressions.put((ExpressionType) itemId, new ApplyParent(parent, argument));
+			parent.getExpression().add(new ObjectFactory().createExpression((ExpressionType) itemId));
+		} else {
+			logger.error("unknown itemId class: " + itemId.getClass().getCanonicalName());
+			return null;
+		}
+		//
+		// Notify
+		//
+		this.fireItemSetChange();
+		return new ExpressionItem(itemId);
+	}
+	
+	private JAXBElement<?> createElement(Object item) {
+		if (item instanceof ApplyType) {
+			return new ObjectFactory().createApply((ApplyType) item);
+		} else if (item instanceof AttributeValueType) {
+			return new ObjectFactory().createAttributeValue((AttributeValueType) item);
+		} else if (item instanceof AttributeDesignatorType) {
+			return new ObjectFactory().createAttributeDesignator((AttributeDesignatorType) item);
+		} else if (item instanceof AttributeSelectorType) {
+			return new ObjectFactory().createAttributeSelector((AttributeSelectorType) item);
+		} else if (item instanceof VariableReferenceType) {
+			return new ObjectFactory().createVariableReference((VariableReferenceType) item);
+		} else if (item instanceof FunctionType) {
+			return new ObjectFactory().createFunction((FunctionType) item);
+		} else if (item instanceof ExpressionType) {
+			return new ObjectFactory().createExpression((ExpressionType) item);
+		}
+		return null;
+	}
+	
+	@Override
+	public boolean addContainerProperty(Object propertyId, Class<?> type,
+			Object defaultValue) throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeContainerProperty(Object propertyId)
+			throws UnsupportedOperationException {
+		return false;
+	}
+
+	@Override
+	public boolean removeAllItems() throws UnsupportedOperationException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("removeAllItems: ");
+		}
+		boolean result = this.doRemoveAllItems();
+		if (result == false) {
+			return false;
+		}
+		//
+		// Notify
+		//
+		this.fireItemSetChange();
+		//
+		// Done
+		//
+		return true;
+	}
+
+	public boolean doRemoveAllItems() throws UnsupportedOperationException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("doRemoveAllItems: ");
+		}
+		//
+		// Removing the root item, make sure its removed from
+		// the parent.
+		//
+		if (this.parent instanceof ConditionType) {
+			((ConditionType) this.parent).setExpression(null);
+		} else if (this.parent instanceof VariableDefinitionType) {
+			((VariableDefinitionType) this.parent).setExpression(null);
+		} else if (this.parent instanceof AttributeAssignmentExpressionType) {
+			((AttributeAssignmentExpressionType) this.parent).setExpression(null);
+		} else if (this.parent instanceof ApplyType) {
+			//
+			// TODO ?? Special case
+			//
+			return false;
+		} else {
+			return false;
+		}
+		//
+		// Null our root
+		//
+		this.root = null;
+		//
+		// Clear out our maps
+		//
+		this.applys.clear();
+		this.designators.clear();
+		this.functions.clear();
+		this.values.clear();
+		this.selectors.clear();
+		this.variables.clear();
+		this.expressions.clear();
+		//
+		// Done
+		//
+		return true;
+	}
+
+	@Override
+	public Collection<?> getChildren(Object itemId) {
+		final Collection<Object> items = new ArrayList<Object>();
+		if (itemId instanceof ApplyType) {
+			items.addAll(this.getChildrenIds((ApplyType) itemId, false));
+		}
+		if (logger.isTraceEnabled()) {
+			logger.trace("getChildren " + itemId + " (" + items.size() + "):" + items);
+		}
+		return Collections.unmodifiableCollection(items);
+	}
+	
+	public FunctionArgument getArgument(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("getArgument: " + itemId);
+		}
+		//
+		// First check if its a root
+		//
+		if (this.isRoot(itemId)) {
+			return null;
+		}
+		//
+		// Not a root - should be in the maps
+		//
+		if (itemId instanceof ApplyType) {
+			return this.applys.get(itemId).getArgument();
+		}
+		if (itemId instanceof AttributeValueType) {
+			return this.values.get(itemId).getArgument();
+		}
+		if (itemId instanceof AttributeDesignatorType) {
+			return this.designators.get(itemId).getArgument();
+		}
+		if (itemId instanceof AttributeSelectorType) {
+			return this.selectors.get(itemId).getArgument();
+		}
+		if (itemId instanceof VariableReferenceType) {
+			return this.variables.get(itemId).getArgument();
+		}
+		if (itemId instanceof FunctionType) {
+			return this.functions.get(itemId).getArgument();
+		}
+		if (itemId instanceof ExpressionType) {
+			return this.expressions.get(itemId).getArgument();
+		}
+		return null;
+	}
+
+	@Override
+	public Object getParent(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("getParent: " + itemId);
+		}
+		//
+		// First check if its a root
+		//
+		if (this.isRoot(itemId)) {
+			return null;
+		}
+		//
+		// Not a root - should be in the maps
+		//
+		if (itemId instanceof ApplyType) {
+			return this.applys.get(itemId).getApply();
+		}
+		if (itemId instanceof AttributeValueType) {
+			return this.values.get(itemId).getApply();
+		}
+		if (itemId instanceof AttributeDesignatorType) {
+			return this.designators.get(itemId).getApply();
+		}
+		if (itemId instanceof AttributeSelectorType) {
+			return this.selectors.get(itemId).getApply();
+		}
+		if (itemId instanceof VariableReferenceType) {
+			return this.variables.get(itemId).getApply();
+		}
+		if (itemId instanceof FunctionType) {
+			return this.functions.get(itemId).getApply();
+		}
+		if (itemId instanceof ExpressionType) {
+			return this.expressions.get(itemId).getApply();
+		}
+		return null;
+	}
+
+	@Override
+	public Collection<?> rootItemIds() {
+		final Collection<Object> items = new ArrayList<Object>();
+		if (this.root != null) {
+			items.add(this.root);
+		}
+		if (logger.isTraceEnabled()) {
+			logger.trace("rootItemIds " + " (" + items.size() + "):" + items);
+		}
+		return Collections.unmodifiableCollection(items);
+	}
+
+	@Override
+	public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
+		//
+		// TODO we can support this later
+		//
+		throw new UnsupportedOperationException("Should we support this? Can be tricky. Most likely user dragging an item from one area to another. For now, use removeItem, addItem.");
+	}
+
+	@Override
+	public boolean areChildrenAllowed(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("areChildrenAllowed: " + itemId);
+		}
+		if (itemId instanceof ApplyType) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed)
+			throws UnsupportedOperationException {
+		if (itemId instanceof ApplyType && areChildrenAllowed) {
+			return true;
+		}
+		if (! areChildrenAllowed) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean isRoot(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("isRoot: " + itemId);
+		}
+		if (itemId == null) {
+			logger.error("isRoot itemId is NULL");
+		}
+		return this.root == itemId;
+	}
+
+	@Override
+	public boolean hasChildren(Object itemId) {
+		if (logger.isTraceEnabled()) {
+			logger.trace("hasChildren: " + itemId);
+		}
+		if (itemId instanceof ApplyType) {
+			return ((ApplyType)itemId).getExpression().size() > 0;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean removeItem(Object itemId) throws UnsupportedOperationException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("removeItem: " + itemId);
+		}
+		//
+		// Check if they are removing the root
+		//
+		if (this.root == itemId) {
+			//
+			// Removing the root item, make sure its removed from
+			// the parent.
+			//
+			boolean result = this.doRemoveAllItems();
+			if (result == false) {
+				return false;
+			}
+			//
+			// Notify
+			//
+			this.fireItemSetChange();
+			return true;
+		}
+		//
+		// There should be a parent
+		//
+		ApplyParent parent = null;
+		//
+		// Remove the item from the maps
+		//
+		if (itemId instanceof ApplyType) {
+			parent = this.applys.get(itemId);
+			if (parent == null) {
+				return false;
+			}
+			if (this.applys.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof AttributeValueType) {
+			parent = this.values.get(itemId);
+			if (this.values.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof AttributeDesignatorType) {
+			parent = this.designators.get(itemId);
+			if (this.designators.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof AttributeSelectorType) {
+			parent = this.selectors.get(itemId);
+			if (this.selectors.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof VariableReferenceType) {
+			parent = this.variables.get(itemId);
+			if (this.variables.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof FunctionType) {
+			parent = this.functions.get(itemId);
+			if (this.functions.remove(itemId) == null) {
+				return false;
+			}
+		} else if (itemId instanceof ExpressionType) {
+			parent = this.expressions.get(itemId);
+			if (this.expressions.remove(itemId) != null) {
+				return false;
+			}
+		} else {
+			return false;
+		}
+		//
+		// Remove it from the parent Apply
+		//
+		boolean removed = false;
+		for (JAXBElement<?> element : parent.getApply().getExpression()) {
+			if (element.getValue().equals(itemId)) {
+				if (parent.getApply().getExpression().remove(element)) {
+					removed = true;
+					break;
+				}
+				break;
+			}
+		}
+		if (! removed) {
+			//
+			// Out of sync
+			//
+			logger.warn("Removing item from parent returned false, although we were able to remove it from our maps.");
+		}
+		//
+		// Notify
+		//
+		this.fireItemSetChange();
+		return true;
+	}
+
+	public class ExpressionItem implements Item {
+		private static final long serialVersionUID = 1L;
+		private final Object data;
+		
+		public ExpressionItem(Object data) {
+			this.data = data;
+		}
+		
+		public String getName() {
+			if (this.data instanceof ApplyType) {
+				if (((ApplyType) this.data).getDescription() != null) {
+					return "Apply - " + ((ApplyType) this.data).getDescription();
+				}
+				return "Apply";
+			}
+			if (this.data instanceof AttributeValueType) {
+				return "Attribute Value";
+			}
+			if (this.data instanceof AttributeDesignatorType) {
+				return "Attribute Designator";
+			}
+			if (this.data instanceof AttributeSelectorType) {
+				return "Attribute Selector";
+			}
+			if (this.data instanceof VariableReferenceType) {
+				return "Variable Reference";
+			}
+			if (this.data instanceof FunctionType) {
+				return "Function";
+			}
+			if (this.data instanceof ExpressionType) {
+				return "<Argument Placeholder>";
+			}
+			return null;
+		}
+		
+		public String getId() {
+			if (this.data instanceof ApplyType) {
+				return ((ApplyType) this.data).getFunctionId();
+			}
+			if (this.data instanceof AttributeValueType) {
+				StringBuilder builder = new StringBuilder();
+				for (Object content : ((AttributeValueType) this.data).getContent()) {
+					builder.append(content);
+				}
+				return builder.toString();
+			}
+			if (this.data instanceof AttributeDesignatorType) {
+				return ((AttributeDesignatorType) this.data).getAttributeId();
+			}
+			if (this.data instanceof AttributeSelectorType) {
+				return ((AttributeSelectorType) this.data).getPath();
+			}
+			if (this.data instanceof VariableReferenceType) {
+				return ((VariableReferenceType) this.data).getVariableId();
+			}
+			if (this.data instanceof FunctionType) {
+				return ((FunctionType) this.data).getFunctionId();
+			}
+			return null;
+		}
+		
+		public String getIdShort() {
+			String id = this.getId();
+			if (id == null) {
+				return id;
+			}
+			//
+			// Make it short
+			//
+			String[] parts = id.split("[:]");
+			
+			if (parts != null && parts.length > 0) {
+				return parts[parts.length - 1];
+			}
+			return id;
+		}
+		
+		public String getDatatype() {
+			if (this.data instanceof ApplyType) {
+				
+				Map<String, FunctionDefinition> map = JPAUtils.getFunctionIDMap();
+				FunctionDefinition function = map.get(((ApplyType) this.data).getFunctionId());
+				if (function != null) {
+					return function.getDatatypeBean().getXacmlId();
+				}
+			}
+			if (this.data instanceof AttributeValueType) {
+				return ((AttributeValueType) this.data).getDataType();
+			}
+			if (this.data instanceof AttributeDesignatorType) {
+				return ((AttributeDesignatorType) this.data).getDataType();
+			}
+			if (this.data instanceof AttributeSelectorType) {
+				return ((AttributeSelectorType) this.data).getDataType();
+			}
+
+			/*
+			if (this.data instanceof VariableReferenceType) {
+				if (this.function instanceof FunctionArgument) {
+					return ((FunctionArgument) this.function).getDatatypeBean().getXacmlId();
+				}
+			}
+			*/
+			/*
+			if (this.data instanceof FunctionType) {
+				if (this.function instanceof FunctionArgument) {
+					return ((FunctionArgument) this.function).getDatatypeBean().getXacmlId();
+				}
+			}
+			*/
+			return null;
+		}
+
+		public String getDatatypeShort() {
+			String dt = this.getDatatype();
+			if (dt == null) {
+				return dt;
+			}
+			//
+			// Get short part
+			//
+			int index = dt.lastIndexOf('#');
+			if (index == -1) {
+				String[] parts = dt.split("[:]");
+				
+				if (parts != null && parts.length > 0) {
+					return parts[parts.length - 1];
+				}
+			} else {
+				return dt.substring(index + 1);
+			}
+			return dt;
+		}
+		
+		@Override
+		public Property<?> getItemProperty(Object id) {
+            return getContainerProperty(this.data, id);
+		}
+		@Override
+		public Collection<?> getItemPropertyIds() {
+           return getContainerPropertyIds();
+		}
+		@Override
+		public boolean addItemProperty(Object id, @SuppressWarnings("rawtypes") Property property) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Expression container does not support adding new properties");
+		}
+		@Override
+		public boolean removeItemProperty(Object id) throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Expression container does not support removing properties");
+		}		
+	}
+}