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

Quick Search    Search Deep

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


1   
2   /*
3    * @(#)DateMathFunction.java
4    *
5    * Copyright 2003-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.DateAttribute;
43  import com.sun.xacml.attr.DateTimeAttribute;
44  import com.sun.xacml.attr.DayTimeDurationAttribute;
45  import com.sun.xacml.attr.YearMonthDurationAttribute;
46  
47  import java.util.Calendar;
48  import java.util.Collections;
49  import java.util.Date;
50  import java.util.GregorianCalendar;
51  import java.util.HashMap;
52  import java.util.HashSet;
53  import java.util.Iterator;
54  import java.util.List;
55  import java.util.Set;
56  
57  
58  /**
59   * A class that implements several of the date math functions. They
60   * all take two arguments. The first is a DateTimeAttribute or a
61   * DateAttribute (as the case may be) and the second is a
62   * DayTimeDurationAttribute or a YearMonthDurationAttribute (as
63   * the case may be). The function adds or subtracts the second
64   * argument to/from the first and returns a value of the same
65   * type as the first argument. If either of the arguments evaluates
66   * to indeterminate, an indeterminate result is returned.
67   *
68   * @since 1.0
69   * @author Steve Hanna
70   * @author Seth Proctor
71   */
72  public class DateMathFunction extends FunctionBase
73  {
74  
75      /**
76       * Standard identifier for the dateTime-add-dayTimeDuration function.
77       */
78      public static final String NAME_DATETIME_ADD_DAYTIMEDURATION =
79          FUNCTION_NS + "dateTime-add-dayTimeDuration";
80  
81      /**
82       * Standard identifier for the dateTime-subtract-dayTimeDuration function.
83       */
84      public static final String NAME_DATETIME_SUBTRACT_DAYTIMEDURATION =
85          FUNCTION_NS + "dateTime-subtract-dayTimeDuration";
86  
87      /**
88       * Standard identifier for the dateTime-add-yearMonthDuration function.
89       */
90      public static final String NAME_DATETIME_ADD_YEARMONTHDURATION =
91          FUNCTION_NS + "dateTime-add-yearMonthDuration";
92  
93      /**
94       * Standard identifier for the dateTime-subtract-yearMonthDuration
95       * function.
96       */
97      public static final String NAME_DATETIME_SUBTRACT_YEARMONTHDURATION =
98          FUNCTION_NS + "dateTime-subtract-yearMonthDuration";
99  
100     /**
101      * Standard identifier for the date-add-yearMonthDuration function.
102      */
103     public static final String NAME_DATE_ADD_YEARMONTHDURATION =
104         FUNCTION_NS + "date-add-yearMonthDuration";
105 
106     /**
107      * Standard identifier for the date-subtract-yearMonthDuration function.
108      */
109     public static final String NAME_DATE_SUBTRACT_YEARMONTHDURATION =
110         FUNCTION_NS + "date-subtract-yearMonthDuration";
111 
112     // private identifiers for the supported functions
113     private static final int ID_DATETIME_ADD_DAYTIMEDURATION = 0;
114     private static final int ID_DATETIME_SUBTRACT_DAYTIMEDURATION = 1;
115     private static final int ID_DATETIME_ADD_YEARMONTHDURATION = 2;
116     private static final int ID_DATETIME_SUBTRACT_YEARMONTHDURATION = 3;
117     private static final int ID_DATE_ADD_YEARMONTHDURATION = 4;
118     private static final int ID_DATE_SUBTRACT_YEARMONTHDURATION = 5;
119 
120     // Argument types
121     private static final String dateTimeDayTimeDurationArgTypes [] =
122         { DateTimeAttribute.identifier,
123           DayTimeDurationAttribute.identifier };
124     private static final String dateTimeYearMonthDurationArgTypes [] =
125         { DateTimeAttribute.identifier,
126           YearMonthDurationAttribute.identifier };
127     private static final String dateYearMonthDurationArgTypes [] =
128         { DateAttribute.identifier,
129           YearMonthDurationAttribute.identifier };
130 
131     // nothing here uses a bag
132     private static final boolean bagParams [] = { false, false };
133 
134     // Argument types for this object
135     private String [] argTypes = null;
136 
137     // mapping from name to provide identifiers and argument types
138     private static HashMap idMap;
139     private static HashMap typeMap;
140 
141     /**
142      * Static initializer to setup the id and type maps
143      */
144     static {
145         idMap = new HashMap();
146 
147         idMap.put(NAME_DATETIME_ADD_DAYTIMEDURATION,
148                   new Integer(ID_DATETIME_ADD_DAYTIMEDURATION));
149         idMap.put(NAME_DATETIME_SUBTRACT_DAYTIMEDURATION,
150                   new Integer(ID_DATETIME_SUBTRACT_DAYTIMEDURATION));
151         idMap.put(NAME_DATETIME_ADD_YEARMONTHDURATION,
152                   new Integer(ID_DATETIME_ADD_YEARMONTHDURATION));
153         idMap.put(NAME_DATETIME_SUBTRACT_YEARMONTHDURATION,
154                   new Integer(ID_DATETIME_SUBTRACT_YEARMONTHDURATION));
155         idMap.put(NAME_DATE_ADD_YEARMONTHDURATION,
156                   new Integer(ID_DATE_ADD_YEARMONTHDURATION));
157         idMap.put(NAME_DATE_SUBTRACT_YEARMONTHDURATION,
158                   new Integer(ID_DATE_SUBTRACT_YEARMONTHDURATION));
159 
160         typeMap = new HashMap();
161 
162         typeMap.put(NAME_DATETIME_ADD_DAYTIMEDURATION,
163                     dateTimeDayTimeDurationArgTypes);
164         typeMap.put(NAME_DATETIME_SUBTRACT_DAYTIMEDURATION,
165                     dateTimeDayTimeDurationArgTypes);
166         typeMap.put(NAME_DATETIME_ADD_YEARMONTHDURATION,
167                     dateTimeYearMonthDurationArgTypes);
168         typeMap.put(NAME_DATETIME_SUBTRACT_YEARMONTHDURATION,
169                     dateTimeYearMonthDurationArgTypes);
170         typeMap.put(NAME_DATE_ADD_YEARMONTHDURATION,
171                     dateYearMonthDurationArgTypes);
172         typeMap.put(NAME_DATE_SUBTRACT_YEARMONTHDURATION,
173                     dateYearMonthDurationArgTypes);
174     };
175 
176     /**
177      * Creates a new <code>DateMathFunction</code> object.
178      *
179      * @param functionName the standard XACML name of the function to be
180      *                     handled by this object, including the full namespace
181      *
182      * @throws IllegalArgumentException if the function is unknown
183      */
184     public DateMathFunction(String functionName) {
185         super(functionName, getId(functionName),
186               getArgumentTypes(functionName), bagParams,
187               getReturnType(functionName), false);
188     }
189 
190     /**
191      * Private helper that returns the internal identifier used for the
192      * given standard function.
193      */
194     private static int getId(String functionName) {
195         Integer i = (Integer)(idMap.get(functionName));
196 
197         if (i == null)
198             throw new IllegalArgumentException("unknown datemath function " +
199                                                functionName);
200 
201         return i.intValue();
202     }
203 
204     /**
205      * Private helper that returns the types used for the given standard
206      * function. Note that this doesn't check on the return value since the
207      * method always is called after getId, so we assume that the function
208      * is present.
209      */
210     private static String [] getArgumentTypes(String functionName) {
211         return (String [])(typeMap.get(functionName));
212     }
213 
214     /**
215      * Private helper that returns the return type for the given standard
216      * function. Note that this doesn't check on the return value since the
217      * method always is called after getId, so we assume that the function
218      * is present.
219      */
220     private static String getReturnType(String functionName) {
221         if (functionName.equals(NAME_DATE_ADD_YEARMONTHDURATION) ||
222             functionName.equals(NAME_DATE_SUBTRACT_YEARMONTHDURATION))
223             return DateAttribute.identifier;
224         else
225             return DateTimeAttribute.identifier;
226     }
227 
228     /**
229      * Returns a <code>Set</code> containing all the function identifiers
230      * supported by this class.
231      *
232      * @return a <code>Set</code> of <code>String</code>s
233      */
234     public static Set getSupportedIdentifiers() {
235         return Collections.unmodifiableSet(idMap.keySet());
236     }
237 
238     /**
239      * Evaluate the function, using the specified parameters.
240      *
241      * @param inputs a <code>List</code> of <code>Evaluatable</code>
242      *               objects representing the arguments passed to the function
243      * @param context an <code>EvaluationCtx</code> so that the
244      *                <code>Evaluatable</code> objects can be evaluated
245      * @return an <code>EvaluationResult</code> representing the
246      *         function's result
247      */
248     public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
249 
250         // Evaluate the arguments
251         AttributeValue [] argValues = new AttributeValue[inputs.size()];
252         EvaluationResult result = evalArgs(inputs, context, argValues);
253         if (result != null)
254             return result;
255 
256         // Now that we have real values, perform the date math operation.
257         AttributeValue attrResult = null;
258 
259         switch (getFunctionId()) {
260         // These two functions are basically the same except for sign.
261         // And they both need to deal with sign anyway, so they share
262         // their code.
263         case ID_DATETIME_ADD_DAYTIMEDURATION:
264         case ID_DATETIME_SUBTRACT_DAYTIMEDURATION: {
265             DateTimeAttribute dateTime = (DateTimeAttribute) argValues[0];
266             DayTimeDurationAttribute duration =
267                 (DayTimeDurationAttribute) argValues[1];
268 
269             // Decide what sign goes with duration
270             int sign = 1;
271             if (getFunctionId() == ID_DATETIME_SUBTRACT_DAYTIMEDURATION)
272                 sign = -sign;
273             if (duration.isNegative())
274                 sign = -sign;
275             long millis = sign * duration.getTotalSeconds();
276             long nanoseconds = dateTime.getNanoseconds();
277             nanoseconds = nanoseconds + (sign * duration.getNanoseconds());
278             if (nanoseconds >= 1000000000) {
279                 nanoseconds -= 1000000000;
280                 millis += 1000;
281             }
282             if (nanoseconds < 0) {
283                 nanoseconds += 1000000000;
284                 millis -= 1000;
285             }
286             millis = millis + dateTime.getValue().getTime();
287 
288             attrResult = new DateTimeAttribute(new Date(millis),
289                                                (int) nanoseconds,
290                                                dateTime.getTimeZone(),
291                                                dateTime.
292                                                  getDefaultedTimeZone());
293 
294             break;
295         }
296         case ID_DATETIME_ADD_YEARMONTHDURATION:
297         case ID_DATETIME_SUBTRACT_YEARMONTHDURATION: {
298             DateTimeAttribute dateTime = (DateTimeAttribute) argValues[0];
299             YearMonthDurationAttribute duration =
300                 (YearMonthDurationAttribute) argValues[1];
301             
302             // Decide what sign goes with duration
303             int sign = 1;
304             if (getFunctionId() == ID_DATETIME_SUBTRACT_YEARMONTHDURATION)
305                 sign = -sign;
306             if (duration.isNegative())
307                 sign = -sign;
308 
309             // Add (or subtract) the years and months.
310             Calendar cal = new GregorianCalendar();
311             cal.setTime(dateTime.getValue());
312             long years = sign * duration.getYears();
313             long months = sign * duration.getMonths();
314             if ((years > Integer.MAX_VALUE) || (years < Integer.MIN_VALUE))
315                 return makeProcessingError("years too large");
316             if ((months > Integer.MAX_VALUE) || (months < Integer.MIN_VALUE))
317                 return makeProcessingError("months too large");
318 
319             cal.add(Calendar.YEAR, (int) years);
320             cal.add(Calendar.MONTH, (int) months);
321 
322             attrResult = new DateTimeAttribute(cal.getTime(),
323                                                dateTime.getNanoseconds(),
324                                                dateTime.getTimeZone(),
325                                                dateTime.
326                                                  getDefaultedTimeZone());
327 
328             break;
329         }
330         case ID_DATE_ADD_YEARMONTHDURATION:
331         case ID_DATE_SUBTRACT_YEARMONTHDURATION: {
332             DateAttribute date = (DateAttribute) argValues[0];
333             YearMonthDurationAttribute duration =
334                 (YearMonthDurationAttribute) argValues[1];
335             
336             // Decide what sign goes with duration
337             int sign = 1;
338             if (getFunctionId() == ID_DATE_SUBTRACT_YEARMONTHDURATION)
339                 sign = -sign;
340             if (duration.isNegative())
341                 sign = -sign;
342 
343             // Add (or subtract) the years and months.
344             Calendar cal = new GregorianCalendar();
345             cal.setTime(date.getValue());
346             long years = sign * duration.getYears();
347             long months = sign * duration.getMonths();
348             if ((years > Integer.MAX_VALUE) || (years < Integer.MIN_VALUE))
349                 return makeProcessingError("years too large");
350             if ((months > Integer.MAX_VALUE) || (months < Integer.MIN_VALUE))
351                 return makeProcessingError("months too large");
352 
353             cal.add(Calendar.YEAR, (int) years);
354             cal.add(Calendar.MONTH, (int) months);
355 
356             attrResult = new DateAttribute(cal.getTime(),
357                                            date.getTimeZone(),
358                                            date.getDefaultedTimeZone());
359 
360             break;
361         }
362         }
363 
364         return new EvaluationResult(attrResult);
365     }
366 }