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