public void toDBObject(
      final Object containingObject,
      final MappedField mf,
      final DBObject dbObj,
      MapperOptions opts) {
    Object fieldValue = mf.getFieldValue(containingObject);
    TypeConverter enc = getEncoder(fieldValue, mf);

    Object encoded = enc.encode(fieldValue, mf);
    if (encoded != null || opts.storeNulls) {
      dbObj.put(mf.getNameToStore(), encoded);
    }
  }
  public <T> UpdateResults<T> update(T ent, UpdateOperations<T> ops) {
    MappedClass mc = mapr.getMappedClass(ent);
    Query<T> q = (Query<T>) createQuery(mc.getClazz());
    q.disableValidation().filter(Mapper.ID_KEY, getId(ent));

    if (mc.getFieldsAnnotatedWith(Version.class).size() > 0) {
      MappedField versionMF = mc.getFieldsAnnotatedWith(Version.class).get(0);
      Long oldVer = (Long) versionMF.getFieldValue(ent);
      q.filter(versionMF.getNameToStore(), oldVer);
      ops.set(versionMF.getNameToStore(), VersionHelper.nextValue(oldVer));
    }

    return update(q, ops);
  }
 @Override
 public String resolve(String fieldName, Class<?> entityClass) {
   Iterable<String> fieldNames = splitter.split(fieldName);
   List<String> resolved = Lists.newArrayList();
   Class<?> lastClass = entityClass;
   for (String name : fieldNames) {
     MappedField mappedField = mapper.getMappedClass(lastClass).getMappedFieldByJavaField(name);
     if (mappedField != null) {
       lastClass = mappedField.getConcreteType();
       resolved.add(mappedField.getNameToStore());
     } else {
       resolved.add(name);
     }
   }
   return joiner.join(resolved);
 }
 @Override
 public Object encode(Object value, MappedField f) {
   if (value == null) return null;
   try {
     boolean useCompression = !f.getAnnotation(Serialized.class).disableCompression();
     return Serializer.serialize(value, useCompression);
   } catch (IOException ex) {
     throw new RuntimeException(ex);
   }
 }
 public void fromDBObject(final DBObject dbObj, final MappedField mf, final Object targetEntity) {
   Object object = mf.getDbObjectValue(dbObj);
   if (object == null) {
     processMissingField(mf);
   } else {
     TypeConverter enc = getEncoder(mf);
     Object decodedValue = enc.decode(mf.getType(), object, mf);
     try {
       mf.setFieldValue(targetEntity, decodedValue);
     } catch (IllegalArgumentException e) {
       throw new MappingException(
           "Error setting value from converter ("
               + enc.getClass().getSimpleName()
               + ") for "
               + mf.getFullName()
               + " to "
               + decodedValue);
     }
   }
 }
  protected <T> WriteResult tryVersionedUpdate(
      DBCollection dbColl, T entity, DBObject dbObj, WriteConcern wc, DB db, MappedClass mc) {
    WriteResult wr = null;
    if (mc.getFieldsAnnotatedWith(Version.class).isEmpty()) return wr;

    MappedField mfVersion = mc.getFieldsAnnotatedWith(Version.class).get(0);
    String versionKeyName = mfVersion.getNameToStore();
    Long oldVersion = (Long) mfVersion.getFieldValue(entity);
    long newVersion = VersionHelper.nextValue(oldVersion);
    dbObj.put(versionKeyName, newVersion);
    if (oldVersion != null && oldVersion > 0) {
      Object idValue = dbObj.get(Mapper.ID_KEY);

      UpdateResults<T> res =
          update(
              find((Class<T>) entity.getClass(), Mapper.ID_KEY, idValue)
                  .filter(versionKeyName, oldVersion),
              dbObj,
              false,
              false,
              wc);

      wr = res.getWriteResult();

      if (res.getUpdatedCount() != 1)
        throw new ConcurrentModificationException(
            "Entity of class "
                + entity.getClass().getName()
                + " (id='"
                + idValue
                + "',version='"
                + oldVersion
                + "') was concurrently updated.");
    } else if (wc == null) wr = dbColl.save(dbObj);
    else wr = dbColl.save(dbObj, wc);

    // update the version.
    mfVersion.setFieldValue(entity, newVersion);
    return wr;
  }
  @Override
  public Object decode(Class targetClass, Object fromDBObject, MappedField f)
      throws MappingException {
    if (fromDBObject == null) return null;

    if (!((fromDBObject instanceof Binary) || (fromDBObject instanceof byte[]))) {
      throw new MappingException(
          "The stored data is not a DBBinary or byte[] instance for "
              + f.getFullName()
              + " ; it is a "
              + fromDBObject.getClass().getName());
    }

    try {
      boolean useCompression = !f.getAnnotation(Serialized.class).disableCompression();
      return Serializer.deserialize(fromDBObject, useCompression);
    } catch (IOException e) {
      throw new MappingException("While deserializing to " + f.getFullName(), e);
    } catch (ClassNotFoundException e) {
      throw new MappingException("While deserializing to " + f.getFullName(), e);
    }
  }
  private TypeConverter getEncoder(Object val, MappedField mf) {

    List<TypeConverter> tcs = null;

    if (val != null) tcs = tcMap.get(val.getClass());

    if (tcs == null || (tcs.size() > 0 && tcs.get(0) instanceof PassthroughConverter))
      tcs = tcMap.get(mf.getType());

    if (tcs != null) {
      if (tcs.size() > 1)
        log.warning(
            "Duplicate converter for " + mf.getType() + ", returning first one from " + tcs);
      return tcs.get(0);
    }

    for (TypeConverter tc : untypedTypeEncoders)
      if (tc.canHandle(mf) || (val != null && tc.isSupported(val.getClass(), mf))) return tc;

    throw new ConverterNotFoundException(
        "Cannot find encoder for " + mf.getType() + " as need for " + mf.getFullName());
  }
  protected void ensureIndexes(
      MappedClass mc,
      boolean background,
      ArrayList<MappedClass> parentMCs,
      ArrayList<MappedField> parentMFs) {
    if (parentMCs.contains(mc)) return;

    // skip embedded types
    if (mc.getEmbeddedAnnotation() != null && (parentMCs == null || parentMCs.isEmpty())) return;

    // Ensure indexes from class annotation
    Indexes idxs = (Indexes) mc.getAnnotation(Indexes.class);
    if (idxs != null && idxs.value() != null && idxs.value().length > 0)
      for (Index index : idxs.value()) {
        BasicDBObject fields = QueryImpl.parseSortString(index.value());
        ensureIndex(
            mc.getClazz(),
            index.name(),
            fields,
            index.unique(),
            index.dropDups(),
            index.background() ? index.background() : background,
            index.sparse() ? index.sparse() : false);
      }

    // Ensure indexes from field annotations, and embedded entities
    for (MappedField mf : mc.getPersistenceFields()) {
      if (mf.hasAnnotation(Indexed.class)) {
        Indexed index = mf.getAnnotation(Indexed.class);
        StringBuilder field = new StringBuilder();
        Class<?> indexedClass = (parentMCs.isEmpty() ? mc : parentMCs.get(0)).getClazz();
        if (!parentMCs.isEmpty())
          for (MappedField pmf : parentMFs) field.append(pmf.getNameToStore()).append(".");

        field.append(mf.getNameToStore());

        ensureIndex(
            indexedClass,
            index.name(),
            new BasicDBObject(field.toString(), index.value().toIndexValue()),
            index.unique(),
            index.dropDups(),
            index.background() ? index.background() : background,
            index.sparse() ? index.sparse() : false);
      }

      if (!mf.isTypeMongoCompatible()
          && !mf.hasAnnotation(Reference.class)
          && !mf.hasAnnotation(Serialized.class)) {
        ArrayList<MappedClass> newParentClasses = (ArrayList<MappedClass>) parentMCs.clone();
        ArrayList<MappedField> newParents = (ArrayList<MappedField>) parentMFs.clone();
        newParentClasses.add(mc);
        newParents.add(mf);
        ensureIndexes(
            mapr.getMappedClass(mf.isSingleValue() ? mf.getType() : mf.getSubClass()),
            background,
            newParentClasses,
            newParents);
      }
    }
  }
 @Override
 protected boolean isSupported(Class c, MappedField optionalExtraInfo) {
   if (optionalExtraInfo != null) return (optionalExtraInfo.hasAnnotation(Serialized.class));
   else return false;
 }