Source code: dods/data/DataObject.java
1 /*-----------------------------------------------------------------------------
2 * Enhydra Java Application Server
3 * Copyright 1997-2000 Lutris Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes Enhydra software developed by Lutris
17 * Technologies, Inc. and its contributors.
18 * 4. Neither the name of Lutris Technologies nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY LUTRIS TECHNOLOGIES AND CONTRIBUTORS ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL LUTRIS TECHNOLOGIES OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *-----------------------------------------------------------------------------
34 * $Id: DataObject.java,v 1.10 2000/01/29 07:01:45 markd Exp $
35 *-----------------------------------------------------------------------------
36 */
37
38
39
40 package dods.data;
41
42 import com.lutris.dods.exceptions.*;
43 import java.util.Vector;
44 import java.io.Serializable;
45 /**
46 * A holder for all the information describing a Data Object.
47 *
48 * @author Philip Martin
49 * @version $Revision: 1.10 $
50 */
51 public class DataObject implements Serializable {
52 /**
53 * Type of mapping this Object will use to go into the Database
54 */
55 protected String dbTableType;
56 /**
57 * All of the Attributes that this Data Object has.
58 */
59 protected Vector attributes;
60 /**
61 * Name of the Package this class will be in.
62 */
63 protected String packageName;
64 /**
65 * All of the DataObjects that this DataObject inherits from.
66 */
67 protected Vector ancestors;
68 /**
69 * This is true if the DataObject is abstract.
70 */
71 protected boolean Abstract;
72 /**
73 * All of the DataObjects which extend this one.
74 */
75 protected Vector extendedBy;
76 /**
77 * Name of the dbTable that this Object will go into.
78 */
79 protected String dbTableName;
80 /**
81 * True when this DataObject is an index for the dataBase.
82 */
83 protected boolean index;
84 /**
85 * The name of this DataObject. This also defines the future class name
86 * which will be nameDO.class
87 */
88 protected String name;
89 /**
90 * All of the DataObjects which have this DataObject as an ancestor.
91 */
92 protected Vector descendents;
93 /**
94 * True if this Class will be final.
95 */
96 protected boolean Final;
97 /**
98 * True if this Class will use "lazy loading" where the DO values are
99 * retrieved from the DB only when on the first get or set call.
100 */
101 protected boolean lazyLoading;
102 /**
103 * True if this Class will fully cache all objects from the database.
104 */
105 protected boolean fullCaching;
106 /**
107 * True if this Class will implement a cache.
108 */
109 protected boolean caching;
110 /**
111 * The DataObject that this DataObject extends.
112 */
113 protected DataObject extensionOf;
114 /**
115 * Valid dbTableType where all concrete classes get a table.
116 */
117 public static final String CONCRETE = "Concrete";
118 /**
119 * Valid dbTableType where all classes get a table.
120 */
121 public static final String ALL_CLASSES = "All Classes";
122 /**
123 * Valid dbTableType where an entire hierarchy is mapped to one table.
124 */
125 public static final String ENTIRE_HIERARCHY = "Entire Hierarchy";
126 /**
127 * Constructor which initializes everything to default values except name.
128 * @param s The DataObject's name.
129 */
130 public DataObject(String s) {
131 this();
132 name = s;
133 }
134 /**
135 * Constructor which initializes all of the variables to default values.
136 */
137 public DataObject() {
138 Abstract = false;
139 index = false;
140 name = "NewObject";
141 dbTableName = "NewDBTable";
142 packageName = "";
143 Final = false;
144 lazyLoading = false;
145 fullCaching = false;
146 caching = false;
147 dbTableType = CONCRETE;
148 extensionOf = null;
149 extendedBy = new Vector();
150 descendents = new Vector();
151 ancestors = new Vector();
152 attributes = new Vector();
153 }
154 /**
155 * Sets the name for this DataObject if it is a valid className.
156 * @exception DataObjectNameException this is thrown if there is a name
157 * conflict or if the string has spaces ect.
158 */
159 public void setName(String s) throws DataObjectNameException {
160 if(s.equals("")) {
161 throw new DataObjectNameException("Class name not Specified");
162 }
163 s.trim();
164 if(!checkIdentifier(s)) {
165 throw new DataObjectNameException("Invalid class name: Use valid Java Identifier");
166 }
167 name = s;
168 }
169 /**
170 * @return The name of the DataObject
171 */
172 public String getName() {
173 return name;
174 }
175 /**
176 * Sets up the name of the Table that this DataObject will be in.
177 * @exception DataObjectNameException Thrown if the name is invalid.
178 */
179 public void setDBTableName(String dbtablename) throws DataObjectNameException {
180 if(dbtablename.equals("")) {
181 throw new DataObjectNameException("DB Table Name not specified.");
182 }
183 dbTableName = dbtablename;
184 }
185 /**
186 * @return The dbTableName for this DataObject.
187 */
188 public String getDBTableName() {
189 return dbTableName;
190 }
191 /**
192 * Set's the name of the Package for this DataObject.
193 * @exception DataObjectNameException Thrown if the package name is invalid.
194 */
195 public void setPackageName(String packagename) throws DataObjectNameException {
196 packagename.trim();
197 if(!checkPackageIdentifier(packagename)) {
198 throw new DataObjectNameException("Invalid PackageName: Use valid Identifier");
199 }
200 packageName = packagename;
201 }
202 /**
203 * @return The packageName.
204 */
205 public String getPackageName() {
206 return packageName;
207 }
208 /**
209 * @return The packageName with leading "root." stripped off.
210 */
211 public String getAdjustedPackageName() {
212 if ( packageName.startsWith( "root." ) )
213 return packageName.substring( 5 );
214 return packageName;
215 }
216 /**
217 * Sets Final for this DataObject
218 */
219 public void setFinal(boolean Fina) {
220 Final = Fina;
221 }
222 /**
223 * @return The type of this DataObject.
224 */
225 public boolean isFinal() {
226 return Final;
227 }
228 /**
229 * Sets lazyLoading for this DataObject
230 */
231 public void setLazyLoading(boolean lazy) {
232 lazyLoading = lazy;
233 }
234 /**
235 * @return The type of this DataObject.
236 */
237 public boolean isLazyLoading() {
238 return lazyLoading;
239 }
240 /**
241 * Sets lazyLoading for this DataObject
242 */
243 public void setFullCaching(boolean full) {
244 fullCaching = full;
245 }
246 /**
247 * @return The type of this DataObject.
248 */
249 public boolean isFullCaching() {
250 return fullCaching;
251 }
252 /**
253 * Sets caching for this DataObject
254 */
255 public void setCaching(boolean impl_cache) {
256 caching = impl_cache;
257 }
258 /**
259 * @return The type of this DataObject.
260 */
261 public boolean isCaching() {
262 return caching;
263 }
264 /**
265 * Sets the DataObject that this extends to a new DataObject
266 * @param extensionof The new DataObject.
267 */
268 public void setExtensionOf(DataObject extensionof) {
269 if(extensionOf != null) {
270 extensionOf.getExtendedBy().removeElement(this);
271 }
272 extensionOf = extensionof;
273 if(extensionOf != null) {
274 extensionOf.getExtendedBy().addElement(this);
275 }
276 updateAncestors();
277 }
278 /**
279 * @return The DataObject that this extends.
280 */
281 public DataObject getExtensionOf(){
282 return extensionOf;
283 }
284 /**
285 * @return The Vector of DataObjects Extended by this DataObject.
286 */
287 public Vector getExtendedBy() {
288 return extendedBy;
289 }
290 /**
291 * @return The Vector of DataObjects that are Descended from this one.
292 */
293 public Vector getDescendents() {
294 return descendents;
295 }
296 /**
297 * @return The Vector containing all of the attributes of this DataObject.
298 */
299 public Vector getAttributes() {
300 return attributes;
301 }
302 /**
303 * Sets the attributes to the new vector of attributes.
304 */
305 public void setAttributes(Vector atts) {
306 attributes.removeAllElements();
307 for(int i = 0; i < atts.size(); i++) {
308 attributes.addElement(atts.elementAt(i));
309 }
310 }
311 /**
312 * Adds a new Attribute.
313 */
314 public void addAttribute(Attribute att) {
315 //System.err.println("DataObject.addAttribute");
316 attributes.addElement(att);
317 }
318 /**
319 * Sets if this is an index or not.
320 */
321 public void setIndex(boolean Index) {
322 index = Index;
323 }
324 /**
325 * @return True if this is an index DataObject
326 */
327 public boolean isIndex() {
328 return index;
329 }
330 /**
331 * Sets if this is an abstract Class.
332 */
333 public void setAbstract(boolean abstract1) {
334 Abstract = abstract1;
335 }
336 /**
337 * @return True if this is a concrete DataObject.
338 */
339 public boolean isConcrete() {
340 return ( isLeaf() && ! isAbstract() );
341 }
342 /**
343 * @return True if this is a leaf DataObject.
344 */
345 public boolean isLeaf() {
346 Vector descendants = getDescendents();
347 if ( 0 == descendants.size() )
348 return true;
349 return false;
350 }
351 /**
352 * @return True if this is an Abstract DataObject.
353 */
354 public boolean isAbstract() {
355 return Abstract;
356 }
357 /**
358 * Sets the DBTableType to a new valid value.
359 * @exception DataObjectTypeException Thrown if the DBTableType is invalid.
360 */
361 public void setDBTableType(String dbtabletype) throws DataObjectTypeException {
362 if(dbtabletype.equals(CONCRETE) || dbtabletype.equals(ALL_CLASSES) || dbtabletype.equals(ENTIRE_HIERARCHY)) {
363 dbTableType = dbtabletype;
364 }
365 else {
366 throw new DataObjectTypeException("Invalid Database Mapping type");
367 }
368 }
369 /**
370 * @return THe DBTableType for this DataObject.
371 */
372 public String getDBTableType() {
373 return dbTableType;
374 }
375 /**
376 * @return The vector containing all of the Ancestors of this DataObject.
377 */
378 public Vector getAncestors() {
379 return ancestors;
380 }
381 /**
382 * Determines if two DataObjects are equal by comparing each value in them.
383 */
384 public boolean equals(DataObject doa) {
385 if(!doa.getName().equals(this.getName()))
386 return false;
387 if(!doa.getPackageName().equals(this.getPackageName()))
388 return false;
389 if(index != doa.isIndex())
390 return false;
391 if(extensionOf != null) {
392 if(doa.getExtensionOf() == null) {
393 return false;
394 }
395 }
396 else {
397 if(doa.getExtensionOf() != null) {
398 return false;
399 }
400 }
401 if(!dbTableType.equals(doa.getDBTableType()))
402 return false;
403 if(!dbTableName.equals(doa.getDBTableName()))
404 return false;
405 if(Final != doa.isFinal())
406 return false;
407 if(Abstract != doa.isAbstract())
408 return false;
409 if(doa.getAttributes().size() != attributes.size())
410 return false;
411 if(doa.getAncestors().size() != ancestors.size())
412 return false;
413 if(doa.getDescendents().size() != descendents.size())
414 return false;
415 if(doa.getExtendedBy().size() != extendedBy.size())
416 return false;
417 for(int i = 0; i < attributes.size(); i++) {
418 if(!((Attribute)attributes.elementAt(i)).equals((Attribute)doa.getAttributes().elementAt(i)))
419 return false;
420 }
421 return true;
422 }
423 /**
424 * Returns a String representation of the form:
425 * "<I>packageName</I>.<I>name</I>DO"
426 */
427 public String toString() {
428 return new String(packageName + "." + name + "DO");
429 }
430 /**
431 * Returns true if the string is a valid identifier.
432 */
433 public boolean checkIdentifier(String s) {
434 int length = s.length();
435 char[] chars = new char[length];
436 s.getChars(0, length-1, chars, 0);
437 if(!Character.isJavaIdentifierStart(chars[0]))
438 return false;
439 for(int i = 1; i < length; i++){
440 if(!Character.isJavaIdentifierPart(chars[i]))
441 return false;
442 }
443 return true;
444 }
445 /**
446 * Similar to checkIdentifier, but this will not give an error when "." are
447 * found in the string.
448 */
449 public boolean checkPackageIdentifier(String s) {
450 int length = s.length();
451 char[] chars = new char[length];
452 s.getChars(0, length-1, chars, 0);
453 if(!Character.isJavaIdentifierStart(chars[0]))
454 return false;
455 for(int i = 1; i < length; i++){
456 if(!Character.isJavaIdentifierPart(chars[i])) {
457 if(chars[i] != '.')
458 return false;
459 }
460 }
461 return true;
462 }
463 /**
464 * This method reworks the hierarchy of DataObjects when a relationship
465 * between them is changed.
466 */
467 public void updateAncestors() {
468 for(int i = 0; i < ancestors.size(); i++) {
469 ((DataObject)ancestors.elementAt(i)).getDescendents().removeElement(this);
470 for(int j = 0; j < descendents.size(); j++) {
471 ((DataObject)ancestors.elementAt(i)).getDescendents().removeElement(
472 ((DataObject)descendents.elementAt(j)));
473 }
474 }
475 ancestors = new Vector();
476 if(extensionOf != null) {
477 for(int i = 0; i < extensionOf.getAncestors().size(); i++) {
478 ancestors.addElement(extensionOf.getAncestors().elementAt(i));
479 }
480 ancestors.addElement(extensionOf);
481 }
482 for(int i = 0; i < ancestors.size(); i++) {
483 ((DataObject)ancestors.elementAt(i)).getDescendents().addElement(this);
484 for(int j = 0; j < descendents.size(); j++) {
485 ((DataObject)ancestors.elementAt(i)).getDescendents().addElement(
486 ((DataObject)descendents.elementAt(j)));
487 }
488 }
489 for(int i = 0; i < extendedBy.size(); i++) {
490 ((DataObject)extendedBy.elementAt(i)).updateAncestors();
491 }
492 }
493 /**
494 * This method checks to see if any of the Attributes in this DataObject
495 * have errors.
496 */
497 public boolean hasAttributeErrors() {
498 for(int i = 0; i < attributes.size(); i++) {
499 if(((Attribute)attributes.elementAt(i)).hasError()) {
500 return true;
501 }
502 }
503 return false;
504 }
505
506 /**
507 * This method will take in a vector of DataObjects and Strings and
508 * stick all of the strings at the front and alphabetize the DataObjects.
509 */
510 public static Vector alphabetizeVector(Vector DOS) {
511 Vector newDOS = new Vector();
512 int strings = 0;
513 for(int i = 0; i < DOS.size(); i++) {
514 if(DOS.elementAt(i) instanceof String) {
515 newDOS.insertElementAt(DOS.elementAt(i), 0);
516 strings++;
517 }
518 else{
519 DataObject DO = (DataObject)DOS.elementAt(i);
520 boolean added = false;
521 for(int j = strings; j < newDOS.size(); j++) {
522 DataObject newDO = (DataObject)newDOS.elementAt(j);
523 if(DO.getName().compareTo(newDO.getName()) < 0) {
524 newDOS.insertElementAt(DO, j);
525 added = true;
526 break;
527 }
528 }
529 if(!added) {
530 newDOS.addElement(DO);
531 }
532 }
533 }
534 return newDOS;
535 }
536 }