public GuiceObjectFactory(final Registry injector, final Morphia morphia) { this.injector = requireNonNull(injector, "Injector is required."); MapperOptions options = morphia.getMapper().getOptions(); this.delegate = options.getObjectFactory(); options.setObjectFactory(this); }
@Override public void configure(final Env env, final Config conf, final Binder binder) { configure(env, conf, binder, (uri, client) -> { String db = uri.getDatabase(); Mapper mapper = new Mapper(); Morphia morphia = new Morphia(mapper); if (this.morphiaCbck != null) { this.morphiaCbck.accept(morphia, conf); } Datastore datastore = morphia.createDatastore(client, mapper, db); if (gen != null) { mapper.addInterceptor(new AutoIncID(datastore, gen)); } if (callback != null) { callback.accept(datastore); } ServiceKey serviceKey = env.serviceKey(); serviceKey.generate(Morphia.class, db, k -> binder.bind(k).toInstance(morphia)); serviceKey.generate(Datastore.class, db, k -> binder.bind(k).toInstance(datastore)); env.onStart(registry -> new GuiceObjectFactory(registry, morphia)); }); }
@Override protected DBRef asReference(Object constant) { Key<?> key = morphia.getMapper().getKey(constant); return morphia.getMapper().keyToDBRef(key); }
@Override public void toDBObject(final Object entity, final MappedField mf, final DBObject dbObject, final Map<Object, DBObject> involvedObjects, final Mapper mapper) { try { mapper.getConverters().toDBObject(entity, mf, dbObject, mapper.getOptions()); } catch (Exception e) { throw new RuntimeException(e); } } }
@Override public void fromDBObject(final Datastore datastore, final DBObject dbObject, final MappedField mf, final Object entity, final EntityCache cache, final Mapper mapper) { mapper.getConverters().fromDBObject(dbObject, mf, entity); }
if (null == o) { values.add(null); } else if (mapper.getConverters().hasSimpleValueConverter(mf) || mapper.getConverters() .hasSimpleValueConverter(o.getClass())) { values.add(mapper.getConverters().encode(o)); } else { final Object val; if (Collection.class.isAssignableFrom(o.getClass()) || Map.class.isAssignableFrom(o.getClass())) { val = mapper.toMongoObject(o, true); } else { val = mapper.toDBObject(o, involvedObjects); if (!values.isEmpty() || mapper.getOptions().isStoreEmpties()) { dbObject.put(name, values);
} else if (isAssignable(mf, value) || isEntity(mc)) { MappedClass mapped = getMappedClass(mf.getSubClass()); if (mapped != null && (Key.class.isAssignableFrom(mapped.getClazz()) || mapped.getEntityAnnotation() != null)) { mappedValue = getDBRefs(mf, (Iterable) value); } else { if (mf.hasAnnotation(Reference.class)) { mappedValue = getDBRefs(mf, (Iterable) value); } else { mappedValue = toMongoObject(value, false); Reference refAnn = mf.getAnnotation(Reference.class); Class<?> idType = null; if (!mf.getType().equals(Key.class) && isMapped(mf.getType())) { idType = getMappedClass(mf.getType()).getMappedIdField().getType(); Key<?> key = value instanceof Key ? (Key<?>) value : getKey(value); if (key != null) { mappedValue = refAnn.idOnly() ? keyToId(key) : keyToDBRef(key); mappedValue = keyToDBRef(valueIsIdType ? createKey(mf.getSubClass(), value) : value instanceof Key ? (Key<?>) value : getKey(value)); if (mappedValue == value) { throw new ValidationException("cannot map to Key<T> field: " + value); mappedValue = toMongoObject(value, false);
private void writeMap(final MappedField mf, final DBObject dbObject, final String name, final Object fieldValue, final Reference refAnn, final Mapper mapper) { final Map<Object, Object> map = (Map<Object, Object>) fieldValue; if ((map != null)) { final Map values = mapper.getOptions().getObjectFactory().createMap(mf); if (ProxyHelper.isProxy(map) && ProxyHelper.isUnFetched(map)) { final ProxiedEntityReferenceMap proxy = (ProxiedEntityReferenceMap) map; final Map<Object, Key<?>> refMap = proxy.__getReferenceMap(); for (final Map.Entry<Object, Key<?>> entry : refMap.entrySet()) { final Object key = entry.getKey(); values.put(key, refAnn.idOnly() ? mapper.keyToId(entry.getValue()) : mapper.keyToDBRef(entry.getValue())); } } else { for (final Map.Entry<Object, Object> entry : map.entrySet()) { final String strKey = mapper.getConverters().encode(entry.getKey()).toString(); values.put(strKey, refAnn.idOnly() ? mapper.keyToId(getKey(entry.getValue(), mapper)) : mapper.keyToDBRef(getKey(entry.getValue(), mapper))); } } if (!values.isEmpty() || mapper.getOptions().isStoreEmpties()) { dbObject.put(name, values); } } }
if (mapper.getConverters().hasSimpleValueConverter(mf) || mapper.getConverters().hasSimpleValueConverter(fieldValue)) { mapper.getOptions().getValueMapper().toDBObject(entity, mf, dbObject, involvedObjects, mapper); } else if (this.customMappers.containsKey(fieldValue.getClass())) { this.customMappers.get(fieldValue.getClass()).toDBObject(entity, mf, dbObject, involvedObjects, mapper); final DBObject newStub = createStub(mapper, fieldValue, mapper.getId(fieldValue)); involvedObjects.put(fieldValue, newStub); cachedStub = newStub; mapper.getOptions().getEmbeddedMapper().toDBObject(entity, mf, dbObject, involvedObjects, mapper);
@Override public void toDBObject(final Object entity, final MappedField mf, final DBObject dbObject, final Map<Object, DBObject> involvedObjects, final Mapper mapper) { final String name = mf.getNameToStore(); final Object fieldValue = mf.getFieldValue(entity); if (mf.isMap()) { writeMap(mf, dbObject, involvedObjects, name, fieldValue, mapper); } else if (mf.isMultipleValues()) { writeCollection(mf, dbObject, involvedObjects, name, fieldValue, mapper); } else { //run converters if (mapper.getConverters().hasDbObjectConverter(mf) || mapper.getConverters().hasDbObjectConverter(entity.getClass())) { mapper.getConverters().toDBObject(entity, mf, dbObject, mapper.getOptions()); return; } final DBObject dbObj = fieldValue == null ? null : mapper.toDBObject(fieldValue, involvedObjects); if (dbObj != null) { if (!shouldSaveClassName(fieldValue, dbObj, mf)) { dbObj.removeField(Mapper.CLASS_NAME_FIELDNAME); } if (!dbObj.keySet().isEmpty() || mapper.getOptions().isStoreEmpties()) { dbObject.put(name, dbObj); } } } }
if (isDBObject && !mapper.isMapped(mf.getConcreteType()) && (mapper.getConverters().hasDbObjectConverter(mf) || mapper.getConverters() .hasDbObjectConverter(mf.getType()))) { mapper.getConverters().fromDBObject(dbObject, mf, entity); } else { Object refObj; if (mapper.getConverters().hasSimpleValueConverter(mf) || mapper.getConverters() .hasSimpleValueConverter(mf.getType())) { refObj = mapper.getConverters().decode(mf.getType(), dbVal, mf); } else { DBObject value = (DBObject) dbVal; refObj = mapper.getOptions().getObjectFactory().createInstance(mapper, mf, value); refObj = mapper.fromDb(datastore, value, refObj, cache);
private void writeSingle(final DBObject dbObject, final String name, final Object fieldValue, final Reference refAnn, final Mapper mapper) { if (fieldValue == null) { if (mapper.getOptions().isStoreNulls()) { dbObject.put(name, null); } } else { Key<?> key = getKey(fieldValue, mapper); if (refAnn.idOnly()) { Object id = mapper.keyToId(key); if (id != null && mapper.isMapped(id.getClass())) { id = mapper.toMongoObject(id, true); } dbObject.put(name, id); } else { dbObject.put(name, mapper.keyToDBRef(key)); } } }
if (dbVal != null) { values = mf.isSet() ? mapper.getOptions().getObjectFactory().createSet(mf) : mapper.getOptions().getObjectFactory().createList(mf); EphemeralMappedField ephemeralMappedField = !mapper.isMapped(mf.getType()) && isMapOrCollection(mf) && (mf.getSubType() instanceof ParameterizedType) ? new EphemeralMappedField((ParameterizedType) mf.getSubType(), mf, mapper) if (mapper.getConverters().hasSimpleValueConverter(mf) || mapper.getConverters() .hasSimpleValueConverter(mf.getSubClass())) { newEntity = mapper.getConverters().decode(mf.getSubClass(), o, mf); } else { newEntity = readMapOrCollectionOrEntity(datastore, mapper, cache, mf, ephemeralMappedField, (DBObject) o); if (!values.isEmpty() || mapper.getOptions().isStoreEmpties()) { if (mf.getType().isArray()) { mf.setFieldValue(entity, ReflectionUtils.convertToArray(mf.getSubClass(), ReflectionUtils.iterToList(values)));
private void addValue(final List values, final Object o, final Mapper mapper, final boolean idOnly) { if (o == null && mapper.getOptions().isStoreNulls()) { values.add(null); return; } final Key key = o instanceof Key ? (Key) o : getKey(o, mapper); values.add(idOnly ? mapper.keyToId(key) : mapper.keyToDBRef(key)); }
@Override public void prePersist(final Object entity, final DBObject dbObj, final Mapper mapper) { MappedClass mclass = mapper.getMappedClass(entity); Field id = mclass.getIdField(); if (id != null && id.getAnnotation(GeneratedValue.class) != null) { try { id.setAccessible(true); final String collName = gen.value(mclass.getClazz()); final Query<StoredId> q = db.find(StoredId.class, "_id", collName); final UpdateOperations<StoredId> uOps = db.createUpdateOperations(StoredId.class) .inc("value"); StoredId newId = db.findAndModify(q, uOps); if (newId == null) { newId = new StoredId(collName); db.save(newId); } id.set(entity, newId.value); } catch (Exception ex) { throw new IllegalStateException("Can't generate ID on " + mclass, ex); } } }
T unwrapped = entity; final LinkedHashMap<Object, DBObject> involvedObjects = new LinkedHashMap<Object, DBObject>(); final DBObject dbObj = mapper.toDBObject(unwrapped, involvedObjects); final Key<T> key = mapper.getKey(unwrapped); unwrapped = ProxyHelper.unwrap(unwrapped); final Object id = mapper.getId(unwrapped); if (id == null) { throw new MappingException("Could not get id for " + unwrapped.getClass().getName()); final MappedClass mc = mapper.getMappedClass(unwrapped); final DBCollection dbColl = getCollection(unwrapped);
protected Mapper createMapper() { Mapper mapper = new Mapper(); mapper.getOptions().setValueMapper(createValueMapper(mapper)); mapper.getOptions().setReferenceMapper(createReferenceMapper(mapper)); mapper.getOptions().setEmbeddedMapper(createEmbeddedMapper(mapper)); mapper.getOptions().setDefaultMapper(createCustomMapper(mapper)); schema.initMapper(mapper); return mapper; }
@Override public void fromDBObject(DBObject dbObject, MappedField mf, Object entity, EntityCache cache, Mapper mapper) { BasicDBList cowlist = (BasicDBList) dbObject.get(mf.getNameToStore()); if (cowlist == null) throw new IllegalArgumentException("Improperly formatted DBObject for CopyOnWriteList"); List core = new ArrayList(); for (Object obj : cowlist) { DBObject listEntryDbObj = (DBObject) obj; // Hack until we can coax MappedField to understand what CopyOnWriteList is. Eliminate as soon as possible. // Currently mf.getSubType() is null because MappedField does not use Iterable to determine a list and thus // does not check for subtypes. Class clazz = mapper.getOptions().getObjectFactory().createInstance(mapper, mf, listEntryDbObj).getClass(); core.add(mapper.fromDBObject(clazz, listEntryDbObj, cache)); } mf.setFieldValue(entity, new CopyOnWriteList(core)); } }
private Object readMapOrCollectionOrEntity(final Datastore datastore, final Mapper mapper, final EntityCache cache, final MappedField mf, final EphemeralMappedField ephemeralMappedField, final DBObject dbObj) { if (ephemeralMappedField != null) { mapper.fromDb(datastore, dbObj, ephemeralMappedField, cache); return ephemeralMappedField.getValue(); } else { final Object newEntity = mapper.getOptions().getObjectFactory().createInstance(mapper, mf, dbObj); return mapper.fromDb(datastore, dbObj, newEntity, cache); } }
private Object getOrCreateInstance(final Class<?> clazz, final Mapper mapper) { if (mapper.getInstanceCache().containsKey(clazz)) { return mapper.getInstanceCache().get(clazz); } final Object o = mapper.getOptions().getObjectFactory().createInstance(clazz); final Object nullO = mapper.getInstanceCache().put(clazz, o); if (nullO != null) { if (LOG.isErrorEnabled()) { LOG.error("Race-condition, created duplicate class: " + clazz); } } return o; }