@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);
   }
 }
  @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);
    }
  }
  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);
      }
    }
  }