// DoubleStringTuple.java // // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, Tommy Jasmin and Jeff McWhirter. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * This provides a LoCal Tuple that can hold numeric and string values without * taking the hit that having slots and lots of Real and Text objects around. * * @author MetApps Development Team * @version $Revision: 1.6 $ $Date: 2009-12-01 14:59:41 $ */ public class DoubleStringTuple extends Tuple { private Data[] prototypes; /** The string values */ String[] strings; /** The numeric values */ double[] doubles; /** The tuple type */ TupleType tt; /** The units for the numeric values */ Unit[] units; /** Holds the components as we create them */ Data[] components; /** my size */ int size; /** * Construct a DoubleStringTuple * * @param type The type * @param units The units for the reals * @param doubles The reals * @param strings The strings */ public DoubleStringTuple(TupleType type, double[] doubles, String[] strings, Unit[] units) { this(type, null,doubles, strings, units); } public DoubleStringTuple(TupleType type, Data[] prototypes,double[] doubles, String[] strings, Unit[] units) { super(type); this.tt = type; this.prototypes = prototypes; this.units = units; this.doubles = doubles; this.strings = strings; size = 0; if (doubles != null) { size += doubles.length; } if (strings != null) { size += strings.length; } } /** * Check if there is no Data in this Tuple. * @return true if there is no data. */ public boolean isMissing() { return doubles == null && strings == null; } /** * Make a tuple type from lists of scalar types * * @param numericTypes List of RealTypes * @param stringTypes List of TextTypes * * @return TupleType of the lists * * @throws RemoteException Java RMI problem * @throws VisADException unable to create TupleType */ public static TupleType makeTupleType(List numericTypes, List stringTypes) throws VisADException { List allTypes = new ArrayList(); allTypes.addAll(numericTypes); allTypes.addAll(stringTypes); MathType[] tmp = (MathType[]) allTypes.toArray(new MathType[allTypes.size()]); return new TupleType(tmp); } /** * Get the i'th component. This creates it if needed and * stores it in the components array * * @param i Which one * * @return The component * * @throws RemoteException Java RMI problem * @throws VisADException unable to create TupleType */ public Data getComponent(int i) throws VisADException, RemoteException { // System.err.println ("DoubleStringTuple.getComponent:" + i); if (components == null) { components = new Data[size]; } if (0 <= i && i < getDimension()) { if (components[i] == null) { components[i] = getComponentInner(i); if (components[i] != null) { ((DataImpl) components[i]).setParent(this); } } return components[i]; } else { throw new TypeException("Tuple: component index out of range: "+i); } } /** * Actually get the component * * @param i i * * @return The component * * @throws RemoteException On badness * @throws VisADException */ private Data getComponentInner(int i) throws VisADException, RemoteException { // System.err.println ("get component:" + i +" doubles:" + doubles.length); //System.err.println ("get component:" +tt.getComponent(i)); if ((doubles != null) && (i < doubles.length)) { if(prototypes!=null) { return ((Real)prototypes[i]).cloneButValue(doubles[i]); } if ((units == null) || (units[i] == null)) { return new Real((RealType) tt.getComponent(i), doubles[i]); } else { return new Real((RealType) tt.getComponent(i), doubles[i], units[i]); } } int idx = i-doubles.length; return new Text((TextType) tt.getComponent(i), strings[idx]); } /** * Create, if needed, and return the component array. * * @return components */ public Data[] getComponents(boolean copy) { try { // System.err.println ("DoubleStringTuple.getComponents"); //Create the array and populate it if needed if (components == null) { components = new Data[size]; } for (int i = 0; i < size; i++) { components[i] = getComponent(i); } return components; } catch (Exception exc) { exc.printStackTrace(); throw new IllegalStateException("Error making component array:"+exc); } } /** * Indicates if this Tuple is identical to an object. * * @param obj The object. * @return <code>true</code> if and only if the object is * a Tuple and both Tuple-s have identical component * sequences. */ public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof DoubleStringTuple)) { return false; } DoubleStringTuple that = (DoubleStringTuple) obj; return Arrays.equals(doubles, that.doubles) && Arrays.equals(strings, that.strings) && tt.equals(that.tt) && Arrays.equals(units, that.units); } /** * Returns the hash code of this object. * @return The hash code of this object. */ public int hashCode() { int hashCode = 0; if (doubles != null) { hashCode ^= doubles.hashCode(); } if (strings != null) { hashCode ^= strings.hashCode(); } hashCode ^= tt.hashCode(); return hashCode; } /** * run 'java visad.DoubleStringTuple' to test the RealTuple class * * @param args ignored * * @throws RemoteException Java RMI problem * @throws VisADException Unable to create the VisAD objects */ public static void main(String args[]) throws VisADException, RemoteException { List reals = new ArrayList(); reals.add(RealType.Latitude); reals.add(RealType.Longitude); reals.add(RealType.Altitude); List strings = new ArrayList(); strings.add(TextType.getTextType("id")); double[] vals = new double[] {40, -105, 5337}; String[] svals = new String[] {"Boulder"}; Unit foot = CommonUnit.meter.scale(.3048); // approximate try { foot = visad.data.units.Parser.parse("foot"); } catch (visad.data.units.ParseException pe) {} Unit[] units = new Unit[] {CommonUnit.degree, CommonUnit.degree, foot}; DoubleStringTuple dst = new DoubleStringTuple(DoubleStringTuple.makeTupleType(reals, strings), vals, svals, units); System.out.println(dst); System.out.println("serializable? "+ visad.util.DataUtility.isSerializable(dst)); } }