Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sun/xacml/cond/MapFunction.java


1   
2   /*
3    * @(#)MapFunction.java  1.4 01/30/03
4    *
5    * Copyright 2003 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  import com.sun.xacml.ParsingException;
41  
42  import com.sun.xacml.attr.AttributeValue;
43  import com.sun.xacml.attr.BagAttribute;
44  
45  import com.sun.xacml.ctx.Status;
46  
47  import java.net.URI;
48  
49  import java.util.ArrayList;
50  import java.util.HashSet;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Set;
55  
56  import org.w3c.dom.Node;
57  import org.w3c.dom.NodeList;
58  
59  
60  /**
61   * Represents the higher order bag function map.
62   *
63   * @since 1.0
64   * @author Seth Proctor
65   */
66  class MapFunction implements Function
67  {
68  
69      /**
70       * The name of this function
71       */
72      public static final String NAME_MAP = FunctionBase.FUNCTION_NS + "map";
73  
74      // the return type for this instance
75      private URI returnType;
76  
77      // the stuff used to make sure that we have a valid identifier or a
78      // known error, just like in the attribute classes
79      private static URI identifier;
80      private static RuntimeException earlyException;
81  
82      // try to initialize the identifier
83      static {
84          try {
85              identifier = new URI(NAME_MAP);
86          } catch (Exception e) {
87              earlyException = new IllegalArgumentException();
88              earlyException.initCause(e);
89          }
90      };
91  
92      /**
93       * Creates a new instance of a <code>MapFunction</code>.
94       *
95       * @param returnType the type returned by this function
96       */
97      public MapFunction(URI returnType) {
98          this.returnType = returnType;
99      }
100 
101     /**
102      * Returns a <code>Set</code> containing all the function identifiers
103      * supported by this class.
104      *
105      * @return a <code>Set</code> of <code>String</code>s
106      */
107     public static Set getSupportedIdentifiers() {
108         Set set = new HashSet();
109 
110         set.add(NAME_MAP);
111 
112         return set;
113     }
114 
115     /**
116      * Creates a new instance of the map function using the data found in
117      * the DOM node provided. This is called by a proxy when the factory
118      * is asked to create one of these functions.
119      *
120      * @param root the DOM node of the apply tag containing this function
121      *
122      * @return a <code>MapFunction</code> instance
123      *
124      * @throws ParsingException if the DOM data was incorrect
125      */
126     public static MapFunction getInstance(Node root) throws ParsingException {
127         URI returnType = null;
128 
129         NodeList nodes = root.getChildNodes();
130         for (int i = 0; i < nodes.getLength(); i++) {
131             Node node = nodes.item(i);
132 
133             if (node.getNodeName().equals("Function")) {
134                 String funcName = node.getAttributes().
135                     getNamedItem("FunctionId").getNodeValue();
136                 FunctionFactory factory = FunctionFactory.getGeneralInstance();
137                 try {
138                     Function function = factory.createFunction(funcName);
139                     returnType = function.getReturnType();
140                     break;
141                 } catch (FunctionTypeException fte) {
142                     // try to get this as an abstract function
143                     try {
144                         Function function = factory.
145                             createAbstractFunction(funcName, root);
146                         returnType = function.getReturnType();
147                         break;
148                     } catch (Exception e) {
149                         // any exception here is an error
150                         throw new ParsingException("invalid abstract map", e);
151                     }
152                 } catch (Exception e) {
153                     // any exception that's not function type is an error
154                     throw new ParsingException("couldn't parse map body", e);
155                 }
156             }
157         }
158 
159         // see if we found the return type
160         if (returnType == null)
161             throw new ParsingException("couldn't find the return type");
162 
163         return new MapFunction(returnType);
164     }
165     
166     /**
167      * Returns the full identifier of this function, as known by the factories.
168      *
169      * @return the function's identifier
170      */
171     public URI getIdentifier() {
172         // strictly speaking, this should never happen
173         if (earlyException != null)
174             throw earlyException;
175 
176         return identifier;
177     }
178 
179     /**
180      * Returns the attribute type returned by this function.
181      *
182      * @return the return type
183      */
184     public URI getReturnType() {
185         return returnType;
186     }
187 
188     /**
189      * Returns <code>true</code>, since the map function always returns a bag
190      *
191      * @return true
192      */
193     public boolean returnsBag() {
194         return true;
195     }
196 
197     /**
198      * Helper function to create a processing error message.
199      */
200     private static EvaluationResult makeProcessingError(String message) {
201         ArrayList code = new ArrayList();
202         code.add(Status.STATUS_PROCESSING_ERROR);
203         return new EvaluationResult(new Status(code, message));
204     }
205 
206     /**
207      * Evaluates the function given the input data. Map expects a
208      * <code>Function</code> followed by a <code>BagAttribute</code>.
209      *
210      * @param inputs the input agrument list
211      * @param context the representation of the request
212      *
213      * @return the result of evaluation
214      */
215     public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
216 
217         // get the inputs, which we expect to be correct
218         Iterator iterator = inputs.iterator();
219         Function function = (Function)(iterator.next());
220         BagAttribute bag = (BagAttribute)(iterator.next());
221         
222         // param: function, bag
223         // return: bag
224         // for each value in the bag evaluate the given function with
225         // the value and put the function result in a new bag that
226         // is ultimately returned
227 
228         Iterator it = bag.iterator();
229         List outputs = new ArrayList();
230 
231         while (it.hasNext()) {
232             List params = new ArrayList();
233             params.add(it.next());
234             EvaluationResult result = function.evaluate(params, context);
235 
236             if (result.indeterminate())
237                 return result;
238 
239             outputs.add(result.getAttributeValue());
240         }
241 
242         return new EvaluationResult(new BagAttribute(returnType, outputs));
243     }
244 
245     /**
246      * Checks that the input list is valid for evaluation.
247      *
248      * @param inputs a <code>List</code> of inputs
249      *
250      * @throws IllegalArgumentException if the inputs cannot be evaluated
251      */
252     public void checkInputs(List inputs) throws IllegalArgumentException {
253         Object [] list = inputs.toArray();
254 
255         // check that we've got the right number of arguments
256         if (list.length != 2)
257             throw new IllegalArgumentException("map requires two inputs");
258 
259         // now check that we've got the right types for map
260         if (! (list[0] instanceof Function))
261             throw new IllegalArgumentException("first argument to map must " +
262                                                "be a Function");
263         Evaluatable eval = (Evaluatable)(list[1]);
264         if (! eval.evaluatesToBag())
265             throw new IllegalArgumentException("second argument to map must " +
266                                                "be a bag");
267 
268         // finally, check that the type in the bag is right for the function
269         List input = new ArrayList();
270         input.add(list[1]);
271         ((Function)(list[0])).checkInputsNoBag(input);
272     }
273 
274     /**
275      * Always throws <code>IllegalArgumentException</code> since map needs
276      * to work on a bag
277      *
278      * @param inputs a <code>List</code> of inputs
279      *
280      * @throws IllegalArgumentException always
281      */
282     public void checkInputsNoBag(List inputs) throws IllegalArgumentException {
283         throw new IllegalArgumentException("map requires a bag");
284     }
285 
286 }