/*
* Copyright (C) 2011 Benoit GUEROUT <bguerout at gmail dot com> and Yves AMSELLEM <amsellem dot yves at gmail dot com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jongo;
import org.bson.types.ObjectId;
import org.jongo.marshall.jackson.JacksonObjectIdUpdater;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* Use {@link JacksonObjectIdUpdater} instead
*/
@Deprecated
public class ReflectiveObjectIdUpdater implements ObjectIdUpdater {
private final Map<Class<?>, Field> fieldCache = new HashMap<Class<?>, Field>();
private final IdFieldSelector idFieldSelector;
public ReflectiveObjectIdUpdater(IdFieldSelector idFieldSelector) {
this.idFieldSelector = idFieldSelector;
}
public boolean mustGenerateObjectId(Object pojo) {
Field idField = selectIdField(pojo.getClass());
return idField != null && isAnEmptyObjectId(pojo, idField);
}
public Object getId(Object pojo) {
Field idField = selectIdField(pojo.getClass());
if (idField != null) {
try {
idField.setAccessible(true);
Object id = idField.get(pojo);
if (id instanceof String && idFieldSelector.isObjectId(idField)) {
return new ObjectId(id.toString());
} else {
return id;
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to obtain objectid from field" + idField.getName() + ", class: " + idField.getClass(), e);
}
}
return null;
}
public void setObjectId(Object newPojo, ObjectId id) {
Field idField = selectIdField(newPojo.getClass());
if (idField == null) {
return;
} else if (!mustGenerateObjectId(newPojo)) {
throw new IllegalArgumentException("Unable to set objectid on class: " + newPojo.getClass());
}
updateField(newPojo, id, idField);
}
private void updateField(Object target, ObjectId id, Field field) {
try {
if (field.getType().equals(ObjectId.class)) {
field.setAccessible(true);
field.set(target, id);
} else if (field.getType().equals(String.class) && idFieldSelector.isObjectId(field)) {
field.setAccessible(true);
field.set(target, id.toString());
}
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Unable to set objectid on class: " + target.getClass(), e);
}
}
private Field selectIdField(Class<?> clazz) {
if (fieldCache.containsKey(clazz)) {
return fieldCache.get(clazz);
}
Class<?> c = clazz;
while (!Object.class.equals(c)) {
for (Field f : c.getDeclaredFields()) {
if (idFieldSelector.isId(f)) {
fieldCache.put(clazz, f);
return f;
}
}
c = c.getSuperclass();
}
return null;
}
private boolean isAnEmptyObjectId(Object target, Field field) {
if (idFieldSelector.isObjectId(field)) {
try {
field.setAccessible(true);
return field.get(target) == null;
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to obtain value from field" + field.getName() + ", class: " + target.getClass(), e);
}
}
return false;
}
public interface IdFieldSelector {
boolean isId(Field f);
boolean isObjectId(Field f);
}
}