2 * Copyright 2005-2010 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.persistence;
18 import java.io.Serializable;
19 import java.util.List;
21 import java.util.concurrent.ConcurrentHashMap;
23 import javax.persistence.Id;
24 import javax.persistence.Version;
26 import org.wamblee.reflection.Accessor;
27 import org.wamblee.reflection.AnnotationUtils;
30 * Factory which creates a {@link Persistent} object for a given JPA entity for
31 * interfacing with the primary key and version of the entity.
33 * This utility only treats primary keys and fields that are annotated with @Id
34 * and @Version. In case ORM files are used for the definition of primary key
35 * and or version, then those fields are ignored.
37 * @author Erik Brakkee
40 public class PersistentFactory {
43 * Cache of a mapping of class names to entity accessors.
45 private static Map<String, EntityAccessor> CACHE = new ConcurrentHashMap<String, EntityAccessor>();
47 static class EntityAccessor {
49 private Accessor version;
51 public EntityAccessor(Accessor<?> aPk, Accessor<?> aVersion) {
56 public Accessor getPk() {
60 public Accessor getVersion() {
65 public static class EntityObjectAccessor implements Persistent {
66 private EntityAccessor accessor;
67 private Object entity;
69 public EntityObjectAccessor(Object aEntity, EntityAccessor aAccessor) {
74 public EntityAccessor getAccessor() {
79 public Serializable getPrimaryKey() {
80 if (accessor == null || accessor.getPk() == null) {
83 return (Serializable) accessor.getPk().get(entity);
87 public void setPrimaryKey(Serializable aKey) {
88 if (accessor == null || accessor.getPk() == null) {
91 accessor.getPk().set(entity, aKey);
95 public Number getPersistedVersion() {
96 if (accessor == null || accessor.getVersion() == null) {
99 return (Number) accessor.getVersion().get(entity);
103 public void setPersistedVersion(Number aVersion) {
104 if (accessor == null || accessor.getVersion() == null) {
107 accessor.getVersion().set(entity, aVersion);
112 * Create the entity accessor for a given class or returns a cached instance
113 * if one already exists.
117 * @return Entity accessor for the given class or null of the given object
120 public static EntityAccessor createEntityAccessor(Class aClass) {
121 EntityAccessor accessor = CACHE.get(aClass.getName());
122 if (accessor == null) {
123 accessor = analyse(aClass);
124 if (accessor != null) {
125 CACHE.put(aClass.getName(), accessor);
131 private static EntityAccessor analyse(Class aClass) {
132 List<Accessor> pkAccessors = AnnotationUtils.analyse(aClass, Id.class);
133 List<Accessor> versionAccessors = AnnotationUtils.analyse(aClass,
135 Accessor<Serializable> pk = null;
136 if (pkAccessors.size() > 0) {
137 pk = pkAccessors.get(0);
139 Accessor<Integer> version = null;
140 if (versionAccessors.size() > 0) {
141 version = versionAccessors.get(0);
143 if (pk != null || version != null) {
144 return new EntityAccessor(pk, version);
150 * Creates the {@link Persistent} wrapper for interfacing with primary key
151 * and version of the entity.
155 * @return Persistent object or null if this is not an entity.
157 public static Persistent create(Object aEntity) {
158 EntityAccessor accessor = createEntityAccessor(aEntity.getClass());
159 if (accessor == null) {
162 return new EntityObjectAccessor(aEntity, accessor);