View Javadoc

1   /* ===================================================================
2    * Copyright 2002-04 SRI International.
3    * Released under the MOZILLA PUBLIC LICENSE Version 1.1
4    * which can be obtained at http://www.mozilla.org/MPL/MPL-1.1.html
5    * This software is distributed on an "AS IS"
6    * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
7    * See the License for the specific language governing rights and
8    * limitations under the License.
9    * =================================================================== */
10  package com.sri.emo.dbobj;
11  
12  import com.jcorporate.expresso.core.controller.ControllerRequest;
13  import com.jcorporate.expresso.core.controller.Transition;
14  import com.jcorporate.expresso.core.db.DBConnection;
15  import com.jcorporate.expresso.core.db.DBException;
16  import com.jcorporate.expresso.core.dbobj.DBField;
17  import com.jcorporate.expresso.core.dbobj.RowSecuredDBObject;
18  import com.jcorporate.expresso.core.security.ReadOnlyUser;
19  import com.jcorporate.expresso.core.security.SuperUser;
20  import com.jcorporate.expresso.core.security.User;
21  import com.sri.emo.controller.PicklistAction;
22  import com.sri.emo.dbobj.model_tree.ModelVisitable;
23  import com.sri.emo.dbobj.model_tree.ModelVisitor;
24  
25  import java.util.Comparator;
26  
27  
28  /***
29   * Provide picklists for any attribute.
30   *
31   * @author larry hamel
32   */
33  public class PickList extends RowSecuredDBObject
34          implements Comparator, Comparable, ModelVisitable, IViewable {
35      /***
36  	 * 
37  	 */
38  	private static final long serialVersionUID = 1L;
39  	public static final String TABLE_NAME = "picklist";
40      public static final String NODE_TYPE = NodeType.NODE_TYPE_NAME;
41      public static final String ATTRIBUTE_TYPE = Attribute.ATTRIBUTE_TYPE;
42      public static final String LIST_ID = "LIST_ID";
43      public static final String DISPLAY_IN_PICKLIST = "VALUE_IN_PICKLIST";
44      public static final String COMMENT = "COMMENT";
45      public static final String ORDER_NUM = "ORDER_NUM";
46      public static final String NOT_SPECIFIED_DISPLAY = "(not specified)";
47      public static final String CONTINUOUS_SMV_TYPE = "Continuous";
48      public static final String FINITE_SMV_TYPE = "Finite";
49      public static final String TASK_SPECIFICATION_MENU_VALUE = "Concrete Specification";
50      public static final String TEMPLATE_MENU_VALUE = "Abstract Template";
51  
52      /***
53       * string constant to use for custom pick list which is INDEPENDENT of any given node type.
54       * (the node type field requires a value)
55       */
56      public static String DUMMY_NODE_TYPE = "DummyNodeType";
57  
58      /***
59       * determine ID for particular items
60       *
61       * @param dbName     The data context
62       * @param nodeType   The node type.
63       * @param attribType The attribute type.
64       * @param matchValue the picklist value.
65       * @return id for specified menu value, or null if not found.
66       * @throws DBException upon error.
67       */
68      public static String getPicklistID(String dbName, String nodeType,
69                                         String attribType, String matchValue) throws DBException {
70          String result = null;
71          PickList pick = new PickList();
72          pick.setDataContext(dbName);
73          pick.setRequestingUser(User.getAdmin(dbName)); // this call is open to the public
74          pick.setField(PickList.NODE_TYPE, nodeType);
75          pick.setField(PickList.ATTRIBUTE_TYPE, attribType);
76          pick.setField(PickList.DISPLAY_IN_PICKLIST, matchValue);
77  
78          if (pick.find()) {
79              result = pick.getID();
80          }
81  
82          return result;
83      }
84  
85      public String getID() throws DBException {
86          return getField(PickList.LIST_ID);
87      }
88  
89      public PickList(ReadOnlyUser theUser) throws DBException {
90          super(theUser);
91      }
92  
93      /***
94       * constructor without parameters is required by framework,
95       * but if you use this constructor,
96       * be sure to setRequestingUid() after instantiation
97       *
98       * @throws DBException upon error.
99       */
100     public PickList() throws DBException {
101     }
102 
103     /***
104      * Constructor
105      *
106      * @param theConnection DBConnection to be used to
107      *                      communicate with the database
108      * @param theUser       User name attempting to access the
109      *                      object
110      * @throws DBException If the user cannot access this
111      *                     object or the object cannot be initialized
112      */
113     public PickList(DBConnection theConnection, int theUser)
114             throws DBException {
115         super(theConnection, theUser);
116     }
117 
118     public PickList(ControllerRequest request) throws DBException {
119         super(request);
120     }
121 
122     public PickList(ControllerRequest request, String id)
123             throws DBException {
124         this(request);
125 
126         setField(LIST_ID, id);
127     }
128 
129     public PickList(String nodeType, String attribType)
130             throws DBException {
131         setField(PickList.NODE_TYPE, nodeType);
132         setField(PickList.ATTRIBUTE_TYPE, attribType);
133     }
134 
135 
136     /***
137      * Defines the database table name and fields for this DB object
138      *
139      * @throws DBException if the operation cannot be performed
140      */
141     protected synchronized void setupFields() throws DBException {
142         setTargetTable(TABLE_NAME);
143         setDescription("Source table for picklist items for all nodes which use picklists");
144         addField(LIST_ID, DBField.AUTOINC_TYPE, 0, false,
145                 "unique id of each item, unique across all lists");
146         addField(NODE_TYPE, DBField.VARCHAR_TYPE, 100, false, "Type of node");
147         addField(ATTRIBUTE_TYPE, DBField.VARCHAR_TYPE, 100, false,
148                 "Type of attribute");
149         addField(DISPLAY_IN_PICKLIST, DBField.VARCHAR_TYPE, 255, true,
150                 "Display in picklist");
151         addField(COMMENT, DBField.LONGVARCHAR_TYPE, 0, true,
152                 "Comment on picklist item");
153         addField(ORDER_NUM, DBField.INTEGER_TYPE, 0, true, "Order in list");
154 
155         addKey(LIST_ID);
156 
157         addIndex("picklist_idx", NODE_TYPE + "," + ATTRIBUTE_TYPE,
158                 false); // group all picklist items together by parent node + attrib type---this is whole menu
159         addIndex("picklist_name_idx", DISPLAY_IN_PICKLIST,
160                 false); // we order by alpha, typically, so put index on it for efficiency
161     } /* setupFields() */
162 
163     /***
164      * implement comparator interface
165      *
166      * @see Comparator
167      */
168     public int compare(Object o1, Object o2) {
169         try {
170             PickList obj1 = (PickList) o1;
171             PickList obj2 = (PickList) o2;
172 
173             Integer i1 = new Integer(obj1.getOrderNumInt());
174             Integer i2 = new Integer(obj2.getOrderNumInt());
175 
176             return i1.compareTo(i2);
177         } catch (DBException dbe) {
178             getLogger().error("TI2: Unable to compare obj values.", dbe);
179 
180             return 0;
181         }
182     }
183 
184     public String getOrderNum() throws DBException {
185         return getField(ORDER_NUM);
186     }
187 
188     public int getOrderNumInt() throws DBException {
189         return getFieldInt(ORDER_NUM);
190     }
191 
192     /***
193      * Compares this object with the specified object for order.  Returns a
194      * negative integer, zero, or a positive integer as this object is less
195      * than, equal to, or greater than the specified object.<p>
196      * <p/>
197      * The implementor must ensure <tt>sgn(x.compareTo(y)) ==
198      * -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
199      * implies that <tt>x.compareTo(y)</tt> must throw an exception iff
200      * <tt>y.compareTo(x)</tt> throws an exception.)<p>
201      * <p/>
202      * The implementor must also ensure that the relation is transitive:
203      * <tt>(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0)</tt> implies
204      * <tt>x.compareTo(z)&gt;0</tt>.<p>
205      * <p/>
206      * Finally, the implementer must ensure that <tt>x.compareTo(y)==0</tt>
207      * implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
208      * all <tt>z</tt>.<p>
209      * <p/>
210      * It is strongly recommended, but <i>not</i> strictly required that
211      * <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>.  Generally speaking, any
212      * class that implements the <tt>Comparable</tt> interface and violates
213      * this condition should clearly indicate this fact.  The recommended
214      * language is "Note: this class has a natural ordering that is
215      * inconsistent with equals."
216      *
217      * @param o the Object to be compared.
218      * @return a negative integer, zero, or a positive integer as this object
219      *         is less than, equal to, or greater than the specified object.
220      * @throws ClassCastException if the specified object's type prevents it
221      *                            from being compared to this Object.
222      */
223     public int compareTo(Object o) {
224         PickList obj2 = (PickList) o;
225 
226         return compare(this, obj2);
227     }
228 
229     /***
230      * @param pickindex
231      * @return String that is display value for given ID, or null if not found
232      * @throws DBException upon error.
233      */
234     public static String getPick(String pickindex)
235             throws DBException {
236         String result = null;
237         PickList pick = new PickList();
238         pick.setField(PickList.LIST_ID, pickindex);
239 
240         if (pick.find()) {
241             result = pick.getField(PickList.DISPLAY_IN_PICKLIST);
242         }
243 
244         return result;
245     }
246 
247     /***
248      * speedy version that skips permission check (for xml)
249      *
250      * @return String that is display value for given ID, or null if not found
251      * @throws DBException upon error.
252      */
253     public static String getPickFast(String pickindex, String dbname)
254             throws DBException {
255         String result = null;
256         PickList pick = new PickList(SuperUser.INSTANCE);
257         pick.setDataContext(dbname);
258         pick.setField(PickList.LIST_ID, pickindex);
259 
260         if (pick.find()) {
261             result = pick.getField(PickList.DISPLAY_IN_PICKLIST);
262         }
263 
264         return result;
265     }
266 
267     /***
268      * @return id which is unique across all lists--index num in table
269      */
270     public int getIndexNum() throws DBException {
271         return getFieldInt(LIST_ID);
272     }
273 
274     public String getDisplayString() throws DBException {
275         return getField(DISPLAY_IN_PICKLIST);
276     }
277 
278     public void setID(String id) throws DBException {
279         setField(LIST_ID, id);
280     }
281 
282     public String getPickAttribType() throws DBException {
283         return getField(ATTRIBUTE_TYPE);
284     }
285 
286     public void setPickAttribType(String type) throws DBException {
287         setField(ATTRIBUTE_TYPE, type);
288     }
289 
290     public String getNodeType() throws DBException {
291         return getField(NODE_TYPE);
292     }
293 
294     public void setNodeType(String type) throws DBException {
295         setField(NODE_TYPE, type);
296     }
297 
298     public void setOrderNum(int order) throws DBException {
299         if (order < 0) {
300             order = 0;
301         }
302 
303         setField(ORDER_NUM, order);
304     }
305 
306     public String getComment() throws DBException {
307         return getField(COMMENT);
308     }
309 
310     /***
311      * provide a transition for viewing this object, suitable for creating an
312      * HTTP link
313      *
314      * @return transtion for viewing, including label for name of object; never null
315      */
316     public Transition getViewTrans() throws DBException {
317         String title = "Picklist item number " + getOrderNum() + " of type: '" + getPickAttribType() + "'";
318         Transition trans = new Transition(title, PicklistAction.class, PicklistAction.PROMPT_EDIT_ITEM);
319         trans.addParam(LIST_ID, getID());
320         return trans;
321     }
322 
323     public void acceptVisitor(ModelVisitor visitor) {
324         visitor.visitPickList(this);
325     }
326 
327 
328     /***
329      * OVERRIDE to use node type permissions
330      *
331      * @param requestedFunction The code of the requested function. The codes are:
332      *                          <ol><li>A: Add<li>
333      *                          <li>S: Search<li>
334      *                          <li>U: Update<li>
335      *                          <li>D: Delete<li>
336      *                          </ol>
337      * @throws com.jcorporate.expresso.core.db.DBException
338      *                           If the requested operation is not permitted to this user
339      * @throws SecurityException if the user is not allowed access to the object.
340      */
341     public void isAllowed(String requestedFunction) throws SecurityException, DBException {
342 
343         // if parent node can be found, use it
344         try {
345             // catch db exception, but NOT securityexception; if parent doesn't allow, don't allow attribute either
346             NodeType type = new NodeType();
347             type.setEntityName(getNodeType());
348             if (!type.find()) {
349                 throw new DBException("cannot find type: " + getNodeType());
350             }
351             type.setRequestingUser(getRequestingUser());
352             type.isAllowed(requestedFunction);
353         } catch (DBException e) {
354             // use local permissons
355             super.isAllowed(requestedFunction);
356         }
357     } /* isAllowed(String) */
358 
359     /***
360      * determine if this function is allowed for this requesting user
361      *
362      * @param requestedFunction code for function -- Add, Update, Delete, Search (read)
363      * @return true if this function is allowed for this requesting user
364      * @throws SecurityException (unchecked) if not allowed
365      * @throws com.jcorporate.expresso.core.db.DBException
366      *                           for other data-related errors.
367      */
368     public boolean isRowAllowed(String requestedFunction) throws DBException {
369         // if parent node can be found, use it
370         boolean result = false;
371         try {
372             // catch db exception, but NOT securityexception; if parent doesn't allow, don't allow attribute either
373             NodeType type = new NodeType();
374             type.setEntityName(getNodeType());
375             if (!type.find()) {
376                 throw new DBException("cannot find type: " + getNodeType());
377             }
378             type.setRequestingUser(getRequestingUser());
379 
380             //type.find() calls isRowAllowed() already.
381             if (!requestedFunction.equals(SEARCH)) {
382                 result = type.isRowAllowed(requestedFunction);
383             } else {
384                 result = true;
385             }
386         } catch (DBException e) {
387             // use local permissons
388             result = super.isRowAllowed(requestedFunction);
389         }
390 
391         return result;
392     }
393 
394     public void setDisplayValue(String descrip) throws DBException {
395         setField(DISPLAY_IN_PICKLIST, descrip);
396     }
397 }