001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.toplink;
022
023 import java.lang.reflect.Field;
024 import java.lang.reflect.Modifier;
025 import java.util.ArrayList;
026 import java.util.List;
027
028 import javax.persistence.Entity;
029
030 import org.granite.logging.Logger;
031 import org.granite.messaging.amf.io.util.DefaultClassGetter;
032 import org.granite.util.ClassUtil;
033
034 import oracle.toplink.essentials.indirection.IndirectContainer;
035 import oracle.toplink.essentials.indirection.ValueHolderInterface;
036
037 /**
038 * @author William DRAI
039 */
040 public class TopLinkClassGetter extends DefaultClassGetter {
041
042 public final static Logger log = Logger.getLogger(TopLinkClassGetter.class);
043
044 @Override
045 public Class<?> getClass(Object o) {
046
047 if (o instanceof ValueHolderInterface) {
048 ValueHolderInterface holder = (ValueHolderInterface)o;
049
050 String className = (
051 holder.isInstantiated() ?
052 holder.getValue().getClass().getName() :
053 Object.class.getName()
054 );
055
056 if (className != null && className.length() > 0) {
057 try {
058 return ClassUtil.forName(className);
059 } catch (Exception e) {
060 log.warn(e, "Could not get class with initializer: %s for: %s", className, className);
061 }
062 }
063 // fallback...
064 return Object.class;
065 }
066 else if (o instanceof TopLinkProxy) {
067 return ((TopLinkProxy)o).getProxiedClass();
068 }
069
070 return super.getClass(o);
071 }
072
073 @Override
074 public boolean isEntity(Object o) {
075 return o.getClass().isAnnotationPresent(Entity.class);
076 }
077
078 @Override
079 public boolean isInitialized(Object owner, String propertyName, Object propertyValue) {
080 if (propertyValue instanceof ValueHolderInterface)
081 return ((ValueHolderInterface)propertyValue).isInstantiated();
082 else if (propertyValue instanceof IndirectContainer)
083 return ((IndirectContainer)propertyValue).isInstantiated();
084
085 return true;
086 }
087
088 @Override
089 public void initialize(Object owner, String propertyName, Object propertyValue) {
090 if (propertyValue instanceof ValueHolderInterface)
091 ((ValueHolderInterface)propertyValue).getValue().toString();
092 else if (propertyValue instanceof IndirectContainer)
093 ((IndirectContainer)propertyValue).getValueHolder().getValue().toString();
094 }
095
096 @Override
097 public List<Object[]> getFieldValues(Object obj, Object dest) {
098 List<Object[]> fieldValues = new ArrayList<Object[]>();
099
100 List<String> topLinkVhs = new ArrayList<String>();
101
102 // Merges field values
103 try {
104 Class<?> clazz = obj.getClass();
105 while (clazz != null) {
106 Field[] fields = clazz.getDeclaredFields();
107 for (Field field : fields) {
108 if ((field.getModifiers() & Modifier.STATIC) != 0
109 || (field.getModifiers() & Modifier.FINAL) != 0
110 || (field.getModifiers() & Modifier.VOLATILE) != 0
111 || (field.getModifiers() & Modifier.NATIVE) != 0
112 || (field.getModifiers() & Modifier.TRANSIENT) != 0)
113 continue;
114
115 if (ValueHolderInterface.class.isAssignableFrom(field.getType())) {
116 field.setAccessible(true);
117 ValueHolderInterface vh = (ValueHolderInterface)field.get(obj);
118 if (!vh.isInstantiated()) {
119 topLinkVhs.add(field.getName());
120 field.set(dest, vh);
121 }
122 }
123 else if (!topLinkVhs.contains("_toplink_" + field.getName() + "_vh")) {
124 field.setAccessible(true);
125 Object o = field.get(obj);
126 Object d = field.get(dest);
127 fieldValues.add(new Object[] { field, o, d });
128 }
129 }
130 clazz = clazz.getSuperclass();
131 }
132 }
133 catch (Exception e) {
134 throw new RuntimeException("Could not merge entity ", e);
135 }
136
137 return fieldValues;
138 }
139 }