1 package org.apache.ojb.broker.metadata;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.util.Hashtable;
19 import java.util.Iterator;
20 import java.util.Vector;
21
22 import org.apache.commons.lang.builder.ToStringBuilder;
23 import org.apache.ojb.broker.OJBRuntimeException;
24 import org.apache.ojb.broker.PersistenceBrokerException;
25 import org.apache.ojb.broker.core.proxy.ProxyHelper;
26 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
27
28
29
30
31
32
33
34
35
36
37 public class ObjectReferenceDescriptor extends AttributeDescriptorBase implements XmlCapable
38 {
39 private static final long serialVersionUID = 5561562217150972131L;
40
41 public static final int CASCADE_NONE = 17;
42 public static final int CASCADE_LINK = 19;
43 public static final int CASCADE_OBJECT = 23;
44
45 private Class m_ClassOfItems = null;
46 private Vector m_ForeignKeyFields = new Vector();
47 private boolean m_CascadeRetrieve = true;
48 private int m_CascadeStore = CASCADE_NONE;
49 private int m_CascadeDelete = CASCADE_NONE;
50 private int m_ProxyPrefetchingLimit = 50;
51
52 private Class m_ProxyOfItems = null;
53 private boolean m_LookedUpProxy = false;
54 private boolean m_OtmDependent = false;
55
56
57
58
59 private Hashtable fkFieldMap = new Hashtable();
60
61
62
63 private boolean lazy = false;
64
65
66
67 private boolean refresh = false;
68
69
70
71
72 public ObjectReferenceDescriptor(ClassDescriptor descriptor)
73 {
74 super(descriptor);
75 }
76
77
78
79
80 public Class getItemProxyClass() throws PersistenceBrokerException
81 {
82 if (!m_LookedUpProxy)
83 {
84 m_ProxyOfItems = getClassDescriptor().getRepository().
85 getDescriptorFor(m_ClassOfItems).getProxyClass();
86 m_LookedUpProxy = true;
87 }
88 return m_ProxyOfItems;
89 }
90
91
92
93
94 public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor cld)
95 {
96 FieldDescriptor[] foreignKeyFieldDescriptors;
97 if ((foreignKeyFieldDescriptors = (FieldDescriptor[]) fkFieldMap.get(cld)) == null)
98 {
99
100 Vector v = getForeignKeyFields();
101
102
103 if (v != null)
104 {
105 Vector ret;
106 if (cld.isInterface())
107 {
108
109
110 Vector extents = cld.getExtentClasses();
111 Class firstConcreteClass = (Class) extents.get(0);
112 cld = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
113 }
114 ret = new Vector();
115
116 Iterator iter = v.iterator();
117 while (iter.hasNext())
118 {
119 Object fk = iter.next();
120 FieldDescriptor fkfd = null;
121
122
123
124
125
126 ClassDescriptor tmp = cld;
127 while(tmp != null)
128 {
129 if (fk instanceof Integer)
130 {
131 Integer index = (Integer) fk;
132 fkfd = cld.getFieldDescriptorByIndex(index.intValue());
133 }
134 else
135 {
136 fkfd = tmp.getFieldDescriptorByName((String) fk);
137 }
138 if(fkfd != null)
139 {
140 break;
141 }
142 else
143 {
144 tmp = tmp.getSuperClassDescriptor();
145 }
146 }
147
148 if (fkfd == null)
149 {
150 throw new OJBRuntimeException("Incorrect or not found field reference name '"
151 + fk + "' in descriptor " + this + " for class-descriptor '"
152 + (cld != null ? cld.getClassNameOfObject() + "'" : "'null'"));
153 }
154 ret.add(fkfd);
155 }
156 foreignKeyFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
157 fkFieldMap.put(cld, foreignKeyFieldDescriptors);
158 }
159 }
160 return foreignKeyFieldDescriptors;
161 }
162
163
164
165
166
167
168
169
170 public Object[] getForeignKeyValues(Object obj, ClassDescriptor mif)
171 throws PersistenceBrokerException
172 {
173 FieldDescriptor[] fks = getForeignKeyFieldDescriptors(mif);
174
175 if(fks.length > 0) obj = ProxyHelper.getRealObject(obj);
176 Object[] result = new Object[fks.length];
177 for (int i = 0; i < result.length; i++)
178 {
179 FieldDescriptor fmd = fks[i];
180 PersistentField f = fmd.getPersistentField();
181
182
183
184
185
186
187
188 result[i] = f.get(obj);
189 }
190 return result;
191 }
192
193
194
195
196 public Class getItemClass()
197 {
198 return m_ClassOfItems;
199 }
200
201
202
203
204 public String getItemClassName()
205 {
206 return this.m_ClassOfItems != null ? this.m_ClassOfItems.getName() : null;
207 }
208
209
210
211
212
213 public void setItemClass(Class c)
214 {
215 m_ClassOfItems = c;
216 }
217
218
219
220
221 public Vector getForeignKeyFields()
222 {
223 return m_ForeignKeyFields;
224 }
225
226
227
228
229 public void setForeignKeyFields(Vector vec)
230 {
231 m_ForeignKeyFields = vec;
232 }
233
234
235
236
237 public void addForeignKeyField(int newId)
238 {
239 if (m_ForeignKeyFields == null)
240 {
241 m_ForeignKeyFields = new Vector();
242 }
243 m_ForeignKeyFields.add(new Integer(newId));
244 }
245
246
247
248
249 public void addForeignKeyField(String newField)
250 {
251 if (m_ForeignKeyFields == null)
252 {
253 m_ForeignKeyFields = new Vector();
254 }
255 m_ForeignKeyFields.add(newField);
256 }
257
258
259
260
261
262 public boolean isRefresh()
263 {
264 return refresh;
265 }
266
267
268
269
270
271 public void setRefresh(boolean refresh)
272 {
273 this.refresh = refresh;
274 }
275
276
277
278
279
280 public boolean isLazy()
281 {
282 return lazy;
283 }
284
285
286
287
288
289 public void setLazy(boolean lazy)
290 {
291 this.lazy = lazy;
292 }
293
294
295
296
297 public boolean getCascadeRetrieve()
298 {
299 return m_CascadeRetrieve;
300 }
301
302
303
304
305 public void setCascadeRetrieve(boolean b)
306 {
307 m_CascadeRetrieve = b;
308 }
309
310
311
312
313 public int getCascadingStore()
314 {
315 return m_CascadeStore;
316 }
317
318
319
320
321 public void setCascadingStore(int cascade)
322 {
323 m_CascadeStore = cascade;
324 }
325
326 public void setCascadingStore(String value)
327 {
328 setCascadingStore(getCascadeStoreValue(value));
329 }
330
331
332
333
334 public boolean getCascadeStore()
335 {
336 return getCascadingStore() == CASCADE_OBJECT;
337 }
338
339
340
341
342 public void setCascadeStore(boolean cascade)
343 {
344 if(cascade)
345 {
346 setCascadingStore(getCascadeStoreValue("true"));
347 }
348 else
349 {
350 setCascadingStore(getCascadeStoreValue("false"));
351 }
352 }
353
354
355
356
357 public int getCascadingDelete()
358 {
359 return m_CascadeDelete;
360 }
361
362
363
364
365 public void setCascadingDelete(int cascade)
366 {
367 m_CascadeDelete = cascade;
368 }
369
370 public void setCascadingDelete(String value)
371 {
372 setCascadingDelete(getCascadeDeleteValue(value));
373 }
374
375
376
377
378 public boolean getCascadeDelete()
379 {
380 return getCascadingDelete() == CASCADE_OBJECT;
381 }
382
383
384
385
386 public void setCascadeDelete(boolean cascade)
387 {
388 if(cascade)
389 {
390 setCascadingDelete(getCascadeDeleteValue("true"));
391 }
392 else
393 {
394 setCascadingDelete(getCascadeDeleteValue("false"));
395 }
396 }
397
398 protected int getCascadeStoreValue(String cascade)
399 {
400 if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
401 {
402 return CASCADE_NONE;
403 }
404 else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
405 {
406 return CASCADE_LINK;
407 }
408 else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
409 {
410 return CASCADE_OBJECT;
411 }
412 else if(cascade.equalsIgnoreCase("true"))
413 {
414 return CASCADE_OBJECT;
415 }
416 else if(cascade.equalsIgnoreCase("false"))
417 {
418
419
420
421
422
423 return CASCADE_LINK;
424 }
425 else
426 {
427 throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
428 + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
429 + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
430 + " ('false' and 'true' are deprecated but still valid)");
431 }
432 }
433
434 protected int getCascadeDeleteValue(String cascade)
435 {
436 if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
437 {
438 return CASCADE_NONE;
439 }
440 else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
441 {
442 return CASCADE_LINK;
443 }
444 else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
445 {
446 return CASCADE_OBJECT;
447 }
448 else if(cascade.equalsIgnoreCase("true"))
449 {
450 return CASCADE_OBJECT;
451 }
452 else if(cascade.equalsIgnoreCase("false"))
453 {
454 return CASCADE_NONE;
455 }
456 else
457 {
458 throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
459 + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
460 + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
461 + " ('false' and 'true' are deprecated but still valid)");
462 }
463 }
464
465 public String getCascadeAsString(int cascade)
466 {
467 String result = null;
468 switch(cascade)
469 {
470 case CASCADE_NONE:
471 result = RepositoryTags.CASCADE_NONE_STR;
472 break;
473 case CASCADE_LINK:
474 result = RepositoryTags.CASCADE_LINK_STR;
475 break;
476 case CASCADE_OBJECT:
477 result = RepositoryTags.CASCADE_OBJECT_STR;
478 break;
479 }
480 return result;
481 }
482
483 public int getProxyPrefetchingLimit()
484 {
485 return m_ProxyPrefetchingLimit;
486 }
487
488 public void setProxyPrefetchingLimit(int proxyPrefetchingLimit)
489 {
490 m_ProxyPrefetchingLimit = proxyPrefetchingLimit;
491 }
492
493
494
495
496 public boolean getOtmDependent()
497 {
498 return m_OtmDependent;
499 }
500
501
502
503
504 public void setOtmDependent(boolean b)
505 {
506 m_OtmDependent = b;
507 }
508
509
510
511
512
513
514
515 public boolean isSuperReferenceDescriptor()
516 {
517 return false;
518 }
519
520
521
522
523
524 public boolean hasConstraint()
525 {
526
527
528
529
530
531 String result = getAttribute("constraint");
532 return result != null && result.equalsIgnoreCase("true");
533 }
534
535
536
537
538
539 public void setConstraint(boolean constraint)
540 {
541 addAttribute("constraint", constraint ? "true" : "false");
542 }
543
544 public String toString()
545 {
546 return new ToStringBuilder(this)
547 .append("cascade_retrieve", getCascadeRetrieve())
548 .append("cascade_store", getCascadeAsString(m_CascadeStore))
549 .append("cascade_delete", getCascadeAsString(m_CascadeDelete))
550 .append("is_lazy", lazy)
551 .append("class_of_Items", m_ClassOfItems)
552 .toString();
553 }
554
555
556
557
558 public String toXML()
559 {
560 RepositoryTags tags = RepositoryTags.getInstance();
561 String eol = System.getProperty( "line.separator" );
562
563
564 StringBuffer result = new StringBuffer( 1024 );
565 result.append( " " );
566 result.append( tags.getOpeningTagNonClosingById( REFERENCE_DESCRIPTOR ) );
567 result.append( eol );
568
569
570
571 String name = this.getAttributeName();
572 if( name == null )
573 {
574 name = RepositoryElements.TAG_SUPER;
575 }
576 result.append( " " );
577 result.append( tags.getAttribute( FIELD_NAME, name ) );
578 result.append( eol );
579
580
581 result.append( " " );
582 result.append( tags.getAttribute( REFERENCED_CLASS, this.getItemClassName() ) );
583 result.append( eol );
584
585
586 if( isLazy() )
587 {
588 result.append( " " );
589 result.append( tags.getAttribute( PROXY_REFERENCE, "true" ) );
590 result.append( eol );
591 result.append( " " );
592 result.append( tags.getAttribute( PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit() ) );
593 result.append( eol );
594 }
595
596
597 if( isRefresh() )
598 {
599 result.append( " " );
600 result.append( tags.getAttribute( REFRESH, "true" ) );
601 result.append( eol );
602 }
603
604
605 result.append( " " );
606 result.append( tags.getAttribute( AUTO_RETRIEVE, "" + getCascadeRetrieve() ) );
607 result.append( eol );
608
609
610 result.append( " " );
611 result.append( tags.getAttribute( AUTO_UPDATE, getCascadeAsString( getCascadingStore() ) ) );
612 result.append( eol );
613
614
615 result.append( " " );
616 result.append( tags.getAttribute( AUTO_DELETE, getCascadeAsString( getCascadingDelete() ) ) );
617 result.append( eol );
618
619
620 if( getOtmDependent() )
621 {
622 result.append( " " );
623 result.append( tags.getAttribute( OTM_DEPENDENT, "true" ) );
624 result.append( eol );
625 }
626
627
628 result.append( " >" );
629 result.append( eol );
630
631
632
633 for( int i = 0; i < getForeignKeyFields().size(); i++ )
634 {
635 Object obj = getForeignKeyFields().get( i );
636 if( obj instanceof Integer )
637 {
638 String fkId = obj.toString();
639 result.append( " " );
640 result.append( tags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
641 result.append( " " );
642 result.append( tags.getAttribute( FIELD_ID_REF, fkId ) );
643 result.append( "/>" );
644 result.append( eol );
645 }
646 else
647 {
648 String fk = ( String ) obj;
649 result.append( " " );
650 result.append( tags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
651 result.append( " " );
652 result.append( tags.getAttribute( FIELD_REF, fk ) );
653 result.append( "/>" );
654 result.append( eol );
655 }
656 }
657
658
659 result.append( " " );
660 result.append( tags.getClosingTagById( REFERENCE_DESCRIPTOR ) );
661 result.append( eol );
662 return result.toString();
663 }
664 }