/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.q; import java.math.BigDecimal; import java.math.BigInteger; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.andork.func.BigDecimalBimapper; import org.andork.func.BigIntegerBimapper; import org.andork.func.Bimapper; import org.andork.func.BooleanBimapper; import org.andork.func.DoubleBimapper; import org.andork.func.EnumBimapper; import org.andork.func.FloatArray2ListBimapper; import org.andork.func.FloatBimapper; import org.andork.func.IntegerBimapper; import org.andork.func.LongBimapper; import org.andork.func.StringBimapper; import org.andork.q.QSpec.Attribute; public class QObjectMapBimapper<S extends QSpec<S>> implements Bimapper<QObject<S>, Object> { private static final Logger LOGGER = Logger.getLogger(QObjectMapBimapper.class.getName()); public static <S extends QSpec<S>> QObjectMapBimapper<S> newInstance(S spec, Bimapper... attrBimappers) { return new QObjectMapBimapper<S>(spec, attrBimappers); } S spec; Bimapper[] attrBimappers; public QObjectMapBimapper(S spec) { this(spec, new Bimapper[spec.getAttributeCount()]); for (int i = 0; i < spec.getAttributeCount(); i++) { Class<?> valueClass = spec.attributeAt(i).getValueClass(); if (valueClass == String.class) { attrBimappers[i] = StringBimapper.instance; } if (valueClass == Boolean.class) { attrBimappers[i] = BooleanBimapper.instance; } else if (valueClass == Integer.class) { attrBimappers[i] = IntegerBimapper.instance; } else if (valueClass == Long.class) { attrBimappers[i] = LongBimapper.instance; } else if (valueClass == Float.class) { attrBimappers[i] = FloatBimapper.instance; } else if (valueClass == float[].class) { attrBimappers[i] = FloatArray2ListBimapper.instance; } else if (valueClass.isEnum()) { attrBimappers[i] = EnumBimapper.newInstance((Class<Enum>) valueClass); } else if (valueClass == Double.class) { attrBimappers[i] = DoubleBimapper.instance; } else if (valueClass == BigInteger.class) { attrBimappers[i] = BigIntegerBimapper.instance; } else if (valueClass == BigDecimal.class) { attrBimappers[i] = BigDecimalBimapper.instance; } } } public QObjectMapBimapper(S spec, Bimapper... attrBimappers) { if (attrBimappers.length != spec.getAttributeCount()) { throw new IllegalArgumentException("attrBimappers.length must equal spec.getAttributeCount()"); } this.spec = spec; this.attrBimappers = attrBimappers; } public QObjectMapBimapper<S> map(Attribute<?> attr, Bimapper bimapper) { attrBimappers[attr.index] = bimapper; return this; } @Override public Object map(QObject<S> in) { if (in == null) { return null; } Map<Object, Object> result = new LinkedHashMap<Object, Object>(); for (int i = 0; i < spec.getAttributeCount(); i++) { Attribute<?> attribute = spec.attributeAt(i); if (in.has(attribute)) { Object value = in.get(attribute); result.put(attribute.getName(), value == null || attrBimappers[i] == null ? value : attrBimappers[i].map(value)); } } return result; } @Override public QObject<S> unmap(Object out) { if (out == null) { return null; } Map<?, ?> m = (Map<?, ?>) out; QObject<S> result = spec.newObject(); for (int i = 0; i < spec.getAttributeCount(); i++) { Attribute<?> attribute = spec.attributeAt(i); if (m.containsKey(attribute.getName())) { Object value = m.get(attribute.getName()); try { result.set(attribute, value == null || attrBimappers[i] == null ? value : attrBimappers[i].unmap(value)); } catch (Throwable t) { LOGGER.log(Level.WARNING, "Failed to set attribute: " + attribute, t); } } } return result; } }