private Property findField(final Mapper mapper, String name) {
   final Iterator<String> iter = Splitter.on(".").split(name).iterator();
   Mapper current = mapper;
   Property property = current.getProperty(iter.next());
   while (iter.hasNext()) {
     current = Mapper.of(property.getTarget());
     property = current.getProperty(iter.next());
   }
   return property;
 }
  @GET
  @Path("fields/{model}")
  @SuppressWarnings("all")
  public Response fields(@PathParam("model") String model) {
    final Response response = new Response();
    final Map<String, Object> meta = Maps.newHashMap();
    final Class<?> modelClass = findClass(model);
    final List<String> names = Lists.newArrayList();

    if (!security.isPermitted(AccessType.READ, (Class) modelClass)) {
      response.setStatus(Response.STATUS_FAILURE);
      return response;
    }

    for (Property p : Mapper.of(modelClass).getProperties()) {
      if (!p.isTransient()) {
        names.add(p.getName());
      }
    }

    meta.put("model", model);
    meta.putAll(findFields(model, names));

    response.setData(meta);
    response.setStatus(Response.STATUS_SUCCESS);

    return response;
  }
  private Map<String, Object> findFields(final String model, final List<String> names) {
    final Map<String, Object> data = Maps.newHashMap();

    if (Strings.isNullOrEmpty(model)) {
      return data;
    }

    final Class<?> modelClass = findClass(model);
    final Mapper mapper = Mapper.of(modelClass);
    final List<Object> fields = Lists.newArrayList();

    boolean massUpdate = false;
    Object bean = null;
    try {
      bean = modelClass.newInstance();
    } catch (Exception e) {
    }

    for (String name : names) {
      Property p = findField(mapper, name);
      if (p != null) {
        Map<String, Object> map = p.toMap();
        map.put("name", name);
        if (p.getSelection() != null && !"".equals(p.getSelection().trim())) {
          map.put("selection", p.getSelection());
          map.put("selectionList", findSelection(p));
        }
        if (p.getTarget() != null) {
          map.put("perms", MetaStore.getPermissions(p.getTarget()));
        }
        if (p.isMassUpdate()) {
          massUpdate = true;
        }
        // find the default value
        if (!p.isTransient() && !p.isVirtual()) {
          Object obj = null;
          if (name.contains(".")) {
            try {
              obj = p.getEntity().newInstance();
            } catch (Exception e) {
            }
          } else {
            obj = bean;
          }
          if (obj != null) {
            Object defaultValue = p.get(obj);
            if (defaultValue != null) {
              map.put("defaultValue", defaultValue);
            }
          }
        }
        fields.add(map);
      }
    }

    Map<String, Object> perms = MetaStore.getPermissions(modelClass);

    if (massUpdate) {
      if (perms == null) {
        perms = Maps.newHashMap();
      }
      perms.put("massUpdate", massUpdate);
    }

    data.put("perms", perms);
    data.put("fields", fields);

    return data;
  }
  @Override
  public DMSFile save(DMSFile entity) {

    final DMSFile parent = entity.getParent();
    final Model related = findRelated(entity);
    final boolean isAttachment = related != null && entity.getMetaFile() != null;

    // if new attachment, save attachment reference
    if (isAttachment) {
      // remove old attachment if file is moved
      MetaAttachment attachmentOld =
          attachments
              .all()
              .filter(
                  "self.metaFile.id = ? AND self.objectId != ? AND self.objectName != ?",
                  entity.getMetaFile().getId(),
                  related.getId(),
                  related.getClass().getName())
              .fetchOne();
      if (attachmentOld != null) {
        System.err.println("OLD: " + attachmentOld);
        attachments.remove(attachmentOld);
      }

      MetaAttachment attachment =
          attachments
              .all()
              .filter(
                  "self.metaFile.id = ? AND self.objectId = ? AND self.objectName = ?",
                  entity.getMetaFile().getId(),
                  related.getId(),
                  related.getClass().getName())
              .fetchOne();
      if (attachment == null) {
        attachment = metaFiles.attach(entity.getMetaFile(), related);
        attachments.save(attachment);
      }
    }

    // if not an attachment or has parent, do nothing
    if (parent != null || related == null) {
      return super.save(entity);
    }

    // create parent folders

    Mapper mapper = Mapper.of(related.getClass());
    String homeName = null;
    try {
      homeName = mapper.getNameField().get(related).toString();
    } catch (Exception e) {
    }
    if (homeName == null) {
      homeName = Strings.padStart("" + related.getId(), 5, '0');
    }

    DMSFile dmsRoot =
        all()
            .filter(
                "(self.relatedId is null OR self.relatedId = 0) AND self.relatedModel = ? and self.isDirectory = true",
                entity.getRelatedModel())
            .fetchOne();

    final Inflector inflector = Inflector.getInstance();

    if (dmsRoot == null) {
      dmsRoot = new DMSFile();
      dmsRoot.setFileName(
          inflector.pluralize(inflector.humanize(related.getClass().getSimpleName())));
      dmsRoot.setRelatedModel(entity.getRelatedModel());
      dmsRoot.setIsDirectory(true);
      dmsRoot = super.save(dmsRoot); // should get id before it's child
    }

    DMSFile dmsHome = new DMSFile();
    dmsHome.setFileName(homeName);
    dmsHome.setRelatedId(entity.getRelatedId());
    dmsHome.setRelatedModel(entity.getRelatedModel());
    dmsHome.setParent(dmsRoot);
    dmsHome.setIsDirectory(true);
    dmsHome = super.save(dmsHome); // should get id before it's child

    entity.setParent(dmsHome);

    return super.save(entity);
  }