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 */ 022package org.granite.toplink; 023 024import java.lang.reflect.Field; 025import java.lang.reflect.Modifier; 026import java.util.ArrayList; 027import java.util.List; 028 029import javax.persistence.Entity; 030 031import org.granite.logging.Logger; 032import org.granite.messaging.amf.io.util.DefaultClassGetter; 033import org.granite.util.TypeUtil; 034 035import oracle.toplink.essentials.indirection.IndirectContainer; 036import oracle.toplink.essentials.indirection.ValueHolderInterface; 037 038/** 039 * @author William DRAI 040 */ 041public 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}