/******************************************************************************* * 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.ArrayList; import java.util.HashMap; import java.util.List; 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 QObjectTabDelimBimapper<S extends QSpec<S>> implements Bimapper<QObject<S>, String> { private static final Logger LOGGER = Logger.getLogger(QObjectTabDelimBimapper.class.getName()); public static <S extends QSpec<S>> QObjectTabDelimBimapper<S> newInstance(S spec) { return new QObjectTabDelimBimapper<S>(spec); } private S spec; private final List<String> colNames = new ArrayList<String>(); private final List<Attribute<?>> colAttributes = new ArrayList<Attribute<?>>(); private final List<Bimapper> colBimappers = new ArrayList<Bimapper>(); private QObjectTabDelimBimapper(S spec) { this.spec = spec; } public QObjectTabDelimBimapper<S> addColumn(Attribute<?> attribute) { return addColumn(attribute == null ? null : attribute.getName(), attribute); } public QObjectTabDelimBimapper<S> addColumn(Attribute<?> attribute, Bimapper bimapper) { return addColumn(attribute == null ? null : attribute.getName(), attribute, bimapper); } public QObjectTabDelimBimapper<S> addColumn(String name, Attribute<?> attribute) { if (attribute == null) { return addColumn(name, null, null); } Bimapper bimapper = null; Class<?> valueClass = attribute.getValueClass(); if (valueClass == String.class) { bimapper = StringBimapper.instance; } if (valueClass == Boolean.class) { bimapper = BooleanBimapper.instance; } else if (valueClass == Integer.class) { bimapper = IntegerBimapper.instance; } else if (valueClass == Long.class) { bimapper = LongBimapper.instance; } else if (valueClass == Float.class) { bimapper = FloatBimapper.instance; } else if (valueClass == float[].class) { bimapper = FloatArray2ListBimapper.instance; } else if (valueClass.isEnum()) { bimapper = EnumBimapper.newInstance((Class<Enum>) valueClass); } else if (valueClass == Double.class) { bimapper = DoubleBimapper.instance; } else if (valueClass == BigInteger.class) { bimapper = BigIntegerBimapper.instance; } else if (valueClass == BigDecimal.class) { bimapper = BigDecimalBimapper.instance; } return addColumn(name, attribute, bimapper); } public QObjectTabDelimBimapper<S> addColumn(String name, Attribute<?> attribute, Bimapper bimapper) { colNames.add(name); colAttributes.add(attribute); colBimappers.add(bimapper); return this; } public String createHeader() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < colAttributes.size(); i++) { if (i > 0) { sb.append('\t'); } if (colNames.get(i) == null) { continue; } sb.append(colNames.get(i)); } return sb.toString(); } public QObjectTabDelimBimapper<S> deriveFromHeader(String header) { Map<String, Integer> colIndices = new HashMap<String, Integer>(); for (int i = 0; i < colNames.size(); i++) { colIndices.put(colNames.get(i), i); } QObjectTabDelimBimapper<S> result = newInstance(spec); String[] cols = header.split("\\t"); for (String name : cols) { Integer index = colIndices.get(name); if (index != null) { result.addColumn(colNames.get(index), colAttributes.get(index), colBimappers.get(index)); } else { result.addColumn(null, null, null); } } return result; } @Override public String map(QObject<S> in) { if (in == null) { return null; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < colAttributes.size(); i++) { if (i > 0) { sb.append('\t'); } if (colAttributes.get(i) == null) { continue; } Bimapper bimapper = colBimappers.get(i); Object value = in.get(colAttributes.get(i)); if (value != null) { sb.append(bimapper == null ? value.toString() : bimapper.map(value)); } } return sb.toString(); } @Override public QObject<S> unmap(String out) { if (out == null) { return null; } QObject<S> result = spec.newObject(); String[] cols = out.split("\\t"); for (int i = 0; i < Math.min(cols.length, colAttributes.size()); i++) { Attribute<?> attr = colAttributes.get(i); if (attr == null) { continue; } Bimapper bimapper = colBimappers.get(i); try { result.set(attr, bimapper == null ? cols[i] : bimapper.unmap(cols[i])); } catch (Throwable t) { LOGGER.log(Level.WARNING, "Failed to set attribute: " + attr, t); } } return result; } }