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.toplink;
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.util.TypeUtil;
034
035 import oracle.toplink.essentials.indirection.IndirectContainer;
036 import oracle.toplink.essentials.indirection.ValueHolderInterface;
037
038 /**
039 * @author William DRAI
040 */
041 public class TopLinkClassGetter extends DefaultClassGetter {
042
043 public final static Logger log = Logger.getLogger(TopLinkClassGetter.class);
044
045 @Override
046 public Class<?> getClass(Object o) {
047
048 if (o instanceof ValueHolderInterface) {
049 ValueHolderInterface holder = (ValueHolderInterface)o;
050
051 String className = (
052 holder.isInstantiated() ?
053 holder.getValue().getClass().getName() :
054 Object.class.getName()
055 );
056
057 if (className != null && className.length() > 0) {
058 try {
059 return TypeUtil.forName(className);
060 } catch (Exception e) {
061 log.warn(e, "Could not get class with initializer: %s for: %s", className, className);
062 }
063 }
064 // fallback...
065 return Object.class;
066 }
067 else if (o instanceof TopLinkProxy) {
068 return ((TopLinkProxy)o).getProxiedClass();
069 }
070
071 return super.getClass(o);
072 }
073
074 @Override
075 public boolean isEntity(Object o) {
076 return o.getClass().isAnnotationPresent(Entity.class);
077 }
078
079 @Override
080 public boolean isInitialized(Object owner, String propertyName, Object propertyValue) {
081 if (propertyValue instanceof ValueHolderInterface)
082 return ((ValueHolderInterface)propertyValue).isInstantiated();
083 else if (propertyValue instanceof IndirectContainer)
084 return ((IndirectContainer)propertyValue).isInstantiated();
085
086 return true;
087 }
088
089 @Override
090 public void initialize(Object owner, String propertyName, Object propertyValue) {
091 if (propertyValue instanceof ValueHolderInterface)
092 ((ValueHolderInterface)propertyValue).getValue().toString();
093 else if (propertyValue instanceof IndirectContainer)
094 ((IndirectContainer)propertyValue).getValueHolder().getValue().toString();
095 }
096
097 @Override
098 public List<Object[]> getFieldValues(Object obj, Object dest) {
099 List<Object[]> fieldValues = new ArrayList<Object[]>();
100
101 List<String> topLinkVhs = new ArrayList<String>();
102
103 // Merges field values
104 try {
105 Class<?> clazz = obj.getClass();
106 while (clazz != null) {
107 Field[] fields = clazz.getDeclaredFields();
108 for (Field field : fields) {
109 if ((field.getModifiers() & Modifier.STATIC) != 0
110 || (field.getModifiers() & Modifier.FINAL) != 0
111 || (field.getModifiers() & Modifier.VOLATILE) != 0
112 || (field.getModifiers() & Modifier.NATIVE) != 0
113 || (field.getModifiers() & Modifier.TRANSIENT) != 0)
114 continue;
115
116 if (ValueHolderInterface.class.isAssignableFrom(field.getType())) {
117 field.setAccessible(true);
118 ValueHolderInterface vh = (ValueHolderInterface)field.get(obj);
119 if (!vh.isInstantiated()) {
120 topLinkVhs.add(field.getName());
121 field.set(dest, vh);
122 }
123 }
124 else if (!topLinkVhs.contains("_toplink_" + field.getName() + "_vh")) {
125 field.setAccessible(true);
126 Object o = field.get(obj);
127 if (dest != null) {
128 Object d = field.get(dest);
129 fieldValues.add(new Object[] { field, o, d });
130 }
131 else
132 fieldValues.add(new Object[] { field, o });
133 }
134 }
135 clazz = clazz.getSuperclass();
136 }
137 }
138 catch (Exception e) {
139 throw new RuntimeException("Could not merge entity ", e);
140 }
141
142 return fieldValues;
143 }
144 }