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