001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2012 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.client.tide.data.impl;
022
023 import java.beans.Introspector;
024 import java.lang.reflect.Method;
025 import java.util.Collections;
026 import java.util.LinkedHashMap;
027 import java.util.List;
028 import java.util.Map;
029 import java.util.Set;
030
031 import javax.validation.ConstraintViolation;
032
033 import org.granite.client.persistence.LazyableCollection;
034 import org.granite.client.tide.collections.ManagedPersistentCollection;
035 import org.granite.client.tide.collections.ManagedPersistentMap;
036 import org.granite.client.tide.data.Identifiable;
037 import org.granite.client.tide.data.Transient;
038 import org.granite.client.tide.data.spi.EntityDescriptor;
039
040 /**
041 * @author William DRAI
042 */
043 public class JavaBeanDataManager extends AbstractDataManager {
044
045 @Override
046 public void setTrackingHandler(TrackingHandler trackingHandler) {
047 }
048
049 @Override
050 public Object getProperty(Object object, String propertyName) {
051 try {
052 Method m = object.getClass().getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
053 return m.invoke(object);
054 }
055 catch (NoSuchMethodException e) {
056 try {
057 Method m = object.getClass().getMethod("is" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
058 return m.invoke(object);
059 }
060 catch (Exception f) {
061 throw new RuntimeException("Could not get property " + propertyName + " on object " + object, f);
062 }
063 }
064 catch (Exception e) {
065 throw new RuntimeException("Could not get property " + propertyName + " on object " + object, e);
066 }
067 }
068
069 @Override
070 public void setProperty(Object object, String propertyName, Object oldValue, Object newValue) {
071 try {
072 Method[] methods = object.getClass().getMethods();
073 String setter = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
074 for (Method m : methods) {
075 if (m.getName().equals(setter) && m.getParameterTypes().length == 1 && m.getParameterTypes()[0].isInstance(newValue)) {
076 m.invoke(object, newValue);
077 break;
078 }
079 }
080 }
081 catch (Exception e) {
082 throw new RuntimeException("Could not get property " + propertyName + " on object " + object, e);
083 }
084 }
085
086 @Override
087 public void setInternalProperty(Object object, String propertyName, Object value) {
088 setProperty(object, propertyName, null, value);
089 }
090
091 @SuppressWarnings("unchecked")
092 @Override
093 public Map<String, Object> getPropertyValues(Object object, boolean includeReadOnly, boolean includeTransient) {
094 return getPropertyValues(object, Collections.EMPTY_LIST, includeReadOnly, includeTransient);
095 }
096
097 @Override
098 public Map<String, Object> getPropertyValues(Object object, List<String> excludedProperties, boolean includeReadOnly, boolean includeTransient) {
099 EntityDescriptor desc = getEntityDescriptor(object);
100
101 Map<String, Object> values = new LinkedHashMap<String, Object>();
102 for (Method m : object.getClass().getMethods()) {
103 if (!m.getName().startsWith("get") && !m.getName().startsWith("is"))
104 continue;
105 if (m.getDeclaringClass().equals(Object.class))
106 continue;
107
108 if (!includeTransient && m.isAnnotationPresent(Transient.class))
109 continue;
110
111 String pname = Introspector.decapitalize(m.getName().substring(m.getName().startsWith("get") ? 3 : 2));
112
113 if (!includeReadOnly) {
114 try {
115 object.getClass().getMethod("set" + pname.substring(0, 1).toUpperCase() + pname.substring(1), m.getReturnType());
116 }
117 catch (NoSuchMethodException e) {
118 continue;
119 }
120 }
121
122 if (desc.getDirtyPropertyName() != null && desc.getDirtyPropertyName().equals(pname))
123 continue;
124
125 try {
126 if (excludedProperties.contains(pname))
127 continue;
128
129 Object value = m.invoke(object);
130
131 values.put(pname, value);
132 }
133 catch (Exception e) {
134 throw new RuntimeException("Could not get property " + m + " on object " + object, e);
135 }
136 }
137 return values;
138 }
139
140 @Override
141 public ManagedPersistentCollection<Object> newPersistentCollection(Identifiable parent, String propertyName, LazyableCollection nextList) {
142 return null;
143 }
144
145 @Override
146 public ManagedPersistentMap<Object, Object> newPersistentMap(Identifiable parent, String propertyName, LazyableCollection nextMap) {
147 return null;
148 }
149
150 @Override
151 public void startTracking(Object previous, Object parent) {
152 }
153
154 @Override
155 public void stopTracking(Object previous, Object parent) {
156 }
157
158 @Override
159 public void clear() {
160 }
161
162 public boolean isDirty() {
163 return false;
164 }
165
166 @Override
167 public void notifyDirtyChange(boolean oldDirty, boolean dirty) {
168 }
169
170 @Override
171 public void notifyEntityDirtyChange(Object entity, boolean oldDirtyEntity, boolean newDirtyEntity) {
172 }
173
174 @Override
175 public void notifyConstraintViolations(Object entity, Set<ConstraintViolation<?>> violations) {
176 }
177
178 }