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