1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2013 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.persist.model;
9 
10 import java.io.Serializable;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Map;
14 
15 /**
16  * The metadata for a persistent class.  A persistent class may be specified
17  * with the {@link Entity} or {@link Persistent} annotation.
18  *
19  * <p>{@code ClassMetadata} objects are thread-safe.  Multiple threads may
20  * safely call the methods of a shared {@code ClassMetadata} object.</p>
21  *
22  * <p>This and other metadata classes are classes rather than interfaces to
23  * allow adding properties to the model at a future date without causing
24  * incompatibilities.  Any such property will be given a default value and
25  * its use will be optional.</p>
26  *
27  * @author Mark Hayes
28  */
29 public class ClassMetadata implements Serializable {
30 
31     private static final long serialVersionUID = -2520207423701776679L;
32 
33     private String className;
34     private int version;
35     private String proxiedClassName;
36     private boolean entityClass;
37     private PrimaryKeyMetadata primaryKey;
38     private Map<String, SecondaryKeyMetadata> secondaryKeys;
39     private List<FieldMetadata> compositeKeyFields;
40     private Collection<FieldMetadata> persistentFields;
41 
42     /**
43      * Used by an {@code EntityModel} to construct persistent class metadata.
44      * The optional {@link #getPersistentFields} property will be set to null.
45      */
ClassMetadata(String className, int version, String proxiedClassName, boolean entityClass, PrimaryKeyMetadata primaryKey, Map<String, SecondaryKeyMetadata> secondaryKeys, List<FieldMetadata> compositeKeyFields)46     public ClassMetadata(String className,
47                          int version,
48                          String proxiedClassName,
49                          boolean entityClass,
50                          PrimaryKeyMetadata primaryKey,
51                          Map<String, SecondaryKeyMetadata> secondaryKeys,
52                          List<FieldMetadata> compositeKeyFields) {
53 
54         this(className, version, proxiedClassName, entityClass, primaryKey,
55              secondaryKeys, compositeKeyFields, null /*persistentFields*/);
56     }
57 
58     /**
59      * Used by an {@code EntityModel} to construct persistent class metadata.
60      */
ClassMetadata(String className, int version, String proxiedClassName, boolean entityClass, PrimaryKeyMetadata primaryKey, Map<String, SecondaryKeyMetadata> secondaryKeys, List<FieldMetadata> compositeKeyFields, Collection<FieldMetadata> persistentFields)61     public ClassMetadata(String className,
62                          int version,
63                          String proxiedClassName,
64                          boolean entityClass,
65                          PrimaryKeyMetadata primaryKey,
66                          Map<String, SecondaryKeyMetadata> secondaryKeys,
67                          List<FieldMetadata> compositeKeyFields,
68                          Collection<FieldMetadata> persistentFields) {
69         this.className = className;
70         this.version = version;
71         this.proxiedClassName = proxiedClassName;
72         this.entityClass = entityClass;
73         this.primaryKey = primaryKey;
74         this.secondaryKeys = secondaryKeys;
75         this.compositeKeyFields = compositeKeyFields;
76         this.persistentFields = persistentFields;
77     }
78 
79     /**
80      * Returns the name of the persistent class.
81      */
getClassName()82     public String getClassName() {
83         return className;
84     }
85 
86     /**
87      * Returns the version of this persistent class.  This may be specified
88      * using the {@link Entity#version} or {@link Persistent#version}
89      * annotation.
90      */
getVersion()91     public int getVersion() {
92         return version;
93     }
94 
95     /**
96      * Returns the class name of the proxied class if this class is a {@link
97      * PersistentProxy}, or null otherwise.
98      */
getProxiedClassName()99     public String getProxiedClassName() {
100         return proxiedClassName;
101     }
102 
103     /**
104      * Returns whether this class is an entity class.
105      */
isEntityClass()106     public boolean isEntityClass() {
107         return entityClass;
108     }
109 
110     /**
111      * Returns the primary key metadata for a key declared in this class, or
112      * null if none is declared.  This may be specified using the {@link
113      * PrimaryKey} annotation.
114      */
getPrimaryKey()115     public PrimaryKeyMetadata getPrimaryKey() {
116         return primaryKey;
117     }
118 
119     /**
120      * Returns an unmodifiable map of key name (which may be different from
121      * field name) to secondary key metadata for all secondary keys declared in
122      * this class, or null if no secondary keys are declared in this class.
123      * This metadata may be specified using {@link SecondaryKey} annotations.
124      */
getSecondaryKeys()125     public Map<String, SecondaryKeyMetadata> getSecondaryKeys() {
126         return secondaryKeys;
127     }
128 
129     /**
130      * Returns an unmodifiable list of metadata for the fields making up a
131      * composite key, or null if this is a not a composite key class.  The
132      * order of the fields in the returned list determines their stored order
133      * and may be specified using the {@link KeyField} annotation.  When the
134      * composite key class does not implement {@link Comparable}, the order of
135      * the fields is the relative sort order.
136      */
getCompositeKeyFields()137     public List<FieldMetadata> getCompositeKeyFields() {
138         return compositeKeyFields;
139     }
140 
141     /**
142      * Returns an unmodifiable list of metadata for the persistent fields in
143      * this class, or null if the default rules for persistent fields should be
144      * used.  All fields returned must be declared in this class and must be
145      * non-static.
146      *
147      * <p>By default (if null is returned) the persistent fields of a class
148      * will be all declared instance fields that are non-transient (are not
149      * declared with the <code>transient</code> keyword).  The default rules
150      * may be overridden by an {@link EntityModel}.  For example, the {@link
151      * AnnotationModel} overrides the default rules when the {@link
152      * NotPersistent} or {@link NotTransient} annotation is specified.</p>
153      */
getPersistentFields()154     public Collection<FieldMetadata> getPersistentFields() {
155         return persistentFields;
156     }
157 
158     @Override
equals(Object other)159     public boolean equals(Object other) {
160         if (other instanceof ClassMetadata) {
161             ClassMetadata o = (ClassMetadata) other;
162             return version == o.version &&
163                    entityClass == o.entityClass &&
164                    nullOrEqual(className, o.className) &&
165                    nullOrEqual(proxiedClassName, o.proxiedClassName) &&
166                    nullOrEqual(primaryKey, o.primaryKey) &&
167                    nullOrEqual(secondaryKeys, o.secondaryKeys) &&
168                    nullOrEqual(compositeKeyFields, o.compositeKeyFields);
169         } else {
170             return false;
171         }
172     }
173 
174     @Override
hashCode()175     public int hashCode() {
176         return version +
177                (entityClass ? 1 : 0) +
178                hashCode(className) +
179                hashCode(proxiedClassName) +
180                hashCode(primaryKey) +
181                hashCode(secondaryKeys) +
182                hashCode(compositeKeyFields);
183     }
184 
nullOrEqual(Object o1, Object o2)185     static boolean nullOrEqual(Object o1, Object o2) {
186         if (o1 == null) {
187             return o2 == null;
188         } else {
189             return o1.equals(o2);
190         }
191     }
192 
hashCode(Object o)193     static int hashCode(Object o) {
194         if (o != null) {
195             return o.hashCode();
196         } else {
197             return 0;
198         }
199     }
200 }
201