/**
* Copyright (C) 2010 Michael Mosmann <michael@mosmann.de>
*
* 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 de.flapdoodle.mongoom.mapping.entities;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Set;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import de.flapdoodle.mongoom.exceptions.MappingException;
import de.flapdoodle.mongoom.mapping.ITransformation;
import de.flapdoodle.mongoom.mapping.converter.reflection.ClassInformation;
import de.flapdoodle.mongoom.mapping.naming.PropertyName;
import de.flapdoodle.mongoom.mapping.properties.IPropertyField;
import de.flapdoodle.mongoom.mapping.properties.Property;
import de.flapdoodle.mongoom.mapping.properties.PropertyReference;
public abstract class AbstractBeanTransformation<Bean, C extends IBeanContext<Bean>> implements
ITransformation<Bean, DBObject> {
protected final C _entityContext;
protected AbstractBeanTransformation(C context) {
_entityContext = context;
}
protected C getContext() {
return _entityContext;
}
@Override
public DBObject asObject(Bean value) {
if (value == null)
return null;
BasicDBObject ret = new BasicDBObject();
IPropertyTransformations propertyTransformations = _entityContext.getPropertyTransformations();
for (PropertyName p : propertyTransformations.propertyNames()) {
ITransformation transformation = propertyTransformations.get(p);
IPropertyField<?> prop = (IPropertyField<?>) propertyTransformations.getProperty(p);
Field field = prop.getField();
Object fieldValue = getFieldValue(field, value);
Object dbValue = transformation.asObject(fieldValue);
if (dbValue != null)
ret.put(p.getMapped(), dbValue);
}
return ret;
}
protected Object getFieldValue(Field field, Bean value) {
try {
field.setAccessible(true);
return field.get(value);
} catch (IllegalArgumentException e) {
throw new MappingException(_entityContext.getViewClass(), e);
} catch (IllegalAccessException e) {
throw new MappingException(_entityContext.getViewClass(), e);
}
}
@Override
public Bean asEntity(DBObject object) {
if (object == null)
return null;
Bean ret = newInstance();
IPropertyTransformations propertyTransformations = _entityContext.getPropertyTransformations();
for (PropertyName p : propertyTransformations.propertyNames()) {
ITransformation transformation = propertyTransformations.get(p);
IPropertyField<?> prop = (IPropertyField<?>) propertyTransformations.getProperty(p);
Field field = prop.getField();
Object fieldValue = transformation.asEntity(getValue(object, p));
if (fieldValue != null)
setFieldValue(ret, field, fieldValue);
}
return ret;
}
private Object getValue(DBObject object, PropertyName p) {
return getValue(object, Property.split(p.getMapped()));
}
private Object getValue(DBObject object, List<String> path) {
if (path.size() > 1) {
Object property = object.get(path.get(0));
if (property instanceof DBObject)
return getValue((DBObject) property, path.subList(1, path.size()));
else
// property is null?
return null;
// throw new MappingException(_entityContext.getViewClass(), "Property "+path+" not found "+object);
}
return object.get(path.get(0));
}
protected void setFieldValue(Bean bean, Field field, Object fieldValue) {
try {
field.setAccessible(true);
field.set(bean, fieldValue);
} catch (IllegalArgumentException e) {
throw new MappingException(_entityContext.getViewClass(), e);
} catch (IllegalAccessException e) {
throw new MappingException(_entityContext.getViewClass(), e);
}
}
private Bean newInstance() {
Class<Bean> viewClass = _entityContext.getViewClass();
return ClassInformation.newInstance(viewClass);
}
@Override
public <Source> PropertyName<Source> propertyName(PropertyReference<Source> property) {
// TODO Auto-generated method stub
return _entityContext.getPropertyTransformations().get(property);
}
@Override
public PropertyName<?> propertyName(String property) {
return _entityContext.getPropertyTransformations().get(property);
}
@Override
public <Source> ITransformation<Source, ?> propertyTransformation(PropertyName<Source> property) {
return _entityContext.getPropertyTransformations().get(property);
}
// @Override
// public <Source> ITransformation<Source, ?> propertyTransformation(TypedPropertyName<Source> property) {
// return (ITransformation<Source, ?>) _entityContext.getPropertyTransformations().get(property);
// }
//
// @Override
// public ITransformation<?, ?> propertyTransformation(String property) {
// return (ITransformation<?, ?>) _entityContext.getPropertyTransformations().get(property);
// }
@Override
public Set<PropertyName<?>> properties() {
return _entityContext.getPropertyTransformations().propertyNames();
}
// @Override
// public Set<TypedPropertyName<?>> properties() {
// return _entityContext.getPropertyTransformations().typedPropertyNames();
// }
}