001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Rodrigo Westrupp
028: */
029:
030: package com.caucho.amber.cfg;
031:
032: import com.caucho.amber.field.IdField;
033: import com.caucho.amber.table.ForeignColumn;
034: import com.caucho.amber.type.AbstractStatefulType;
035: import com.caucho.amber.type.RelatedType;
036: import com.caucho.bytecode.JAccessibleObject;
037: import com.caucho.bytecode.JAnnotation;
038: import com.caucho.bytecode.JClass;
039: import com.caucho.bytecode.JField;
040: import com.caucho.bytecode.JMethod;
041: import com.caucho.config.ConfigException;
042: import com.caucho.util.L10N;
043:
044: import java.util.ArrayList;
045: import java.util.HashMap;
046: import java.util.HashSet;
047: import java.util.Iterator;
048: import java.util.logging.Logger;
049: import java.lang.reflect.*;
050:
051: /**
052: * Abstract introspector for orm.xml and annotations.
053: */
054: abstract public class AbstractConfigIntrospector {
055: private static final Logger log = Logger
056: .getLogger(AbstractConfigIntrospector.class.getName());
057: private static final L10N L = new L10N(
058: AbstractConfigIntrospector.class);
059:
060: // annotations allowed for a property
061: static HashSet<String> _propertyAnnotations = new HashSet<String>();
062:
063: // types allowed with a @Basic annotation
064: static HashSet<String> _basicTypes = new HashSet<String>();
065:
066: // annotations allowed with a @Basic annotation
067: static HashSet<String> _basicAnnotations = new HashSet<String>();
068:
069: // types allowed with an @Id annotation
070: static HashSet<String> _idTypes = new HashSet<String>();
071:
072: // annotations allowed with an @Id annotation
073: static HashSet<String> _idAnnotations = new HashSet<String>();
074:
075: // annotations allowed with a @ManyToOne annotation
076: static HashSet<String> _manyToOneAnnotations = new HashSet<String>();
077:
078: // annotations allowed with a @OneToMany annotation
079: static HashSet<String> _oneToManyAnnotations = new HashSet<String>();
080:
081: // types allowed with a @OneToMany annotation
082: static HashSet<String> _oneToManyTypes = new HashSet<String>();
083:
084: // annotations allowed with a @ManyToMany annotation
085: static HashSet<String> _manyToManyAnnotations = new HashSet<String>();
086:
087: // types allowed with a @ManyToMany annotation
088: static HashSet<String> _manyToManyTypes = new HashSet<String>();
089:
090: // annotations allowed with a @OneToOne annotation
091: static HashSet<String> _oneToOneAnnotations = new HashSet<String>();
092:
093: // annotations allowed with a @Embedded annotation
094: static HashSet<String> _embeddedAnnotations = new HashSet<String>();
095:
096: // annotations allowed with a @EmbeddedId annotation
097: static HashSet<String> _embeddedIdAnnotations = new HashSet<String>();
098:
099: // annotations allowed with a @Version annotation
100: static HashSet<String> _versionAnnotations = new HashSet<String>();
101:
102: // types allowed with an @Version annotation
103: static HashSet<String> _versionTypes = new HashSet<String>();
104:
105: AnnotationConfig _annotationCfg = new AnnotationConfig();
106:
107: /**
108: * Validates a callback method
109: */
110: void validateCallback(String callbackName, JMethod method,
111: boolean isListener) throws ConfigException {
112: if (method.isFinal())
113: throw error(
114: method,
115: L
116: .l(
117: "'{0}' must not be final. @{1} methods may not be final.",
118: method.getFullName(), callbackName));
119:
120: if (method.isStatic())
121: throw error(
122: method,
123: L
124: .l(
125: "'{0}' must not be static. @{1} methods may not be static.",
126: method.getFullName(), callbackName));
127:
128: JClass params[] = method.getParameterTypes();
129:
130: if (isListener) {
131: if (params.length != 1) {
132: throw error(
133: method,
134: L
135: .l(
136: "'{0}' must have the <METHOD>(Object) signature for entity listeners.",
137: method.getFullName()));
138: }
139: } else if (params.length != 0) {
140: throw error(
141: method,
142: L
143: .l(
144: "'{0}' must not have any arguments. @{1} methods have zero arguments for entities or mapped superclasses.",
145: method.getFullName(), callbackName));
146: }
147: }
148:
149: /**
150: * Validates the bean
151: */
152: public void validateType(JClass type, boolean isEntity)
153: throws ConfigException {
154: if (type.isFinal())
155: throw new ConfigException(
156: L
157: .l(
158: "'{0}' must not be final. Entity beans may not be final.",
159: type.getName()));
160:
161: // NOTE: Both abstract and concrete classes can be entities.
162:
163: // MappedSuperclass does not need constructor validation.
164: if (isEntity)
165: validateConstructor(type);
166:
167: for (JMethod method : type.getMethods()) {
168: if (method.getDeclaringClass().getName().equals(
169: "java.lang.Object")) {
170: } else if (method.isFinal())
171: throw error(
172: method,
173: L
174: .l(
175: "'{0}' must not be final. Entity beans methods may not be final.",
176: method.getFullName()));
177: }
178: }
179:
180: /**
181: * Checks for a valid constructor.
182: */
183: public void validateConstructor(JClass type) throws ConfigException {
184: for (JMethod ctor : type.getConstructors()) {
185: JClass[] param = ctor.getParameterTypes();
186:
187: if (param.length == 0
188: && (ctor.isPublic() || ctor.isProtected()))
189: return;
190: }
191:
192: // jpa/0gb2
193: throw new ConfigException(
194: L
195: .l(
196: "'{0}' needs a public or protected no-arg constructor. Entity beans must have a public or protected no-arg constructor.",
197: type.getName()));
198: }
199:
200: /**
201: * Validates a non-getter method.
202: */
203: public void validateNonGetter(JMethod method)
204: throws ConfigException {
205: JAnnotation ann = isAnnotatedMethod(method);
206:
207: if ((ann != null)
208: && (!ann.getType().equals("javax.persistence.Version"))) {
209: throw error(
210: method,
211: L
212: .l(
213: "'{0}' is not a valid annotation for {1}. Only public getters and fields may have property annotations.",
214: ann.getType(), method.getFullName()));
215: }
216: }
217:
218: /**
219: * Validates a non-getter method.
220: */
221: JAnnotation isAnnotatedMethod(JMethod method)
222: throws ConfigException {
223: for (JAnnotation ann : method.getDeclaredAnnotations()) {
224: if (_propertyAnnotations.contains(ann.getType())) {
225: return ann;
226: }
227: }
228:
229: return null;
230: }
231:
232: static boolean containsFieldOrCompletion(AbstractStatefulType type,
233: String fieldName) {
234: // jpa/0l03
235:
236: while (type != null) {
237:
238: if (type.getField(fieldName) != null)
239: return true;
240:
241: if (type.containsCompletionField(fieldName))
242: return true;
243:
244: if (type instanceof RelatedType)
245: type = ((RelatedType) type).getParentType();
246: }
247:
248: return false;
249: }
250:
251: static void validateAnnotations(JAccessibleObject field,
252: String fieldType, HashSet<String> validAnnotations)
253: throws ConfigException {
254: for (JAnnotation ann : field.getDeclaredAnnotations()) {
255: String name = ann.getType();
256:
257: if (!name.startsWith("javax.persistence"))
258: continue;
259:
260: if (!validAnnotations.contains(name)) {
261: throw error(
262: field,
263: L
264: .l(
265: "{0} may not have a @{1} annotation. {2} does not allow @{3}.",
266: field.getName(), name,
267: fieldType, name));
268: }
269: }
270: }
271:
272: static ConfigException error(JAccessibleObject field, String msg) {
273: // XXX: the field is for line numbers in the source, theoretically
274:
275: String className = field.getDeclaringClass().getName();
276:
277: int line = field.getLine();
278:
279: if (line > 0)
280: return new ConfigException(className + ":" + line + ": "
281: + msg);
282: else
283: return new ConfigException(className + "."
284: + field.getName() + ": " + msg);
285: }
286:
287: static String toFieldName(String name) {
288: if (Character.isLowerCase(name.charAt(0)))
289: return name;
290: else if (name.length() == 1
291: || Character.isLowerCase(name.charAt(1)))
292: return Character.toLowerCase(name.charAt(0))
293: + name.substring(1);
294: else
295: return name;
296: }
297:
298: static ArrayList<ForeignColumn> calculateColumns(
299: com.caucho.amber.table.Table mapTable, RelatedType type,
300: Object[] joinColumnsAnn) {
301: if (joinColumnsAnn == null || joinColumnsAnn.length == 0)
302: return calculateColumns(mapTable, type);
303:
304: ArrayList<ForeignColumn> columns = new ArrayList<ForeignColumn>();
305:
306: for (int i = 0; i < joinColumnsAnn.length; i++) {
307: ForeignColumn foreignColumn;
308: JAnnotation joinColumnAnn = (JAnnotation) joinColumnsAnn[i];
309:
310: foreignColumn = mapTable.createForeignColumn(joinColumnAnn
311: .getString("name"), type.getId().getKey()
312: .getColumns().get(0));
313:
314: columns.add(foreignColumn);
315: }
316:
317: return columns;
318: }
319:
320: static ArrayList<ForeignColumn> calculateColumns(
321: JAccessibleObject field,
322: com.caucho.amber.table.Table mapTable, String prefix,
323: RelatedType type, Object[] joinColumnsAnn,
324: HashMap<String, JoinColumnConfig> joinColumnsConfig)
325: throws ConfigException {
326: if ((joinColumnsAnn == null || joinColumnsAnn.length == 0)
327: && (joinColumnsConfig == null || joinColumnsConfig
328: .size() == 0))
329: return calculateColumns(mapTable, prefix, type);
330:
331: ArrayList<ForeignColumn> columns = new ArrayList<ForeignColumn>();
332:
333: // #1448 not reproduced.
334: if (type.getId() == null)
335: throw error(field, L.l(
336: "Entity {0} has no primary key defined.", type
337: .getName()));
338:
339: ArrayList<IdField> idFields = type.getId().getKeys();
340:
341: int len;
342:
343: if (joinColumnsAnn != null)
344: len = joinColumnsAnn.length;
345: else
346: len = joinColumnsConfig.size();
347:
348: if (len != idFields.size()) {
349: throw error(
350: field,
351: L
352: .l(
353: "@JoinColumns for {0} do not match number of the primary key columns in {1}. The foreign key columns must match the primary key columns.",
354: field.getName(), type.getName()));
355: }
356:
357: Iterator it = null;
358:
359: if (joinColumnsConfig != null)
360: it = joinColumnsConfig.values().iterator();
361:
362: for (int i = 0; i < len; i++) {
363: ForeignColumn foreignColumn;
364:
365: String name;
366:
367: if (joinColumnsAnn != null) {
368: JAnnotation joinColumnAnn = (JAnnotation) joinColumnsAnn[i];
369: name = joinColumnAnn.getString("name");
370: } else {
371: JoinColumnConfig joinColumnConfig = (JoinColumnConfig) it
372: .next();
373: name = joinColumnConfig.getName();
374: }
375:
376: foreignColumn = mapTable.createForeignColumn(name, idFields
377: .get(i).getColumns().get(0));
378:
379: columns.add(foreignColumn);
380: }
381:
382: return columns;
383: }
384:
385: static ArrayList<ForeignColumn> calculateColumns(
386: com.caucho.amber.table.Table mapTable, RelatedType type) {
387: ArrayList<ForeignColumn> columns = new ArrayList<ForeignColumn>();
388:
389: RelatedType parentType = type;
390:
391: ArrayList<com.caucho.amber.table.Column> targetIdColumns;
392:
393: targetIdColumns = type.getId().getColumns();
394:
395: while (targetIdColumns.size() == 0) {
396:
397: parentType = parentType.getParentType();
398:
399: if (parentType == null)
400: break;
401:
402: targetIdColumns = parentType.getId().getColumns();
403: }
404:
405: for (com.caucho.amber.table.Column key : targetIdColumns) {
406: columns.add(mapTable
407: .createForeignColumn(key.getName(), key));
408: }
409:
410: return columns;
411: }
412:
413: static ArrayList<ForeignColumn> calculateColumns(
414: com.caucho.amber.table.Table mapTable, String prefix,
415: RelatedType type) {
416: ArrayList<ForeignColumn> columns = new ArrayList<ForeignColumn>();
417:
418: RelatedType parentType = type;
419:
420: ArrayList<com.caucho.amber.table.Column> targetIdColumns;
421:
422: targetIdColumns = type.getId().getColumns();
423:
424: while (targetIdColumns.size() == 0) {
425:
426: parentType = parentType.getParentType();
427:
428: if (parentType == null)
429: break;
430:
431: targetIdColumns = parentType.getId().getColumns();
432: }
433:
434: for (com.caucho.amber.table.Column key : targetIdColumns) {
435: columns.add(mapTable.createForeignColumn(prefix
436: + key.getName(), key));
437: }
438:
439: return columns;
440: }
441:
442: protected static String loc(JMethod method) {
443: return method.getDeclaringClass().getName() + "."
444: + method.getName() + ": ";
445: }
446:
447: protected static String loc(Method method) {
448: return method.getDeclaringClass().getSimpleName() + "."
449: + method.getName() + ": ";
450: }
451:
452: protected static String loc(JField field) {
453: return field.getDeclaringClass().getName() + "."
454: + field.getName() + ": ";
455: }
456:
457: protected static String loc(Field field) {
458: return field.getDeclaringClass().getSimpleName() + "."
459: + field.getName() + ": ";
460: }
461:
462: public static String toSqlName(String name) {
463: return name.toUpperCase();
464: }
465:
466: class AnnotationConfig {
467: private JAnnotation _annotation;
468: private Object _config;
469:
470: public JAnnotation getAnnotation() {
471: return _annotation;
472: }
473:
474: public Object getConfig() {
475: return _config;
476: }
477:
478: public void setAnnotation(JAnnotation annotation) {
479: _annotation = annotation;
480: }
481:
482: public void setConfig(Object config) {
483: _config = config;
484: }
485:
486: public boolean isNull() {
487: return (_annotation == null) && (_config == null);
488: }
489:
490: public void reset() {
491: _annotation = null;
492: _config = null;
493: }
494:
495: public void reset(JClass type, Class cl) {
496: _annotation = type.getAnnotation(cl);
497: _config = null;
498: }
499:
500: public void reset(JAccessibleObject field, Class cl) {
501: _annotation = field.getAnnotation(cl);
502: _config = null;
503: }
504:
505: public EmbeddableConfig getEmbeddableConfig() {
506: return (EmbeddableConfig) _config;
507: }
508:
509: public EntityConfig getEntityConfig() {
510: return (EntityConfig) _config;
511: }
512:
513: public MappedSuperclassConfig getMappedSuperclassConfig() {
514: return (MappedSuperclassConfig) _config;
515: }
516:
517: public EntityListenersConfig getEntityListenersConfig() {
518: return (EntityListenersConfig) _config;
519: }
520:
521: public TableConfig getTableConfig() {
522: return (TableConfig) _config;
523: }
524:
525: public SecondaryTableConfig getSecondaryTableConfig() {
526: return (SecondaryTableConfig) _config;
527: }
528:
529: public IdClassConfig getIdClassConfig() {
530: return (IdClassConfig) _config;
531: }
532:
533: public PostLoadConfig getPostLoadConfig() {
534: return (PostLoadConfig) _config;
535: }
536:
537: public PrePersistConfig getPrePersistConfig() {
538: return (PrePersistConfig) _config;
539: }
540:
541: public PostPersistConfig getPostPersistConfig() {
542: return (PostPersistConfig) _config;
543: }
544:
545: public PreUpdateConfig getPreUpdateConfig() {
546: return (PreUpdateConfig) _config;
547: }
548:
549: public PostUpdateConfig getPostUpdateConfig() {
550: return (PostUpdateConfig) _config;
551: }
552:
553: public PreRemoveConfig getPreRemoveConfig() {
554: return (PreRemoveConfig) _config;
555: }
556:
557: public PostRemoveConfig getPostRemoveConfig() {
558: return (PostRemoveConfig) _config;
559: }
560:
561: public InheritanceConfig getInheritanceConfig() {
562: return (InheritanceConfig) _config;
563: }
564:
565: public NamedQueryConfig getNamedQueryConfig() {
566: return (NamedQueryConfig) _config;
567: }
568:
569: public NamedNativeQueryConfig getNamedNativeQueryConfig() {
570: return (NamedNativeQueryConfig) _config;
571: }
572:
573: public SqlResultSetMappingConfig getSqlResultSetMappingConfig() {
574: return (SqlResultSetMappingConfig) _config;
575: }
576:
577: public PrimaryKeyJoinColumnConfig getPrimaryKeyJoinColumnConfig() {
578: return (PrimaryKeyJoinColumnConfig) _config;
579: }
580:
581: public DiscriminatorColumnConfig getDiscriminatorColumnConfig() {
582: return (DiscriminatorColumnConfig) _config;
583: }
584:
585: public IdConfig getIdConfig() {
586: return (IdConfig) _config;
587: }
588:
589: public EmbeddedIdConfig getEmbeddedIdConfig() {
590: return (EmbeddedIdConfig) _config;
591: }
592:
593: public ColumnConfig getColumnConfig() {
594: return (ColumnConfig) _config;
595: }
596:
597: public GeneratedValueConfig getGeneratedValueConfig() {
598: return (GeneratedValueConfig) _config;
599: }
600:
601: public BasicConfig getBasicConfig() {
602: return (BasicConfig) _config;
603: }
604:
605: public VersionConfig getVersionConfig() {
606: return (VersionConfig) _config;
607: }
608:
609: public ManyToOneConfig getManyToOneConfig() {
610: return (ManyToOneConfig) _config;
611: }
612:
613: public OneToOneConfig getOneToOneConfig() {
614: return (OneToOneConfig) _config;
615: }
616:
617: public ManyToManyConfig getManyToManyConfig() {
618: return (ManyToManyConfig) _config;
619: }
620:
621: public OneToManyConfig getOneToManyConfig() {
622: return (OneToManyConfig) _config;
623: }
624:
625: public MapKeyConfig getMapKeyConfig() {
626: return (MapKeyConfig) _config;
627: }
628:
629: public JoinTableConfig getJoinTableConfig() {
630: return (JoinTableConfig) _config;
631: }
632:
633: public JoinColumnConfig getJoinColumnConfig() {
634: return (JoinColumnConfig) _config;
635: }
636:
637: public AttributeOverrideConfig getAttributeOverrideConfig() {
638: return (AttributeOverrideConfig) _config;
639: }
640:
641: // public AttributeOverridesConfig getAttributeOverridesConfig() {
642: // return (AttributeOverridesConfig) _config;
643: // }
644:
645: public AssociationOverrideConfig getAssociationOverrideConfig() {
646: return (AssociationOverrideConfig) _config;
647: }
648:
649: // public AssociationOverridesConfig getAssociationOverridesConfig() {
650: // return (AssociationOverridesConfig) _config;
651: // }
652: }
653:
654: static {
655: // annotations allowed with a @Basic annotation
656: _basicAnnotations.add("javax.persistence.Basic");
657: _basicAnnotations.add("javax.persistence.Column");
658: _basicAnnotations.add("javax.persistence.Enumerated");
659: _basicAnnotations.add("javax.persistence.Lob");
660: _basicAnnotations.add("javax.persistence.Temporal");
661:
662: // non-serializable types allowed with a @Basic annotation
663: _basicTypes.add("boolean");
664: _basicTypes.add("byte");
665: _basicTypes.add("char");
666: _basicTypes.add("short");
667: _basicTypes.add("int");
668: _basicTypes.add("long");
669: _basicTypes.add("float");
670: _basicTypes.add("double");
671: _basicTypes.add("[byte");
672: _basicTypes.add("[char");
673: _basicTypes.add("[java.lang.Byte");
674: _basicTypes.add("[java.lang.Character");
675:
676: // annotations allowed with an @Id annotation
677: _idAnnotations.add("javax.persistence.Column");
678: _idAnnotations.add("javax.persistence.GeneratedValue");
679: _idAnnotations.add("javax.persistence.Id");
680: _idAnnotations.add("javax.persistence.SequenceGenerator");
681: _idAnnotations.add("javax.persistence.TableGenerator");
682: _idAnnotations.add("javax.persistence.Temporal");
683:
684: // allowed with a @Id annotation
685: _idTypes.add("boolean");
686: _idTypes.add("byte");
687: _idTypes.add("char");
688: _idTypes.add("short");
689: _idTypes.add("int");
690: _idTypes.add("long");
691: _idTypes.add("float");
692: _idTypes.add("double");
693: _idTypes.add("java.lang.Boolean");
694: _idTypes.add("java.lang.Byte");
695: _idTypes.add("java.lang.Character");
696: _idTypes.add("java.lang.Short");
697: _idTypes.add("java.lang.Integer");
698: _idTypes.add("java.lang.Long");
699: _idTypes.add("java.lang.Float");
700: _idTypes.add("java.lang.Double");
701: _idTypes.add("java.lang.String");
702: _idTypes.add("java.util.Date");
703: _idTypes.add("java.sql.Date");
704:
705: // annotations allowed with a @ManyToOne annotation
706: _manyToOneAnnotations.add("javax.persistence.ManyToOne");
707: _manyToOneAnnotations.add("javax.persistence.JoinColumn");
708: _manyToOneAnnotations.add("javax.persistence.JoinColumns");
709:
710: // annotations allowed with a @OneToMany annotation
711: _oneToManyAnnotations.add("javax.persistence.OneToMany");
712: _oneToManyAnnotations.add("javax.persistence.JoinTable");
713: _oneToManyAnnotations.add("javax.persistence.MapKey");
714: _oneToManyAnnotations.add("javax.persistence.OrderBy");
715:
716: // types allowed with a @OneToMany annotation
717: _oneToManyTypes.add("java.util.Collection");
718: _oneToManyTypes.add("java.util.List");
719: _oneToManyTypes.add("java.util.Set");
720: _oneToManyTypes.add("java.util.Map");
721:
722: // annotations allowed with a @ManyToMany annotation
723: _manyToManyAnnotations.add("javax.persistence.ManyToMany");
724: _manyToManyAnnotations.add("javax.persistence.JoinTable");
725: _manyToManyAnnotations.add("javax.persistence.MapKey");
726: _manyToManyAnnotations.add("javax.persistence.OrderBy");
727:
728: // types allowed with a @ManyToMany annotation
729: _manyToManyTypes.add("java.util.Collection");
730: _manyToManyTypes.add("java.util.List");
731: _manyToManyTypes.add("java.util.Set");
732: _manyToManyTypes.add("java.util.Map");
733:
734: // annotations allowed with a @OneToOne annotation
735: _oneToOneAnnotations.add("javax.persistence.OneToOne");
736: _oneToOneAnnotations.add("javax.persistence.JoinColumn");
737: _oneToOneAnnotations.add("javax.persistence.JoinColumns");
738:
739: // annotations allowed with a @Embedded annotation
740: _embeddedAnnotations.add("javax.persistence.Embedded");
741: _embeddedAnnotations.add("javax.persistence.AttributeOverride");
742: _embeddedAnnotations
743: .add("javax.persistence.AttributeOverrides");
744: _embeddedAnnotations.add("javax.persistence.Column");
745:
746: // annotations allowed with a @EmbeddedId annotation
747: _embeddedIdAnnotations.add("javax.persistence.EmbeddedId");
748: _embeddedIdAnnotations
749: .add("javax.persistence.AttributeOverride");
750: _embeddedIdAnnotations
751: .add("javax.persistence.AttributeOverrides");
752:
753: // annotations allowed for a property
754: _propertyAnnotations.add("javax.persistence.Basic");
755: _propertyAnnotations.add("javax.persistence.Column");
756: _propertyAnnotations.add("javax.persistence.Id");
757: _propertyAnnotations.add("javax.persistence.Transient");
758: _propertyAnnotations.add("javax.persistence.OneToOne");
759: _propertyAnnotations.add("javax.persistence.ManyToOne");
760: _propertyAnnotations.add("javax.persistence.OneToMany");
761: _propertyAnnotations.add("javax.persistence.ManyToMany");
762: _propertyAnnotations.add("javax.persistence.JoinColumn");
763: _propertyAnnotations.add("javax.persistence.Embedded");
764: _propertyAnnotations.add("javax.persistence.EmbeddedId");
765: _propertyAnnotations.add("javax.persistence.Version");
766:
767: // annotations allowed with a @Version annotation
768: _versionAnnotations.add("javax.persistence.Version");
769: _versionAnnotations.add("javax.persistence.Column");
770: _versionAnnotations.add("javax.persistence.Temporal");
771:
772: // types allowed with a @Version annotation
773: _versionTypes.add("short");
774: _versionTypes.add("int");
775: _versionTypes.add("long");
776: _versionTypes.add("java.lang.Short");
777: _versionTypes.add("java.lang.Integer");
778: _versionTypes.add("java.lang.Long");
779: _versionTypes.add("java.sql.Timestamp");
780: }
781: }
|