http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java
new file mode 100755
index 0000000..e61e59f
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java
@@ -0,0 +1,132 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.Iterator;
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.Bag;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionBagIsIn implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML 'type'-is-in predicates as functions taking two 
arguments, the first of <code>type</code> and the second of type 
<code>Bag</code>,
+ * and returning a <code>Boolean</code> for whether the first argument is 
contained in the second.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             string-is-in
+ *             boolean-is-in
+ *             integer-is-in
+ *             double-is-in
+ *             time-is-in
+ *             date-is-in
+ *             dateTime-is-in
+ *             anyURI-is-in
+ *             hexBinary-is-in
+ *             base64Binary-is-in
+ *             dayTimeDuration-is-in (version 1 and3)
+ *             yearMonthDuration-is-in (version 1 and 3)
+ *             x500Name-is-in
+ *             rfc822Name-is-in
+ *             ipAddress-is-in
+ *             dnsName-is-in
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the elements in the Input 
argument Bag
+ * 
+ * The Output for these functions is always a Boolean.
+ */
+public class FunctionDefinitionBagIsIn<I> extends 
FunctionDefinitionBase<Boolean, I> {
+
+       
+       /**
+        * Constructor - need dataType input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionBagIsIn(Identifier idIn, DataType<I> 
dataTypeArgsIn) {
+               super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, false);
+
+       }
+
+       /**
+        * Evaluates this <code>FunctionDefinition</code> on the given 
<code>List</code> of{@link 
com.att.research.xacmlatt.pdp.policy.FunctionArgument}s.
+        * 
+        * @param evaluationContext the {@link 
com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation
+        * @param arguments the <code>List</code> of 
<code>FunctionArgument</code>s for the evaluation
+        * @return an {@link 
com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the 
call
+        */
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+
+               if (arguments == null || arguments.size() != 2) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Expected 2 arguments, got " + 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+               
+               // get the thing to look for in the bag
+               FunctionArgument elementArgument = arguments.get(0);
+
+               ConvertedArgument<I> convertedTargetArgument = new 
ConvertedArgument<I>(elementArgument, this.getDataTypeArgs(), false);
+               if ( ! convertedTargetArgument.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedTargetArgument.getStatus()));
+               }
+               
+               // Special case: Most methods want the value contained in the 
AttributeValue object inside the FunctionArgument.
+               // This one wants the AttributeValue itself.
+               // We use the ConvertedArgument constructor to validate that 
the argument is ok, then use the AttributeValue
+               // from the FunctionArgument.
+               AttributeValue<?> attributeValueElement = 
elementArgument.getValue();
+
+               // now get the bag
+               FunctionArgument bagArgument = arguments.get(1);
+               ConvertedArgument<Bag> convertedBagArgument = new 
ConvertedArgument<Bag>(bagArgument, null, true);
+
+               if ( ! convertedBagArgument.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedBagArgument.getStatus()));
+               }
+       
+               Bag bag = convertedBagArgument.getBag();
+
+               Iterator<AttributeValue<?>> iterBagContents     = 
bag.getAttributeValues();
+               while (iterBagContents.hasNext()) {
+                       AttributeValue<?> attributeValueBagContents     = 
iterBagContents.next();
+                       
+                       /*
+                        * Should we be checking the type of the bag contents 
and returning an error if the bag contents are not of the
+                        * right type?  The spec does not say this, so we just 
use the AttributeValue.equals() method for now.
+                        */
+                       if 
(attributeValueElement.equals(attributeValueBagContents)) {
+                               return ER_TRUE;
+                       }
+               }
+               
+               return ER_FALSE;
+       }
+
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java
new file mode 100755
index 0000000..03e1210
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java
@@ -0,0 +1,117 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.Bag;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionBagOneAndOnly implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML 'type'-one-and-only predicates as functions taking one 
<code>Bag</code> argument and returning the single element in that bag of the 
'type'.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             string-one-and-only
+ *             boolean-one-and-only
+ *             integer-one-and-only
+ *             double-one-and-only
+ *             time-one-and-only
+ *             date-one-and-only
+ *             dateTime-one-and-only
+ *             anyURI-one-and-only
+ *             hexBinary-one-and-only
+ *             base64Binary-one-and-only
+ *             dayTimeDuration-one-and-only (version 1 and3)
+ *             yearMonthDuration-one-and-only (version 1 and 3)
+ *             x500Name-one-and-only
+ *             rfc822Name-one-and-only
+ *             ipAddress-one-and-only
+ *             dnsName-one-and-only
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the elements in the bag 
handed to this as the Input argument, 
+ *     which is also the type of the return value
+ * 
+ */
+public class FunctionDefinitionBagOneAndOnly<I> extends 
FunctionDefinitionBase<I,I> {
+
+       
+       /**
+        * Constructor - need dataType input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionBagOneAndOnly(Identifier idIn, DataType<I> 
dataTypeArgsIn) {
+               super(idIn, dataTypeArgsIn, dataTypeArgsIn, false);
+       }
+
+       /**
+        * Evaluates this <code>FunctionDefinition</code> on the given 
<code>List</code> of{@link 
com.att.research.xacmlatt.pdp.policy.FunctionArgument}s.
+        * 
+        * @param evaluationContext the {@link 
com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation
+        * @param arguments the <code>List</code> of 
<code>FunctionArgument</code>s for the evaluation
+        * @return an {@link 
com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the 
call
+        */
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+
+               if (arguments == null || arguments.size() != 1) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + " 
Expected 1 argument, got " + 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+               
+               FunctionArgument argument = arguments.get(0);
+               ConvertedArgument<Bag> convertedArgument = new 
ConvertedArgument<Bag>(argument, null, true);
+
+               if ( ! convertedArgument.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedArgument.getStatus()));
+               }
+               
+               Bag bag = convertedArgument.getBag();
+               
+               if (bag.size() != 1) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + 
+                                       " Expected 1 but Bag has " + bag.size() 
+ " elements"));
+               }
+
+               // get the single value from the bag
+               AttributeValue<?> attributeValueOneAndOnly      = 
bag.getAttributeValues().next();
+               assert(attributeValueOneAndOnly != null);
+               
+               // make sure it has the right type
+               //
+               if 
(!this.getDataTypeId().equals(attributeValueOneAndOnly.getDataTypeId())) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + 
+                                       " Element in bag of wrong type. 
Expected " + 
+                                       
this.getShortDataTypeId(this.getDataTypeId()) + " got " + 
this.getShortDataTypeId(attributeValueOneAndOnly.getDataTypeId())));            
      
+               }
+               return ExpressionResult.newSingle(attributeValueOneAndOnly);
+       }
+
+
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java
new file mode 100755
index 0000000..af75491
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java
@@ -0,0 +1,110 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML;
+import com.att.research.xacml.std.StdAttributeValue;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.Bag;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionBagSize implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML 'type'-bag-size predicates as functions taking one 
<code>Bag</code> argument and returning an <code>Integer</code> 
+ * representing the number of elements in the bag.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             string-bag-size
+ *             boolean-bag-size
+ *             integer-bag-size
+ *             double-bag-size
+ *             time-bag-size
+ *             date-bag-size
+ *             dateTime-bag-size
+ *             anyURI-bag-size
+ *             hexBinary-bag-size
+ *             base64Binary-bag-size
+ *             dayTimeDuration-bag-size (version 1 and3)
+ *             yearMonthDuration-bag-size (version 1 and 3)
+ *             x500Name-bag-size
+ *             rfc822Name-bag-size
+ *             ipAddress-bag-size
+ *             dnsName-bag-size
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the function Input arguments
+ */
+public class FunctionDefinitionBagSize<I> extends 
FunctionDefinitionBase<BigInteger, I> {
+
+
+       /**
+        * Constructor - need dataType input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionBagSize(Identifier idIn, DataType<I> 
dataTypeArgsIn) {
+               super(idIn, DataTypes.DT_INTEGER, dataTypeArgsIn, false);
+       }
+
+       /**
+        * Evaluates this <code>FunctionDefinition</code> on the given 
<code>List</code> of{@link 
com.att.research.xacmlatt.pdp.policy.FunctionArgument}s.
+        * 
+        * @param evaluationContext the {@link 
com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation
+        * @param arguments the <code>List</code> of 
<code>FunctionArgument</code>s for the evaluation
+        * @return an {@link 
com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the 
call
+        */
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+
+               if (arguments == null || arguments.size() != 1) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Expected 1 argument, got " + 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+               
+               FunctionArgument argument = arguments.get(0);
+               ConvertedArgument<Bag> convertedArgument = new 
ConvertedArgument<Bag>(argument, null, true);
+
+               if ( ! convertedArgument.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedArgument.getStatus()));
+               }
+               
+               Bag bag = convertedArgument.getBag();
+               
+               if (bag == null) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Bag is null" ));
+
+               }
+
+
+               // type is correct, so create a wrapper and return it
+               AttributeValue<BigInteger> resultAttributeValue = new 
StdAttributeValue<BigInteger>(XACML.ID_DATATYPE_INTEGER, 
BigInteger.valueOf(bag.size()));
+               return ExpressionResult.newSingle(resultAttributeValue);
+       }
+
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java
new file mode 100755
index 0000000..390e9b2
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java
@@ -0,0 +1,165 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.datatypes.DataTypeBoolean;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionDefinition;
+
+
+/**
+ * /**
+ * FunctionDefinitionBase provides a common base for {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition}s.
+ * The child classes derived from this are of two types:
+ * <UL>
+ * <LI> Functions returning a single simple value of a type defined in {@link 
com.att.research.xacml.std.datatypes.DataTypes}.
+ *     These functions will all derive from {@link 
com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionSimple}.
+ * <LI> Functions returning a single bag with elements of a single type.
+ * <UL>
+ * <P>
+ * This base class contains the following components:
+ * <UL>
+ * <LI> The Identity for this function.
+ * <LI> The DataType of the data returned from this function.  
+ *     For Bags this means the DataType of the elements in the bag, or null if 
that is ambiguous.
+ * <LI> Commonly-used values.
+ * </UL>
+ * 
+ * @author glenngriffin
+ * 
+ * @param <O> the java class for the Output data type returned by the 
<code>FunctionDefinition</code>
+ * @param <I> the java class for the Input data type expected in the arguments 
to the <code>FunctionDefinition</code>.  
+ *             Some functions have non-homogeneous arguments but may still 
have a main 'type'.
+ */
+public abstract class FunctionDefinitionBase<O,I> implements 
FunctionDefinition {
+       
+       // The XACML identifier string for this particular function
+       private Identifier      id;
+       
+       // each function derived from this returns a single non-bag data value 
of the following type, or a Bag containing elements of this type
+       private DataType<O>     dataTypeReturn;
+       
+       // All functions have input arguments and expect them to be of a given 
type.
+       // In some instances the argument gets multiple values of different 
types, but when the function has a 'type' associated with it's name
+       // specific ones of the input must be of this type.
+       // When an argument Input to the function is a Bag, the elements in 
that bag will be of this type.
+       // This corresponds most closely to the 'type' in the function name (as 
in 'type'-bag or 'type'-equals).
+       private DataType<I> dataTypeArgs;
+       
+       // true = the return value from this function is a bag; false = return 
value is a single-value DataType object
+       private boolean returnsBag;
+       
+       /*
+        * For functions that return a Boolean result we create a single 
instance of the True/False return values that they can share
+        */
+       protected static final ExpressionResult                 ER_TRUE         
= ExpressionResult.newSingle(DataTypeBoolean.AV_TRUE);
+       protected static final ExpressionResult                 ER_FALSE        
= ExpressionResult.newSingle(DataTypeBoolean.AV_FALSE);
+       
+       /**
+        * Creates a new <code>FunctionDefinitionBase</code> with the {@link 
com.att.research.xacml.api.Identifier} <code>idIn</code> as
+        * the function id.
+        * 
+        * @param idIn the <code>Identifier</code> for this 
<code>FunctionDefinitionBase</code>
+        */
+       protected FunctionDefinitionBase(Identifier idIn, DataType<O> 
returnDataTypeIn, DataType<I> argumentDataTypeIn, boolean returnsBagIn) {
+               this.id                 = idIn;
+               this.dataTypeReturn = returnDataTypeIn;
+               this.dataTypeArgs = argumentDataTypeIn;
+               this.returnsBag = returnsBagIn;
+       }
+       
+       /**
+        * Returns a shortened version of the Id for this function, primarilly 
for use with error messages to prevent them from becoming too long.
+        * This is a simple convenience method to reduce code bloat.
+        * 
+        * @return
+        */
+       public String getShortFunctionId() {
+               return 
this.getId().getUri().toString().substring(this.getId().getUri().toString().indexOf("function:"));
+       }
+       
+       /**
+        * Returns a shortened version of the given DataType Id, primarily for 
use with error messages to prevent them from becoming too long.
+        * This is a simple convenience method to reduce code bloat.
+        * 
+        * @param identifier expected to have '#' in it, and if no '#' should 
have ":data-type:"
+        * @return
+        */
+       public String getShortDataTypeId(Identifier identifier) {
+               String idString = identifier.stringValue();
+               int index = idString.indexOf("#");
+               if (index < 0) {
+                       index = idString.indexOf(":data-type:");
+                       if (index < 0) {
+                               return idString;
+                       } else {
+                               return idString.substring(index + 11);
+                       }
+               } else {
+                       return idString.substring(index+1);
+               }
+       }
+       
+       /**
+        * Return a new Status that includes the name of this function in front 
of the original status' message.
+        * This is a convenience method to reduce code bloat.
+        * 
+        * @param originalStatu
+        * @return
+        */
+       public Status getFunctionStatus(Status originalStatus) {
+               return new StdStatus(originalStatus.getStatusCode(), 
getShortFunctionId() + " " + originalStatus.getStatusMessage());
+       }
+       
+       
+       //
+       // Getters for the internal variables
+       //
+       
+       @Override
+       public Identifier getId() {
+               return this.id;
+       }
+       
+       @Override
+       public Identifier getDataTypeId() {
+               if (this.dataTypeReturn == null) {
+                       return null;
+               } else {
+                       return this.dataTypeReturn.getId();
+               }
+       }
+       
+       public DataType<O> getDataType() {
+               return this.dataTypeReturn;
+       }
+       
+       /**
+        * Return the Identifier for the Input Argument(s) DataType.
+        * 
+        * @return
+        */
+       public DataType<I> getDataTypeArgs() {
+               return this.dataTypeArgs;
+       }
+       
+       @Override
+       public boolean returnsBag() {
+               return returnsBag;
+       }
+       
+       
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java
new file mode 100755
index 0000000..a6af460
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java
@@ -0,0 +1,136 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionComparison implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML comparison predicates as functions taking two arguments 
of the same type
+ * and returning a <code>Boolean</code>.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             integer-greater-than
+ *             integer-greater-than-or-equal
+ *             integer-less-than
+ *             integer-less-than-or-equal      
+ *             double-greater-than
+ *             double-greater-than-or-equal
+ *             double-less-than
+ *             double-less-than-or-equal 
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the function Input arguments
+ */
+public class FunctionDefinitionComparison<I extends Comparable<I>> extends 
FunctionDefinitionHomogeneousSimple<Boolean, I> {
+
+       /**
+        * List of comparison operations.
+        * 
+        * @author glenngriffin
+        *
+        */
+       public enum OPERATION {GREATER_THAN, GREATER_THAN_EQUAL, LESS_THAN, 
LESS_THAN_EQUAL };
+       
+       // the operation for this instance of the class
+       private OPERATION operation;
+       
+       
+       /**
+        * Constructor - need dataType input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionComparison(Identifier idIn, DataType<I> 
dataTypeArgsIn, OPERATION opIn) {
+               super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, 2);
+               operation = opIn;
+       }
+
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+
+               List<I> convertedArguments      = new ArrayList<I>();
+               Status status                           = 
this.validateArguments(arguments, convertedArguments);
+               
+               /*
+                * If the function arguments are not correct, just return an 
error status immediately
+                */
+               if 
(!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) {
+                       return 
ExpressionResult.newError(getFunctionStatus(status));
+               }
+               
+               int compareResult;
+               try {
+                       compareResult = 
((I)convertedArguments.get(0)).compareTo((I)convertedArguments.get(1));
+               } catch (Exception e) {
+                       String message = e.getMessage();
+                       if (e.getCause() != null) {
+                               message = e.getCause().getMessage();
+                       }
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+               }
+
+               switch (operation) {
+               case GREATER_THAN:
+                       if (compareResult > 0) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+                       
+               case GREATER_THAN_EQUAL:
+                       if (compareResult > -1) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+                       
+               case LESS_THAN:
+                       if (compareResult < 0) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+                       
+               case LESS_THAN_EQUAL:
+                       if (compareResult < 1) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+               }
+       
+               // switch on enum should handle everything - should never get 
here
+               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " ENUM did not cover case of " + operation));
+
+       }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java
new file mode 100755
index 0000000..5530065
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java
@@ -0,0 +1,125 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+
+import java.util.List;
+
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.DataTypeException;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.IDateTime;
+import com.att.research.xacml.std.datatypes.ISO8601Duration;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionDateTimeArithmetic implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML Date and Time Arithmetic predicates.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             dateTime-add-dayTimeDuration
+ *             dateTime-add-yearMonthDuration
+ *             dateTime-subtract-dayTimeDuration
+ *             dateTime-subtract-yearMonthDuration
+ *             date-add-yearMonthDuration
+ *             date-subtract-yearMonthDuration
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the function Input arguments;
+ *             SPECIAL CASE: this applies ONLY to the 2nd argument.
+ * @param <O> the java class for the data type of the function Output;
+ *             SPECIAL CASE: this ALSO applies to the type of the 1st Input 
argument.
+ */
+public class FunctionDefinitionDateTimeArithmetic<O extends IDateTime<O>, I 
extends ISO8601Duration> extends FunctionDefinitionBase<O, I> {
+
+       /**
+        * List of Date and Time Arithmetic operations.
+        * 
+        * @author glenngriffin
+        *
+        */
+       public enum OPERATION {ADD, SUBTRACT};
+       
+       // operation to be used in this instance of the class
+       private final OPERATION operation;
+
+       
+       
+       /**
+        * Constructor - need dataTypeArgs input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionDateTimeArithmetic(Identifier idIn, 
DataType<O> dataTypeIn, DataType<I> dataTypeArgsIn, OPERATION op) {
+               super(idIn, dataTypeIn, dataTypeArgsIn, false);
+               this.operation = op;
+       }
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+               if (arguments == null ||  arguments.size() != 2) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " Expected 2 arguments, got " + 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+               
+               // first arg has same type as function output
+               FunctionArgument functionArgument = arguments.get(0);
+               ConvertedArgument<O> convertedArgument0 = new 
ConvertedArgument<O>(functionArgument, this.getDataType(), false);
+               if ( ! convertedArgument0.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedArgument0.getStatus()));
+               }
+               O idateOrig     = convertedArgument0.getValue();
+               
+               // second argument is of input type
+               functionArgument = arguments.get(1);
+               ConvertedArgument<I> convertedArgument1 = new 
ConvertedArgument<I>(functionArgument, this.getDataTypeArgs(), false);
+               if ( ! convertedArgument1.isOk()) {
+                       return 
ExpressionResult.newError(getFunctionStatus(convertedArgument1.getStatus()));
+               }
+               // get the Duration object from the argument which includes all 
fields, even if the incoming argument does not include them all
+               ISO8601Duration duration = convertedArgument1.getValue();
+               
+               // add/subtract the duration to the input argument
+               //
+               O idateResult   = null;
+               switch(this.operation) {
+               case ADD:
+                       idateResult     = idateOrig.add(duration);
+                       break;
+               case SUBTRACT:
+                       idateResult     = idateOrig.sub(duration);
+                       break;
+               }
+               ExpressionResult expressionResult       = null;
+               try {
+                       expressionResult        = 
ExpressionResult.newSingle(this.getDataType().createAttributeValue(idateResult));
 
+               } catch (DataTypeException e) {
+                       String message = e.getMessage();
+                       if (e.getCause() != null) {
+                               message = e.getCause().getMessage();
+                       }
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));                 
+               }
+               return expressionResult; 
+       }
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java
new file mode 100755
index 0000000..af5c1e6
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java
@@ -0,0 +1,88 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionEquality extends {@link 
com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple}
 to
+ * implement the XACML Equality predicates as functions taking two arguments 
of the same data type and returning a <code>Boolean</code>.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             string-equal
+ *             boolean-equal
+ *             integer-equal
+ *             double-equal
+ *             date-equal
+ *             time-equal
+ *             dateTime-equal
+ *             dayTimeDuration-equal
+ *             yearMonthDuration-equal
+ *             anyURI-equal
+ * 
+ * @author car
+ * @version $Revision: 1.2 $
+ * 
+ * @param <I> the java class for the data type of the function Input arguments
+ */
+public class FunctionDefinitionEquality<I> extends 
FunctionDefinitionHomogeneousSimple<Boolean, I> {
+       
+       /**
+        * Determines if the two <code>T</code> values are equal using the java 
<code>equals</code> method.  Derived classes
+        * may override this if the <code>equals</code> method is not 
sufficient.
+        * 
+        * @param v1 the first object to compare
+        * @param v2 the second object to compare
+        * @return true if the two objects are the same, else false
+        */
+       protected boolean isEqual(I v1, I v2) {
+               return v1.equals(v2);
+       }
+       
+       public FunctionDefinitionEquality(Identifier idIn, DataType<I> 
dataTypeArgsIn) {
+               super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, 2);
+       }
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+               List<I> convertedArguments      = new ArrayList<I>();
+               Status status                           = 
this.validateArguments(arguments, convertedArguments);
+               
+               /*
+                * If the function arguments are not correct, just return an 
error status immediately
+                */
+               if 
(!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) {
+                       return 
ExpressionResult.newError(getFunctionStatus(status));
+               }
+               
+               /*
+                * Now just perform the equality operation.
+                */
+               if (this.isEqual(convertedArguments.get(0), 
convertedArguments.get(1))) {
+                       return ER_TRUE;
+               } else {
+                       return ER_FALSE;
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java
new file mode 100755
index 0000000..515cbd5
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java
@@ -0,0 +1,523 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.IdentifierImpl;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.Bag;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue;
+import com.att.research.xacmlatt.pdp.policy.FunctionDefinition;
+import com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory;
+
+/**
+ * FunctionDefinitionSet implements {@link 
com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to
+ * implement the XACML Set predicates as functions taking two arguments of 
<code>Bag</code> the same primitive type
+ * and returning either a <code>Boolean</code> or a <code>Bag</code> of the 
same primitive type.
+ * <P>
+ * The ipAddress, dnsName and xPathExpression do not have set functions 
defined for them in section 10.2.8 of the Release 3 XACML spec.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             string-bag
+ *             boolean-bag
+ *             integer-bag
+ *             double-bag
+ *             time-bag
+ *             date-bag
+ *             dateTime-bag
+ *             anyURI-bag
+ *             hexBinary-bag
+ *             base64Binary-bag
+ *             dayTimeDuration-bag (version 1 and3)
+ *             yearMonthDuration-bag (version 1 and 3)
+ *             x500Name-bag
+ *             rfc822Name-bag
+ * 
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <I> the java class for the data type of the function Input arguments
+ * @param <O> the java class for the data type of the function Output
+ */
+public class FunctionDefinitionHigherOrderBag<O,I> extends 
FunctionDefinitionBase<O, I> {
+
+       /**
+        * List of comparison operations.
+        * 
+        * @author glenngriffin
+        *
+        */
+       public enum OPERATION {ANY_OF, ALL_OF, ANY_OF_ANY, ALL_OF_ANY, 
ANY_OF_ALL, ALL_OF_ALL, MAP  };
+       
+       // the operation for this instance of the class
+       private OPERATION operation;
+       
+       
+       /**
+        * Constructor - need dataType input because of java Generic 
type-erasure during compilation.
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        */
+       public FunctionDefinitionHigherOrderBag(Identifier idIn, DataType<O> 
dataTypeIn, DataType<I> dataTypeArgsIn, OPERATION opIn) {
+               super(idIn, dataTypeIn, dataTypeArgsIn, ((opIn == 
OPERATION.MAP) ? true : false) );
+               operation = opIn;
+       }
+
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+
+               // simple argument check
+               if (arguments == null || arguments.size() < 2) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " Expected at least 2 arguments, got " 
+ 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+               
+               // three functions have some things known about the arguments
+               if (operation == OPERATION.ALL_OF_ANY || operation == 
OPERATION.ANY_OF_ALL || operation == OPERATION.ALL_OF_ALL) {
+                       if (arguments.size() != 3) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " Expected 3 arguments, got " + 
arguments.size()) );
+                       }
+                       // the 2nd & 3rd arguments must both be bags
+                       if ( arguments.get(1) == null || ! 
arguments.get(1).isBag() ) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                               " 2nd argument must be bag, got 
'" + ((arguments.get(1) == null) ? "null" : 
this.getShortDataTypeId(arguments.get(1).getValue().getDataTypeId())) + "'" ));
+                       }
+                       if (arguments.get(2) == null || ! 
arguments.get(2).isBag() ) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                               " 3rd argument must be bag, got 
'" + ((arguments.get(2) == null) ? "null" : 
this.getShortDataTypeId(arguments.get(2).getValue().getDataTypeId())) + "'" ));
+                       }
+               }
+               
+               // first argument is supposed to be a Function ID passed to us 
as an AnyURI
+               FunctionArgument functionIdArgument = arguments.get(0);
+               if (functionIdArgument == null || functionIdArgument.getValue() 
== null) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " Predicate Function (first argument) 
was null"));
+               }
+               if ( ! 
functionIdArgument.getValue().getDataTypeId().equals(DataTypes.DT_ANYURI.getId()))
 {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " First argument expected URI, got " + 
functionIdArgument.getValue().getDataTypeId() ) );
+               }
+               Identifier functionId = new IdentifierImpl((URI) 
functionIdArgument.getValue().getValue());
+               
+               // look up the actual function definition based on that ID
+               StdFunctionDefinitionFactory fdf = new 
StdFunctionDefinitionFactory();
+               
+               FunctionDefinition predicate = 
fdf.getFunctionDefinition(functionId);
+               
+               if (predicate == null) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " First argument was not URI of a 
function, got '" + functionId + "'") );
+               }
+               // in all cases except MAP, the predicate must return True/False
+               if (operation != OPERATION.MAP) {
+                       if ( ! 
predicate.getDataTypeId().equals(DataTypes.DT_BOOLEAN.getId())) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                               " Predicate Function must 
return boolean, but '" + predicate.getId() + "' returns '" + 
this.getShortDataTypeId(predicate.getDataTypeId()) ));
+                       }
+               }
+               
+               
+               
+               // The remaining arguments may be either bags or primitive 
types.
+               // We do not know what the primitive types will be, and do not 
concern ourselves about that here 
+               // (the predicate function we just got and will call later will 
complain if they do not match its expectations).
+               // The predicate function will want things as 
FunctionAttributes, so we do not need to unwrap anything.
+               boolean bagSeen = false;
+               for (int i = 1; i < arguments.size(); i++) {
+                       FunctionArgument argument = arguments.get(i);
+                       if (argument == null) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                               " Got null argument at index " 
+ i) );
+                       }
+                       // force evaluation and check status
+                       if ( ! argument.getStatus().isOk()) {
+                               return 
ExpressionResult.newError(getFunctionStatus(argument.getStatus()));
+                       }
+
+                       // for bags, remember that we saw one; for non-bag 
primitives, check that the primitive value is not null
+                       if (argument.isBag()) {
+                               bagSeen = true;
+                       } else {
+                               if (argument.getValue() == null || 
argument.getValue().getValue() == null) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Got null attribute at 
index " + i) );
+                               }
+                       }
+               }
+
+               // all functions require at least one bag
+               if ( ! bagSeen && operation != OPERATION.ANY_OF_ANY) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                       " Did not get any Bag argument; must 
have at least 1") );
+               }
+               
+               
+               // arguments are ready for use
+               
+               // list of arguments for passing to the predicate
+               List<FunctionArgument> predicateArguments = new 
ArrayList<FunctionArgument>();
+
+               // for functions that take a single bag, which index is that 
bag at
+               int indexOfBagInOriginalArgs = -1;
+               
+               // bag iterator
+               Iterator<AttributeValue<?>> bagIterator1;
+               Iterator<AttributeValue<?>> bagIterator2;
+
+               
+               
+               
+               switch (operation) {
+               
+               case ANY_OF:
+                       // Copy the primitive arguments to the list for passing 
to the predicate,
+                       // putting a place-holder in for the value from the 
(single) bag
+                       for (int i = 1; i < arguments.size(); i++) {
+                               predicateArguments.add(arguments.get(i));
+                               if (arguments.get(i).isBag()) {
+                                       if (indexOfBagInOriginalArgs == -1) {
+                                               indexOfBagInOriginalArgs = i ;
+                                       } else {
+                                               // bag already found - we 
should have only one
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " must have 
only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at 
" + i) );
+                                       }
+                               }
+                       }
+                       
+                       // get each primitive value in turn
+                       bagIterator1 = 
arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues();
+                       while (bagIterator1.hasNext()) {
+                               // all of the predicate arguments have been 
created except that the one from the bag needs to replace the place-holder in 
the list
+                               predicateArguments.set(indexOfBagInOriginalArgs 
- 1, new FunctionArgumentAttributeValue(bagIterator1.next()));
+                               ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                               if ( ! res.isOk()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Predicate error: " + 
res.getStatus().getStatusMessage()) );
+                               }
+                               if ( (Boolean)(res.getValue().getValue()) == 
true) {
+                                       return ER_TRUE;
+                               }
+                       }
+
+                       return ER_FALSE;
+                       
+                       
+                       
+               case ALL_OF:
+                       // Copy the primitive arguments to the list for passing 
to the predicate,
+                       // putting a place-holder in for the value from the 
(single) bag
+                       for (int i = 1; i < arguments.size(); i++) {
+                               predicateArguments.add(arguments.get(i));
+                               if (arguments.get(i).isBag()) {
+                                       if (indexOfBagInOriginalArgs == -1) {
+                                               indexOfBagInOriginalArgs = i ;
+                                       } else {
+                                               // bag already found - we 
should have only one
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " must have 
only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at 
" + i) );
+                                       }
+                               }
+                       }
+                       
+                       // get each primitive value in turn
+                       bagIterator1 = 
arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues();
+                       while (bagIterator1.hasNext()) {
+                               // all of the predicate arguments have been 
created except that the one from the bag needs to replace the place-holder in 
the list
+                               predicateArguments.set(indexOfBagInOriginalArgs 
- 1, new FunctionArgumentAttributeValue(bagIterator1.next()));
+                               ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                               if ( ! res.isOk()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Predicate error: " + 
res.getStatus().getStatusMessage()) );
+                               }
+                               if ( (Boolean)(res.getValue().getValue()) == 
false) {
+                                       return ER_FALSE;
+                               }
+                       }
+                       return ER_TRUE;
+               
+                       
+               case ANY_OF_ANY:
+                       // empty bags can give odd error messages, so check 
here and return something that makes more sense
+                       for (int i = 1; i < arguments.size(); i++) {
+                               if (arguments.get(i).isBag() && 
arguments.get(i).getBag().size() == 0) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Bag is empty at index 
" + i ));
+                               }
+                       }
+                       // This is different from all the other Higher-order 
bag functions because it can take an unbounded number of arguments any/all of 
which may be bags.
+                       // (The others take either an unbounded number of args 
of which exactly 1 is a bag, or they take exactly 2 bags)
+                       // To handle the possibility of multiple bags without 
knowing a priori how many there might be,
+                       // we first create all possible lists of arguments to 
be passed to the predicate.
+                       // This is done using a depth-first search of the total 
argument space.
+                       List<List<FunctionArgument>> listOfPredicateLists = new 
ArrayList<List<FunctionArgument>>();            
+                       
+                       /*
+                        * Start the recursive append process
+                        */
+                       appendCrossProduct(new ArrayList<FunctionArgument>(), 
arguments.subList(1, arguments.size()), 0, listOfPredicateLists);
+                       
+                       // we now have all possible argument lists for the 
predicate to work on, so do the ANY operation now
+                       for (List<FunctionArgument> predicateArgumentList : 
listOfPredicateLists) {
+                               // all of the predicate arguments have been 
created except that the one from the bag needs to replace the place-holder in 
the list
+                               ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArgumentList);
+                               if ( ! res.isOk()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Predicate error: " + 
res.getStatus().getStatusMessage()) );
+                               }
+                               if ( (Boolean)(res.getValue().getValue()) == 
true) {
+                                       return ER_TRUE;
+                               }
+                       }
+                       
+                       // if we get here then none of the combinations gave a 
TRUE result
+                       return ER_FALSE;
+               
+                       
+                       
+               case ALL_OF_ANY:
+//TODO - it might be more efficient to extract all the attributes from the 
first bag and convert them to FunctionArguments just once, then use that list 
each time
+                       
+                       // get the element from the 2nd bag that we want to 
check all elements from the 1st bag against
+                       bagIterator2 = 
arguments.get(2).getBag().getAttributeValues();
+                       while (bagIterator2.hasNext()) {
+                               FunctionArgument predicateArgument2 = new 
FunctionArgumentAttributeValue(bagIterator2.next());
+                               boolean allMatch = true;
+                               
+                               // now look at every value of the first bag 
operating with the selected value from the 2nd
+                               bagIterator1 = 
arguments.get(1).getBag().getAttributeValues();
+                               while (bagIterator1.hasNext()) {
+
+                                       predicateArguments.clear();
+                                       predicateArguments.add(new 
FunctionArgumentAttributeValue(bagIterator1.next()));
+                                       
predicateArguments.add(predicateArgument2);
+                                       
+                                       ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                                       if ( ! res.isOk()) {
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " Predicate 
error: " + res.getStatus().getStatusMessage()) );
+                                       }
+                                       if ( 
(Boolean)(res.getValue().getValue()) == false) {
+                                               allMatch = false;
+                                               break;
+                                       }
+                               }
+                               if (allMatch) {
+                                       // wee found one value in bag2 that 
works (is TRUE) for all values in bag1
+                                       return ER_TRUE;
+                               }
+                               // this value from bag2 did not work, so get 
the next one
+                       }
+                       
+                       // no value in bag2 worked for all values of bag1
+                       return ER_FALSE;
+
+                       
+                       
+               case ANY_OF_ALL:
+//TODO - it might be more efficient to extract all the attributes from the 2nd 
bag and convert them to FunctionArguments just once, then use that list each 
time
+                       
+                       // get the element from the 1st bag that we want to 
check all elements from the 1st bag against
+                       bagIterator1 = 
arguments.get(1).getBag().getAttributeValues();
+                       while (bagIterator1.hasNext()) {
+                               FunctionArgument predicateArgument1 = new 
FunctionArgumentAttributeValue(bagIterator1.next());
+                               boolean allMatch = true;
+                               
+                               // now look at every value of the 2nd bag 
operating with the selected value from the first
+                               bagIterator2 = 
arguments.get(2).getBag().getAttributeValues();
+                               while (bagIterator2.hasNext()) {
+                                       predicateArguments.clear();
+                                       
predicateArguments.add(predicateArgument1);
+                                       predicateArguments.add(new 
FunctionArgumentAttributeValue(bagIterator2.next()));
+                                       
+                                       ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                                       if ( ! res.isOk()) {
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " Predicate 
error: " + res.getStatus().getStatusMessage()) );
+                                       }
+                                       if ( 
(Boolean)(res.getValue().getValue()) == false) {
+                                               allMatch = false;
+                                               break;
+                                       }
+                               }
+                               if (allMatch) {
+                                       // wee found one value in bag1 that 
works (is TRUE) for all values in bag2
+                                       return ER_TRUE;
+                               }
+                               // this value from bag1 did not work, so get 
the next one
+                       }
+                       
+                       // no value in bag1 worked for all values of bag2
+                       return ER_FALSE;
+                       
+                       
+                       
+               case ALL_OF_ALL:
+//TODO - it might be more efficient to extract all the attributes from the 2nd 
bag and convert them to FunctionArguments just once, then use that list each 
time
+
+                       // get the element from the 1st bag that we want to 
check all elements from the 1st bag against
+                       bagIterator1 = 
arguments.get(1).getBag().getAttributeValues();
+                       while (bagIterator1.hasNext()) {
+                               FunctionArgument predicateArgument1 = new 
FunctionArgumentAttributeValue(bagIterator1.next());
+
+                               // now look at every value of the 2nd bag 
operating with the selected value from the first
+                               bagIterator2 = 
arguments.get(2).getBag().getAttributeValues();
+                               while (bagIterator2.hasNext()) {
+                                       predicateArguments.clear();
+                                       
predicateArguments.add(predicateArgument1);
+                                       predicateArguments.add(new 
FunctionArgumentAttributeValue(bagIterator2.next()));
+
+                                       ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                                       if ( ! res.isOk()) {
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " Predicate 
error: " + res.getStatus().getStatusMessage()) );
+                                       }
+
+                                       if ( 
(Boolean)(res.getValue().getValue()) == false) {
+                                               return ER_FALSE;
+                                       }
+                               }
+                               // this value did not fail, so try the next
+                       }
+                       
+                       // everything in bag1 worked (was true) for everything 
in bag 2
+                       return ER_TRUE;
+                       
+                       
+                       
+               case MAP:
+                       // Copy the primitive arguments to the list for passing 
to the predicate,
+                       // putting a place-holder in for the value from the 
(single) bag
+                       for (int i = 1; i < arguments.size(); i++) {
+                               predicateArguments.add(arguments.get(i));
+                               if (arguments.get(i).isBag()) {
+                                       if (indexOfBagInOriginalArgs == -1) {
+                                               indexOfBagInOriginalArgs = i ;
+                                       } else {
+                                               // bag already found - we 
should have only one
+                                               return 
ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                               " must have 
only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at 
" + i) );
+                                       }
+                               }
+                       }
+                       
+                       Bag outputBag = new Bag();
+                       
+                       // get each primitive value in turn
+                       bagIterator1 = 
arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues();
+                       while (bagIterator1.hasNext()) {
+                               // all of the predicate arguments have been 
created except that the one from the bag needs to replace the place-holder in 
the list
+                               predicateArguments.set(indexOfBagInOriginalArgs 
- 1, new FunctionArgumentAttributeValue(bagIterator1.next()));
+                               ExpressionResult res = 
predicate.evaluate(evaluationContext, predicateArguments);
+                               if ( ! res.isOk()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Predicate error: " + 
res.getStatus().getStatusMessage()) );
+                               }
+                               if (res.isBag()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ 
+                                                       " Cannot put bag inside 
bag; predicate was '" + predicate.getId() + "'"));
+                               }
+                               outputBag.add(res.getValue());
+                       }
+                       
+                       
+                       return ExpressionResult.newBag(outputBag);
+                       
+               }
+       
+               // all cases should have been covered by above - should never 
get here
+               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Could not evaluate Higher-Order Bag function " + operation));
+
+       }
+
+
+       
+       
+       
+       
+       
+       
+       
+       
+       
+       
+       /**
+        * Performs the depth-first walk to generate argument lists.  Needed by 
any-of-any because of the variable number of bags it might get.
+        * 
+        * This code was salvaged from the R2 version of the product and 
adjusted to fit the new way of doing business.
+        * 
+        * @param argListInProgress the current argument list being generated 
in this pass
+        * @param valueList the list of expression result values 
+        * @param nPosition the position within the expression result values to 
use to append to the base argument list
+        * @param listArgLists the <code>List</code> where final argument lists 
are appended
+        */
+       private static void appendCrossProduct(List<FunctionArgument> 
argListInProgress, List<FunctionArgument> valueList, int nPosition, 
List<List<FunctionArgument>> listArgLists) {
+               /*
+                * Have we hit a leaf?
+                */
+               if (nPosition >= valueList.size()) {
+                       List<FunctionArgument>  copy    = new 
ArrayList<FunctionArgument>();
+                       copy.addAll(argListInProgress);
+                       listArgLists.add(copy);
+                       return;
+               }
+               
+               /*
+                * Check to see if the value at the current position is a 
primitive or a bag
+                */
+               FunctionArgument        FunctionArgument        = 
valueList.get(nPosition);
+               if (FunctionArgument.isBag() && 
FunctionArgument.getBag().getAttributeValues() != null && 
FunctionArgument.getBag().size() > 0) {
+                       Iterator<AttributeValue<?>>     iterBagValues   = 
FunctionArgument.getBag().getAttributeValues();
+                       while (iterBagValues.hasNext()) {
+                               AttributeValue<?>       attributeValue  = 
iterBagValues.next();
+                               FunctionArgument        functionArgument        
= new FunctionArgumentAttributeValue(attributeValue);
+                               argListInProgress.add(functionArgument);
+                               appendCrossProduct(argListInProgress, 
valueList, nPosition+1, listArgLists);
+                               
argListInProgress.remove(argListInProgress.size()-1);
+                       }
+               } else {
+                       /*
+                        * This is a simple value, so we can just append to the 
argListInProgress and continue the recursion
+                        */
+                       argListInProgress.add(FunctionArgument);
+                       appendCrossProduct(argListInProgress, valueList, 
nPosition+1, listArgLists);
+                       argListInProgress.remove(argListInProgress.size()-1);
+               }
+       }
+       
+       
+       
+       
+       
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java
new file mode 100755
index 0000000..a41ccbe
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java
@@ -0,0 +1,142 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.List;
+
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionHomogeneousSimple extends {@link 
com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionSimple}
+ * with utility methods for ensuring the types of the arguments passed in the 
<code>evaluate</code> method matches the parameterized
+ * type, and the number of arguments is correct.
+ * When evaluated the resulting arguments must be simple data types, not bags.
+ * 
+ * The various functions have the following needs with respect to their 
arguments:
+ * <UL>
+ * <LI>
+ * The argument list size is pre-defined and all arguments can be evaluated at 
once before the function is called.
+ * <LI>
+ * The argument list size is pre-defined but the arguments must be evaluated 
one at a time by the function.
+ * <LI>
+ * The argument list size is not pre-defined.
+ * </UL>
+ * To support those needs this class includes methods for checking the list 
size and evaluating a single argument as well as
+ * combining those operations in a single method to make it simpler for the 
calling function.
+ * 
+ * @author car
+ * @version $Revision: 1.3 $
+ *
+ * @param <O> the java class for the value of the Output return result from 
the <code>FunctionDefinition</code>
+ * @param <I> the java class for the value of the Input {@link 
com.att.research.xacmlatt.pdp.policy.FunctionArgument}s in the 
<code>evaluate</code> method
+ */
+public abstract class FunctionDefinitionHomogeneousSimple<O,I> extends 
FunctionDefinitionBase<O,I> {
+       
+
+       // null means that number of arguments is variable
+       private Integer                 numArgs;
+       
+       /**
+        * Constructor
+        * 
+        * @param idIn
+        * @param dataTypeReturnIn
+        * @param dataTypeArgsIn
+        * @param nArgs
+        */
+       public FunctionDefinitionHomogeneousSimple(Identifier idIn, DataType<O> 
dataTypeReturnIn, DataType<I> dataTypeArgsIn, Integer nArgs) {
+               super(idIn, dataTypeReturnIn, dataTypeArgsIn, false);
+               this.numArgs            = nArgs;
+       }
+       
+
+       /**
+        * Gets the number of arguments expected to this 
<code>FunctionDefinition</code>.
+        * For functions without a pre-defined number of arguments this is not 
used.
+        * 
+        * @return the number of arguments expected to this 
<code>FunctionDefinition</code>.
+        */
+       public Integer getNumArgs() {
+               return this.numArgs;
+       }
+       
+       
+       /**
+        * Validates the given <code>List</code> of 
<code>FunctionArgument</code>s has the correct count and <code>DataType</code> 
and evaluates expressions.
+        * This combines both the argument list length check and the evaluation 
of all arguments on that list.
+        * 
+        * @param listFunctionArguments the <code>List</code> of 
<code>FunctionArgument</code>s to validate
+        * @return a {@link com.att.research.xacml.api.Status} indication with 
an error if the arguments are not valid
+        */
+       public Status validateArguments(List<FunctionArgument> 
listFunctionArguments, List<I> convertedValues) {
+               /*
+                * See if we have to validate the number of arguments
+                */
+               Status listLengthStatus = 
validateArgumentListLength(listFunctionArguments);
+               if ( ! listLengthStatus.isOk()) {
+                       return listLengthStatus;
+               }
+               
+               
+               /*
+                * Now validate the types of the arguments
+                */
+               for (int i = 0; i < listFunctionArguments.size(); i++) {
+                       FunctionArgument functionArgument = 
listFunctionArguments.get(i);
+                       ConvertedArgument<I> argument = new 
ConvertedArgument<I>(functionArgument, getDataTypeArgs(), false);
+                       if ( ! argument.isOk()) {
+                               // when a Status is returned that indicates an 
error, tell caller which arg had problem
+                               Status decoratedStatus = new 
StdStatus(argument.getStatus().getStatusCode(), 
argument.getStatus().getStatusMessage() + " at arg index " + i  );
+                               return decoratedStatus;
+                       }
+                       if (convertedValues != null) {
+                               convertedValues.add(argument.getValue());
+                       }
+               }
+               
+               /*
+                * Everything passed the data type test, so we are good to go
+                */
+               return StdStatus.STATUS_OK;
+       }
+       
+       
+       /**
+        * Validates the given <code>List</code> of 
<code>FunctionArgument</code>s has the correct count.
+        * 
+        * @param listFunctionArguments the <code>List</code> of 
<code>FunctionArgument</code>s to validate
+        * @return a {@link com.att.research.xacml.api.Status} indication with 
an error if the arguments are not valid
+        */
+       public Status validateArgumentListLength(List<FunctionArgument> 
listFunctionArguments) {
+               /*
+                * See if we have to validate the number of arguments
+                */
+               if ((listFunctionArguments == null && this.numArgs > 0 ) ||
+                               (listFunctionArguments != null && this.numArgs 
!= listFunctionArguments.size()) ) {
+                       return new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Expected " + 
this.numArgs + " arguments, got " + 
+                               ((listFunctionArguments == null) ? 0 : 
listFunctionArguments.size())  );
+               }
+               
+               /*
+                * Everything passed the data type test, so we are good to go
+                */
+               return StdStatus.STATUS_OK;
+       }
+       
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java
new file mode 100755
index 0000000..a99456b
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java
@@ -0,0 +1,219 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionLogical extends {@link 
com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple}
 to
+ * implement the XACML Logic predicates as functions taking zero, one, or 
multiple arguments of type <code>Boolean</code> and returning a 
<code>Boolean</code>.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             or
+ *             and
+ *             n-of
+ *             not
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ */
+public class FunctionDefinitionLogical extends 
FunctionDefinitionHomogeneousSimple<Boolean,Boolean> {
+       
+       /**
+        * List of Logical Operations types
+        * 
+        * @author glenngriffin
+        *
+        */
+       public enum OPERATION {OR, AND, N_OF, NOT}
+       
+       // the operation that this instance is being asked to do
+       private final OPERATION operation;
+       
+       
+       public FunctionDefinitionLogical(Identifier idIn, OPERATION op) {
+               super(idIn, DataTypes.DT_BOOLEAN, DataTypes.DT_BOOLEAN, null);
+               operation = op;
+       }
+
+       
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+               
+               switch (operation) {
+               case OR:
+                       if (arguments == null || arguments.size() == 0) {
+                               return ER_FALSE;
+                       }
+                       try {
+                               // evaluate the arguments one at a time and 
abort on the first true
+                               for (int i = 0; i < arguments.size(); i++) {
+                                       ConvertedArgument<Boolean> argument = 
new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false);
+                                       if ( ! argument.isOk()) {
+                                               // return a decorated message
+                                               return 
ExpressionResult.newError(getFunctionStatus(argument.getStatus()));
+                                       }
+                                       if (argument.getValue() == true) {
+                                               return ER_TRUE;
+                                       }
+                               }
+                       } catch (Exception e) {
+                               String message = e.getMessage();
+                               if (e.getCause() != null) {
+                                       message = e.getCause().getMessage();
+                               }
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+                       }
+                       return ER_FALSE;
+
+                       
+               case AND:
+                       if (arguments == null || arguments.size() == 0) {
+                               return ER_TRUE;
+                       }
+                       try {
+                               // evaluate the arguments one at a time and 
abort on the first false
+                               for (int i = 0; i < arguments.size(); i++) {
+                                       ConvertedArgument<Boolean> argument = 
new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false);
+                                       if ( ! argument.isOk()) {
+                                               return 
ExpressionResult.newError(getFunctionStatus(argument.getStatus()));
+                                       }
+                                       if (argument.getValue() == false) {
+                                               return ER_FALSE;
+                                       }
+                               }
+
+                       } catch (Exception e) {
+                               String message = e.getMessage();
+                               if (e.getCause() != null) {
+                                       message = e.getCause().getMessage();
+                               }
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+                       }
+                       return ER_TRUE;
+                       
+                       
+               case N_OF:
+                       Integer argumentCountNeeded;
+                       int trueArgumentsSeen = 0;
+                       if (arguments == null || arguments.size() == 0) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Expected 1 argument, got 0"));
+                       }
+                       try {
+                               //
+                               // Special case:
+                               //      The first argument in the list (an 
Integer) is not homogeneous with the rest of the arguments (Booleans).
+                               //      While this is technically not a 
FunctionDefinitionHomogeneousSimple type of object, we derive from that class 
anyway
+                               //      so that we can take advantage of the 
validateArgument() method in that class.
+                               //      Unfortunately we cannot re-use that 
same code (because of generics - it gets messy) for the Integer argument.
+                               //      The following code essentially does the 
same job as validateArgument() on the first argument in the list.
+                               //
+                               
+                               // first arg is the number of remaining 
arguments that must be TRUE
+                               if (arguments.get(0) == null) {
+                                       return ER_TRUE;
+                               }
+                               if ( ! arguments.get(0).getStatus().isOk()) {
+                                       return 
ExpressionResult.newError(getFunctionStatus(arguments.get(0).getStatus()));
+                               }
+                               if (arguments.get(0).isBag()) {
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Expected a simple value, saw a bag"));
+                               }
+                               AttributeValue<?> attributeValue = 
arguments.get(0).getValue();
+                               if (attributeValue == null) {
+                                       // assume this is the same as "first 
argument is 0"
+                                       return ER_TRUE;
+                               }
+
+                               argumentCountNeeded = 
DataTypes.DT_INTEGER.convert(attributeValue.getValue()).intValue();
+                               if (argumentCountNeeded == 0) {
+                                       return ER_TRUE;
+                               }
+                               if (arguments.size() - 1 < argumentCountNeeded) 
{
+                                       // return a non-OK status to signal 
indeterminate
+                                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+
+                                                       " Expected " + 
argumentCountNeeded + " arguments but only " +
+                                                       (arguments.size() - 1) 
+ " arguments in list after the count"));
+                               }
+                               for (int i = 1; i < arguments.size(); i++) {
+                                       ConvertedArgument<Boolean> argument = 
new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false);
+                                       if ( ! argument.isOk()) {
+                                               return 
ExpressionResult.newError(getFunctionStatus(argument.getStatus()));
+                                       }
+                                       if ((argument.getValue()) == true) {
+                                               trueArgumentsSeen++;
+                                               if (trueArgumentsSeen >= 
argumentCountNeeded) {
+                                                       return ER_TRUE;
+                                               }
+                                       }
+                                       // if we cannot reach the goal, stop 
now.
+                                       // remaining entries to be looked at = 
list size - i - 1, which is the most additional TRUEs that we could get.
+                                       if ( (arguments.size() - i - 1) + 
trueArgumentsSeen < argumentCountNeeded) {
+                                               // do not evaluate remaining 
entries
+                                               return ER_FALSE;
+                                       }
+                               }
+                               // did not reach our goal
+                               return ER_FALSE;
+                               
+                       } catch (Exception e) {
+                               String message = e.getMessage();
+                               if (e.getCause() != null) {
+                                       message = e.getCause().getMessage();
+                               }
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+                       }
+                       
+                       
+               case NOT:
+                       if (arguments == null || arguments.size() != 1) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Expected 1 argument, got " +
+                                               ((arguments == null) ? "null" : 
arguments.size()) ) );
+                       }
+                       try {
+                               ConvertedArgument<Boolean> argument = new 
ConvertedArgument<Boolean>(arguments.get(0), this.getDataTypeArgs(), false);
+                               if ( ! argument.isOk()) {
+                                       return 
ExpressionResult.newError(getFunctionStatus(argument.getStatus()));
+                               }
+                               if (argument.getValue() == true) {
+                                       return ER_FALSE;
+                               } else {
+                                       return ER_TRUE;
+                               }
+                       } catch (Exception e) {
+                               String message = e.getMessage();
+                               if (e.getCause() != null) {
+                                       message = e.getCause().getMessage();
+                               }
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+                       }
+               }
+               
+               // all cases should have been covered by above - should never 
get here
+               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " Could not evaluate Logical function " + operation));
+
+       }
+
+       
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java
new file mode 100755
index 0000000..ce5ec07
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java
@@ -0,0 +1,90 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.DataType;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.api.XACML;
+import com.att.research.xacml.std.StdAttributeValue;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionNumberTypeConversion extends {@link 
FunctionDefinitionHomogeneousSimple} to
+ * implement the XACML predicates foc converting <code>Double</code> to 
<code>Integer</code> and vice versa.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             double-to-integer
+ *             integer-to-double
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ * @param <O> the java class for the data type of the function Output
+ * @param <I> the java class for the data type of the function Input argument
+ */
+public class FunctionDefinitionNumberTypeConversion<O extends Number, I 
extends Number> extends FunctionDefinitionHomogeneousSimple<O, I> {
+
+
+       public FunctionDefinitionNumberTypeConversion(Identifier idIn, 
DataType<O> outputType, DataType<I> argType) {
+               super(idIn, outputType, argType, 1);
+               
+       }
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+               List<I> convertedArguments      = new ArrayList<I>();
+               Status status                           = 
this.validateArguments(arguments, convertedArguments);
+
+               /*
+                * If the function arguments are not correct, just return an 
error status immediately
+                */
+               if 
(!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) {
+                       return 
ExpressionResult.newError(getFunctionStatus(status));
+               }
+               
+               /*
+                * Numeric operations cannot be operated on generically in 
java, so we have to check the types and handle separately.
+                * Whichever type the argument is, convert it to the other
+                */
+               ExpressionResult expressionResult;
+               try {
+                       if (convertedArguments.get(0).getClass() == 
BigInteger.class) {
+                               AttributeValue<Double>  doubleResult    = new 
StdAttributeValue<Double>(XACML.ID_DATATYPE_DOUBLE,
+                                               new Double(  
((BigInteger)convertedArguments.get(0)).toString()  ) );
+                               expressionResult = 
ExpressionResult.newSingle(doubleResult);
+                       } else {
+                               AttributeValue<BigInteger>      integerResult   
= new StdAttributeValue<BigInteger>(XACML.ID_DATATYPE_INTEGER, 
BigInteger.valueOf(((Double)convertedArguments.get(0)).intValue()) );
+                               expressionResult = 
ExpressionResult.newSingle(integerResult);
+                       }
+               } catch (Exception e) {
+                       String message = e.getMessage();
+                       if (e.getCause() != null) {
+                               message = e.getCause().getMessage();
+                       }
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() 
+ " " + message));
+               }
+               
+               return expressionResult;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java
----------------------------------------------------------------------
diff --git 
a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java
 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java
new file mode 100755
index 0000000..5015204
--- /dev/null
+++ 
b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java
@@ -0,0 +1,141 @@
+/*
+ *                        AT&T - PROPRIETARY
+ *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
+ *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
+ *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
+ *
+ *          Copyright (c) 2013 AT&T Knowledge Ventures
+ *              Unpublished and Not for Publication
+ *                     All Rights Reserved
+ */
+package com.att.research.xacmlatt.pdp.std.functions;
+
+import java.util.List;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacml.std.datatypes.RFC822Name;
+import com.att.research.xacmlatt.pdp.eval.EvaluationContext;
+import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
+import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
+
+/**
+ * FunctionDefinitionRFC822NameMatch extends {@link 
com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple}
 to
+ * implement the XACML RFC822Name match predicate as functions taking one 
<code>String</code> and one <code>RFC822Name</code> arguments
+ * and returning a single <code>Boolean</code> value.
+ * 
+ * In the first implementation of XACML we had separate files for each XACML 
Function.
+ * This release combines multiple Functions in fewer files to minimize code 
duplication.
+ * This file supports the following XACML codes:
+ *             rfc822Name-match
+ * 
+ * @author glenngriffin
+ * @version $Revision: 1.1 $
+ * 
+ */
+public class FunctionDefinitionRFC822NameMatch extends 
FunctionDefinitionBase<Boolean, RFC822Name> {
+       
+
+       /**
+        * Constructor
+        * 
+        * @param idIn
+        * @param dataTypeArgsIn
+        * @param op
+        */
+       public FunctionDefinitionRFC822NameMatch(Identifier idIn) {
+               super(idIn, DataTypes.DT_BOOLEAN, DataTypes.DT_RFC822NAME, 
false);
+       }
+
+
+       @Override
+       public ExpressionResult evaluate(EvaluationContext evaluationContext, 
List<FunctionArgument> arguments) {
+               
+               if (arguments == null || arguments.size() != 2) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + " 
Expected 2 arguments, got " + 
+                                       ((arguments == null) ? "null" : 
arguments.size()) ));
+               }
+
+               // get the string to search for
+               ConvertedArgument<String> stringArgument = new 
ConvertedArgument<String>(arguments.get(0), DataTypes.DT_STRING, false);
+               if ( ! stringArgument.isOk()) {
+                       Status decoratedStatus = new 
StdStatus(stringArgument.getStatus().getStatusCode(), 
stringArgument.getStatus().getStatusMessage() + " at arg index 0"  );
+                       return 
ExpressionResult.newError(getFunctionStatus(decoratedStatus));
+               }
+               String searchTermString = stringArgument.getValue();
+               
+               // get the RFC822Name to match with
+               ConvertedArgument<RFC822Name> rfc822Argument = new 
ConvertedArgument<RFC822Name>(arguments.get(1), DataTypes.DT_RFC822NAME, false);
+               if ( ! rfc822Argument.isOk()) {
+                       Status decoratedStatus = new 
StdStatus(rfc822Argument.getStatus().getStatusCode(), 
rfc822Argument.getStatus().getStatusMessage() + " at arg index 1"  );
+                       return 
ExpressionResult.newError(getFunctionStatus(decoratedStatus));
+               }
+               
+               RFC822Name rfc822Name = rfc822Argument.getValue();
+               
+               
+               /*
+                * Now perform the match.
+                */
+               
+               /*
+                * According to the spec the string must be one of the 
following 3 things:
+                *      - a name with an '@' in it = a full name that must 
exactly match the whole RFC name (domain part is ignore case)
+                *      - a domain name (without an '@' and not starting with a 
'.') = must match whole RFC domain name (ignore case)
+                *      - a partial domain name (without an '@') starting with 
a '.' = the last part of the RFC domain name (ignore case)
+                */
+
+               String[] searchTerms = searchTermString.split("@");
+               
+               if (searchTerms.length > 2) {
+                       return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + 
+                                       " String contained more than 1 '@' in 
'" + searchTermString + "'" ));
+               }
+
+               if (searchTerms.length == 2 || searchTermString.endsWith("@")) {
+                       // this is an exact match
+                       if (searchTerms[0] == null || searchTerms[0].length() 
== 0) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + 
+                                               " String missing local part in 
'" + searchTermString + "'" ));
+                       }
+                       if (searchTerms.length < 2 || searchTerms[1] == null || 
searchTerms[1].length() == 0) {
+                               return ExpressionResult.newError(new 
StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + 
+                                               " String missing domain part in 
'" + searchTermString + "'" ));
+                       }
+                       
+                       // args are ok, so check both against RFC name
+                       if (searchTerms[0].equals(rfc822Name.getLocalName()) && 
+                                       
searchTerms[1].toLowerCase().equals(rfc822Name.getCanonicalDomainName())) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }                       
+               }
+               
+               // we have only a domain name, which may be whole or partial
+               
+               // make it match the canonical version
+               searchTerms[0] = searchTerms[0].toLowerCase();
+               
+               if (searchTerms[0].charAt(0) == '.') {
+                       // name is partial - must match the end
+                       if 
(rfc822Name.getCanonicalDomainName().endsWith(searchTerms[0])) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+               } else {
+                       // name is whole domain - must match exactly
+                       if 
(rfc822Name.getCanonicalDomainName().equals(searchTerms[0])) {
+                               return ER_TRUE;
+                       } else {
+                               return ER_FALSE;
+                       }
+               }
+
+       }
+
+}

Reply via email to