Source code: com/sun/xacml/cond/GeneralBagFunction.java
1
2 /*
3 * @(#)GeneralBagFunction.java
4 *
5 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistribution of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistribution in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
18 * be used to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind. ALL
22 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
23 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
24 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
25 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
26 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
27 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
28 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
29 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
30 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
31 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use in
34 * the design, construction, operation or maintenance of any nuclear facility.
35 */
36
37 package com.sun.xacml.cond;
38
39 import com.sun.xacml.EvaluationCtx;
40
41 import com.sun.xacml.attr.AttributeValue;
42 import com.sun.xacml.attr.BagAttribute;
43 import com.sun.xacml.attr.IntegerAttribute;
44
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Set;
51
52
53 /**
54 * Specific <code>BagFunction</code> class that supports all of the
55 * general-purpose bag functions: type-one-and-only, type-bag-size, and
56 * type-bag.
57 *
58 * @since 1.2
59 * @author Seth Proctor
60 */
61 public class GeneralBagFunction extends BagFunction
62 {
63
64 // private identifiers for the supported functions
65 private static final int ID_BASE_ONE_AND_ONLY = 0;
66 private static final int ID_BASE_BAG_SIZE = 1;
67 private static final int ID_BASE_BAG = 2;
68
69 // mapping of function name to its associated parameters
70 private static HashMap paramMap;
71 private static Set supportedIds;
72
73 /**
74 * Static initializer that sets up the paramater info for all the
75 * supported functions.
76 */
77 static {
78 paramMap = new HashMap();
79
80 for (int i = 0; i < baseTypes.length; i++) {
81 String baseType = baseTypes[i];
82 String functionBaseName = FUNCTION_NS + simpleTypes[i];
83
84 paramMap.put(functionBaseName + NAME_BASE_ONE_AND_ONLY,
85 new BagParameters(ID_BASE_ONE_AND_ONLY, baseType,
86 true, 1, baseType, false));
87
88 paramMap.put(functionBaseName + NAME_BASE_BAG_SIZE,
89 new BagParameters(ID_BASE_BAG_SIZE, baseType, true,
90 1, IntegerAttribute.identifier,
91 false));
92
93 paramMap.put(functionBaseName + NAME_BASE_BAG,
94 new BagParameters(ID_BASE_BAG, baseType, false, -1,
95 baseType, true));
96 }
97
98 supportedIds = Collections.
99 unmodifiableSet(new HashSet(paramMap.keySet()));
100
101 paramMap.put(NAME_BASE_ONE_AND_ONLY,
102 new BagParameters(ID_BASE_ONE_AND_ONLY, null, true, 1,
103 null, false));
104 paramMap.put(NAME_BASE_BAG_SIZE,
105 new BagParameters(ID_BASE_BAG_SIZE, null, true, 1,
106 IntegerAttribute.identifier, false));
107 paramMap.put(NAME_BASE_BAG,
108 new BagParameters(ID_BASE_BAG, null, false, -1, null,
109 true));
110
111
112 };
113
114 /**
115 * Constructor that is used to create one of the general-purpose standard
116 * bag functions. The name supplied must be one of the standard XACML
117 * functions supported by this class, including the full namespace,
118 * otherwise an exception is thrown. Look in <code>BagFunction</code>
119 * for details about the supported names.
120 *
121 * @param functionName the name of the function to create
122 *
123 * @throws IllegalArgumentException if the function is unknown
124 */
125 public GeneralBagFunction(String functionName) {
126 super(functionName, getId(functionName), getArgumentType(functionName),
127 getIsBag(functionName), getNumArgs(functionName),
128 getReturnType(functionName), getReturnsBag(functionName));
129 }
130
131 /**
132 * Constructor that is used to create instances of general-purpose bag
133 * functions for new (non-standard) datatypes. This is equivalent to
134 * using the <code>getInstance</code> methods in <code>BagFunction</code>
135 * and is generally only used by the run-time configuration code.
136 *
137 * @param functionName the name of the new function
138 * @param datatype the full identifier for the supported datatype
139 * @param functionType which kind of Bag function, based on the
140 * <code>NAME_BASE_*</code> fields
141 */
142 public GeneralBagFunction(String functionName, String datatype,
143 String functionType) {
144 super(functionName, getId(functionType), datatype,
145 getIsBag(functionType), getNumArgs(functionType),
146 getCustomReturnType(functionType, datatype),
147 getReturnsBag(functionType));
148 }
149
150 /**
151 * Private helper that returns the internal identifier used for the
152 * given standard function.
153 */
154 private static int getId(String functionName) {
155 BagParameters params = (BagParameters)(paramMap.get(functionName));
156
157 if (params == null)
158 throw new IllegalArgumentException("unknown bag function: " +
159 functionName);
160
161 return params.id;
162 }
163
164 /**
165 * Private helper that returns the argument type for the given standard
166 * function. Note that this doesn't check on the return value since the
167 * method always is called after getId, so we assume that the function
168 * is present.
169 */
170 private static String getArgumentType(String functionName) {
171 return ((BagParameters)(paramMap.get(functionName))).arg;
172 }
173
174 /**
175 * Private helper that returns if the given standard function takes
176 * a bag. Note that this doesn't check on the return value since the
177 * method always is called after getId, so we assume that the function
178 * is present.
179 */
180 private static boolean getIsBag(String functionName) {
181 return ((BagParameters)(paramMap.get(functionName))).argIsBag;
182 }
183
184 /**
185 * Private helper that returns the argument count for the given standard
186 * function. Note that this doesn't check on the return value since the
187 * method always is called after getId, so we assume that the function
188 * is present.
189 */
190 private static int getNumArgs(String functionName) {
191 return ((BagParameters)(paramMap.get(functionName))).params;
192 }
193
194 /**
195 * Private helper that returns the return type for the given standard
196 * function. Note that this doesn't check on the return value since the
197 * method always is called after getId, so we assume that the function
198 * is present.
199 */
200 private static String getReturnType(String functionName) {
201 return ((BagParameters)(paramMap.get(functionName))).returnType;
202 }
203
204 /**
205 * Private helper that returns if the return type is a bag for the given
206 * standard function. Note that this doesn't check on the return value
207 * since the method always is called after getId, so we assume that the
208 * function is present.
209 */
210 private static boolean getReturnsBag(String functionName) {
211 return ((BagParameters)(paramMap.get(functionName))).returnsBag;
212 }
213
214 /**
215 * Private helper used by the custom datatype constructor to figure out
216 * what the return type is. Note that this doesn't check on the return
217 * value since the method always is called after getId, so we assume that
218 * the function is present.
219 */
220 private static String getCustomReturnType(String functionType,
221 String datatype) {
222 String ret = ((BagParameters)(paramMap.get(functionType))).returnType;
223
224 if (ret == null)
225 return datatype;
226 else
227 return ret;
228 }
229
230 /**
231 * Returns a <code>Set</code> containing all the function identifiers
232 * supported by this class.
233 *
234 * @return a <code>Set</code> of <code>String</code>s
235 */
236 public static Set getSupportedIdentifiers() {
237 return supportedIds;
238 }
239
240 /**
241 * Evaluate the function, using the specified parameters.
242 *
243 * @param inputs a <code>List</code> of <code>Evaluatable</code>
244 * objects representing the arguments passed to the function
245 * @param context an <code>EvaluationCtx</code> so that the
246 * <code>Evaluatable</code> objects can be evaluated
247 * @return an <code>EvaluationResult</code> representing the
248 * function's result
249 */
250 public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
251
252 // Evaluate the arguments
253 AttributeValue [] argValues = new AttributeValue[inputs.size()];
254 EvaluationResult result = evalArgs(inputs, context, argValues);
255 if (result != null)
256 return result;
257
258 // Now that we have real values, perform the requested operation.
259 AttributeValue attrResult = null;
260
261 switch (getFunctionId()) {
262
263 // *-one-and-only takes a single bag and returns a
264 // single value of baseType
265 case ID_BASE_ONE_AND_ONLY: {
266 BagAttribute bag = (BagAttribute)(argValues[0]);
267
268 if (bag.size() != 1)
269 return makeProcessingError(getFunctionName() + " expects " +
270 "a bag that contains a single " +
271 "element, got a bag with " +
272 bag.size() + " elements");
273
274 attrResult = (AttributeValue)(bag.iterator().next());
275 break;
276 }
277
278 // *-size takes a single bag and returns an integer
279 case ID_BASE_BAG_SIZE: {
280 BagAttribute bag = (BagAttribute)(argValues[0]);
281
282 attrResult = new IntegerAttribute(bag.size());
283 break;
284 }
285
286 // *-bag takes any number of elements of baseType and
287 // returns a bag containing those elements
288 case ID_BASE_BAG: {
289 List argsList = Arrays.asList(argValues);
290
291 attrResult = new BagAttribute(getReturnType(), argsList);
292 break;
293 }
294 }
295
296 return new EvaluationResult(attrResult);
297 }
298
299 /**
300 * Private class that is used for mapping each function to it set of
301 * parameters.
302 */
303 private static class BagParameters {
304 public int id;
305 public String arg;
306 public boolean argIsBag;
307 public int params;
308 public String returnType;
309 public boolean returnsBag;
310
311 public BagParameters(int id, String arg, boolean argIsBag, int params,
312 String returnType, boolean returnsBag) {
313 this.id = id;
314 this.arg = arg;
315 this.argIsBag = argIsBag;
316 this.params = params;
317 this.returnType = returnType;
318 this.returnsBag = returnsBag;
319 }
320 }
321
322 }