Package com.opengamma.web.analytics.blotter

Source Code of com.opengamma.web.analytics.blotter.JsonBeanStructureVisitor

/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.web.analytics.blotter;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.joda.beans.Bean;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaBean;
import org.joda.beans.MetaProperty;
import org.joda.beans.PropertyDefinition;
import org.joda.convert.StringConvert;
import org.json.JSONObject;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.util.ArgumentChecker;

/**
* TODO can this be deleted?
* TODO how should read-only properties be handled? I guess it depends on the use case of the data
*/
// TODO do this as HTML, easier to consume
/* package */ class JsonBeanStructureVisitor implements BeanVisitor<JSONObject> {

  private static final Map<Class<?>, String> s_types = Maps.newHashMap();
  private static final String NUMBER = "number";
  private static final String BOOLEAN = "boolean";
  private static final String STRING = "string";

  static {
    s_types.put(Double.TYPE, NUMBER);
    s_types.put(Double.class, NUMBER);
    s_types.put(Float.TYPE, NUMBER);
    s_types.put(Float.class, NUMBER);
    s_types.put(Long.TYPE, NUMBER);
    s_types.put(Long.class, NUMBER);
    s_types.put(Short.TYPE, NUMBER);
    s_types.put(Short.class, NUMBER);
    s_types.put(Integer.TYPE, NUMBER);
    s_types.put(Integer.class, NUMBER);
    s_types.put(Byte.TYPE, NUMBER);
    s_types.put(Byte.class, NUMBER);
    s_types.put(BigDecimal.class, NUMBER);
    s_types.put(Boolean.TYPE, BOOLEAN);
    s_types.put(Boolean.class, BOOLEAN);
    s_types.put(Character.TYPE, STRING);
    s_types.put(Character.class, STRING);
    s_types.put(String.class, STRING);
  }

  private final Map<String, Object> _json = Maps.newHashMap();
  private final BeanHierarchy _beanHierarchy;
  private final StringConvert _stringConvert;

  /* package */ JsonBeanStructureVisitor(Set<MetaBean> metaBeans) {
    ArgumentChecker.notNull(metaBeans, "metaBeans");
    _beanHierarchy = new BeanHierarchy(metaBeans);
    // TODO parameter for this
    _stringConvert = JodaBeanUtils.stringConverter();
  }

  @Override
  public void visitMetaBean(MetaBean metaBean) {
    // TODO configurable field name
    _json.clear();
    _json.put("type", metaBean.beanType().getSimpleName());
  }

  @Override
  public void visitBeanProperty(MetaProperty<?> property, BeanTraverser traverser) {
    Set<Class<? extends Bean>> argumentTypes = _beanHierarchy.subtypes(property.propertyType());
    if (argumentTypes.isEmpty()) {
      throw new OpenGammaRuntimeException("No bean types are available to satisfy property " + property);
    }
    List<String> beanTypeNames = Lists.newArrayListWithCapacity(argumentTypes.size());
    for (Class<? extends Bean> argumentType : argumentTypes) {
      beanTypeNames.add(argumentType.getSimpleName());
    }
    _json.put(property.name(), optional(property, StringUtils.join(beanTypeNames, "|")));
  }

  @Override
  public void visitCollectionProperty(MetaProperty<?> property, BeanTraverser traverser) {
    _json.put(property.name(), arrayType(property));
  }

  @Override
  public void visitSetProperty(MetaProperty<?> property, BeanTraverser traverser) {
    _json.put(property.name(), arrayType(property));
  }

  @Override
  public void visitListProperty(MetaProperty<?> property, BeanTraverser traverser) {
    _json.put(property.name(), arrayType(property));
  }

  @Override
  public void visitMapProperty(MetaProperty<?> property, BeanTraverser traverser) {
    Class<? extends Bean> beanType = property.metaBean().beanType();
    Class<?> keyType = JodaBeanUtils.mapKeyType(property, beanType);
    Class<?> valueType = JodaBeanUtils.mapValueType(property, beanType);
    _json.put(property.name(), optional(property,  "{" + typeFor(keyType) + ":" + typeFor(valueType) + "}"));
  }

  @Override
  public void visitProperty(MetaProperty<?> property, BeanTraverser traverser) {
    _json.put(property.name(), optional(property, typeFor(property)));
  }

  private static String optional(MetaProperty<?> property, String type) {
    if (nullable(property)) {
      return type + "?";
    } else {
      return type;
    }
  }

  @Override
  public JSONObject finish() {
    return new JSONObject(_json);
  }

  private String arrayType(MetaProperty<?> property) {
    return optional(property, "[" + typeFor(property.propertyType()) + "]");
  }

  private String typeFor(MetaProperty<?> property) {
    return typeFor(property.propertyType());
  }

  private String typeFor(Class<?> type) {
    String typeName = s_types.get(type);
    if (typeName != null) {
      return typeName;
    } else {
      try {
        _stringConvert.findConverter(type);
        return STRING;
      } catch (Exception e) {
        throw new OpenGammaRuntimeException("No type mapping found for class " + type.getName(), e);
      }
    }
  }

  private static boolean nullable(MetaProperty<?> property) {
    if (property.propertyType().isPrimitive()) {
      return false;
    } else {
      PropertyDefinition definitionAnnotation = property.annotation(PropertyDefinition.class);
      return !definitionAnnotation.validate().equals("notNull");
    }
  }
}
TOP

Related Classes of com.opengamma.web.analytics.blotter.JsonBeanStructureVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.