All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.joda.beans.ser.map.JodaBeanSimpleMapReader Maven / Gradle / Ivy

There is a newer version: 2.11.1
Show newest version
/*
 *  Copyright 2001-present Stephen Colebourne
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.joda.beans.ser.map;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.joda.beans.Bean;
import org.joda.beans.BeanBuilder;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaBean;
import org.joda.beans.MetaProperty;
import org.joda.beans.ser.JodaBeanSer;
import org.joda.beans.ser.SerCategory;
import org.joda.beans.ser.SerDeserializer;
import org.joda.beans.ser.SerIterable;
import org.joda.beans.ser.SerIteratorFactory;
import org.joda.beans.ser.SerOptional;

/**
 * Provides the ability for a Joda-Bean to read from a JSON-like in memory {@code Map}.
 * 

* The format is defined by {@link JodaBeanSimpleMapWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ public class JodaBeanSimpleMapReader { /** * Settings. */ private final JodaBeanSer settings; /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanSimpleMapReader(JodaBeanSer settings) { JodaBeanUtils.notNull(settings, "settings"); this.settings = settings; } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param the root type * @param input the map input, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(Map input, Class rootType) { JodaBeanUtils.notNull(input, "input"); JodaBeanUtils.notNull(rootType, "rootType"); try { return parseRoot(input, rootType); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } //----------------------------------------------------------------------- /** * Parses the root bean. * * @param input the map input, not null * @param declaredType the declared type, not null * @return the bean, not null * @throws Exception if an error occurs */ private T parseRoot(Map input, Class declaredType) throws Exception { Object parsed = parseBean(input, declaredType); return declaredType.cast(parsed); } // parse a bean, event after object start passed in private Object parseBean(Map input, Class beanType) throws Exception { String propName = ""; try { SerDeserializer deser = settings.getDeserializers().findDeserializer(beanType); MetaBean metaBean = deser.findMetaBean(beanType); BeanBuilder builder = deser.createBuilder(beanType, metaBean); for (Entry entry : input.entrySet()) { // property name propName = entry.getKey(); MetaProperty metaProp = deser.findMetaProperty(beanType, metaBean, propName); // ignore unknown properties if (metaProp != null && !metaProp.style().isDerived()) { Object value = parseObject( entry.getValue(), SerOptional.extractType(metaProp, beanType), metaProp, beanType, null); deser.setValue(builder, metaProp, SerOptional.wrapValue(metaProp, beanType, value)); } propName = ""; } return deser.build(beanType, builder); } catch (Exception ex) { throw new IllegalArgumentException( "Error parsing bean: " + beanType.getName() + "::" + propName + ", " + ex.getMessage(), ex); } } // parse object, event passed in @SuppressWarnings("unchecked") private Object parseObject( Object input, Class declaredType, MetaProperty metaProp, Class beanType, SerIterable parentIterable) throws Exception { // parse based on type if (Bean.class.isAssignableFrom(declaredType)) { if (input instanceof Map) { return parseBean((Map) input, declaredType); } else { return parseSimple(input, declaredType); } } else { if (input instanceof List || input instanceof Map) { SerIterable childIterable = null; if (metaProp != null) { childIterable = settings.getIteratorFactory().createIterable(metaProp, beanType, true); } else if (parentIterable != null) { childIterable = settings.getIteratorFactory().createIterable(parentIterable); } if (childIterable == null) { if (input instanceof List) { if (declaredType.isArray()) { childIterable = SerIteratorFactory.array(declaredType.getComponentType()); } else { childIterable = SerIteratorFactory.list(Object.class, Collections.>emptyList()); } } else { childIterable = SerIteratorFactory.map( String.class, Object.class, Collections.>emptyList()); } } return parseIterable(input, childIterable); } else { return parseSimple(input, declaredType); } } } //----------------------------------------------------------------------- private Object parseIterable(Object input, SerIterable iterable) throws Exception { if (iterable.category() == SerCategory.MAP) { return parseIterableMap(input, iterable); } else if (iterable.category() == SerCategory.COUNTED) { return parseIterableCounted(input, iterable); } else if (iterable.category() == SerCategory.TABLE) { return parseIterableTable(input, iterable); } else if (iterable.category() == SerCategory.GRID) { return parseIterableGrid(input, iterable); } else { return parseIterableArray(input, iterable); } } @SuppressWarnings("unchecked") private Object parseIterableMap(Object input, SerIterable iterable) throws Exception { if (input instanceof Map) { for (Entry entry : ((Map) input).entrySet()) { String keyStr = entry.getKey(); Object key = convertText(keyStr, iterable.keyType()); Object value = parseObject(entry.getValue(), iterable.valueType(), null, null, iterable); iterable.add(key, null, value, 1); } return iterable.build(); } else if (input instanceof List) { List inputList = (List) input; for (Object inputVal : inputList) { List inputData = (List) inputVal; if (inputData.size() != 3) { throw new IllegalArgumentException("Expected table iterable to have entries of size 3"); } Object key = parseObject(inputData.get(0), iterable.keyType(), null, null, null); Object value = parseObject(inputData.get(2), iterable.valueType(), null, null, iterable); iterable.add(key, null, value, 1); } return iterable.build(); } else { throw new IllegalArgumentException("Invalid data: Expected List or Map but found " + input); } } private Object parseIterableTable(Object input, SerIterable iterable) throws Exception { List inputList = (List) input; for (Object inputVal : inputList) { List inputData = (List) inputVal; if (inputData.size() != 3) { throw new IllegalArgumentException("Expected table iterable to have entries of size 3"); } Object key = parseObject(inputData.get(0), iterable.keyType(), null, null, null); Object col = parseObject(inputData.get(1), iterable.columnType(), null, null, null); Object value = parseObject(inputData.get(2), iterable.valueType(), null, null, iterable); iterable.add(key, col, value, 1); } return iterable.build(); } private Object parseIterableGrid(Object input, SerIterable iterable) throws Exception { List inputList = (List) input; if (inputList.size() < 2) { throw new IllegalArgumentException("Expected counted iterable to be size 3"); } Integer rows = (Integer) inputList.get(0); Integer columns = (Integer) inputList.get(1); iterable.dimensions(new int[] {rows, columns}); for (Object inputVal : inputList.subList(2, inputList.size())) { List inputData = (List) inputVal; if (inputData.size() != 2) { throw new IllegalArgumentException("Expected grid iterable to have entries of size 3"); } Integer row = (Integer) inputData.get(0); Integer col = (Integer) inputData.get(1); Object value = parseObject(inputData.get(2), iterable.valueType(), null, null, iterable); iterable.add(row, col, value, 1); } return iterable.build(); } private Object parseIterableCounted(Object input, SerIterable iterable) throws Exception { List inputList = (List) input; for (Object inputVal : inputList) { List inputData = (List) inputVal; if (inputData.size() != 2) { throw new IllegalArgumentException("Expected counted iterable to have entries of size 2"); } Object value = parseObject(inputData.get(0), iterable.valueType(), null, null, iterable); Integer count = (Integer) inputData.get(1); iterable.add(null, null, value, count); } return iterable.build(); } private Object parseIterableArray(Object input, SerIterable iterable) throws Exception { List inputList = (List) input; for (Object inputVal : inputList) { Object value = parseObject(inputVal, iterable.valueType(), null, null, iterable); iterable.add(null, null, value, 1); } return iterable.build(); } private Object parseSimple(Object input, Class type) throws Exception { if (input == null) { if (type == double.class || type == Double.class) { return Double.NaN; // leniently accept null for NaN } else if (type == float.class || type == Float.class) { return Float.NaN; // leniently accept null for NaN } else { return null; } } if (input instanceof String) { return convertText(input, type); } if (input instanceof Boolean) { return input; } if (input instanceof Long) { Long inputLong = (Long) input; if (type == Long.class || type == long.class) { return inputLong; } else { return convertInteger(inputLong.longValue(), type); } } if (input instanceof Integer) { Integer inputInteger = (Integer) input; if (type == Integer.class || type == int.class) { return inputInteger; } else { return convertInteger(inputInteger.longValue(), type); } } if (input instanceof Double) { Double inputDouble = (Double) input; if (type == Double.class || type == double.class) { return inputDouble; } else if (type == Float.class || type == float.class) { return inputDouble.floatValue(); } else { return convertInteger(inputDouble.longValue(), type); } } if (input instanceof Float) { Float inputFloat = (Float) input; if (type == Float.class || type == float.class) { return inputFloat; } else if (type == Double.class || type == double.class) { return inputFloat.doubleValue(); } else { return convertInteger(inputFloat.longValue(), type); } } if (input instanceof Short || input instanceof Byte) { return input; } throw new IllegalArgumentException("Invalid data: Expected simple type but found " + input); } private Object convertText(Object input, Class type) { if (type == Object.class || type.isAssignableFrom(String.class)) { return input; } return settings.getConverter().convertFromString(type, (String) input); } private Object convertInteger(long value, Class type) { if (type == Long.class || type == long.class) { return Long.valueOf(value); } else if (type == Short.class || type == short.class) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of short: " + value); } return Short.valueOf((short) value); } else if (type == Byte.class || type == byte.class) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of byte: " + value); } return Byte.valueOf((byte) value); } else if (type == Double.class || type == double.class) { double dblVal = (double) value; if (value != (long) dblVal) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of double: " + value); } return Double.valueOf(dblVal); } else if (type == Float.class || type == float.class) { float fltVal = (float) value; if (value != (long) fltVal) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of float: " + value); } return Float.valueOf(fltVal); } else { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Expected int, but was " + value); } return Integer.valueOf((int) value); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy