/* * JoinDataSet.java * * Created on April 27, 2007, 10:52 AM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package org.das2.qds; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Create a higher rank dataset with dim 0 being a JOIN dimension. Join implies * that the joined datasets occupy the same physical dimension, and this can * be thought of as the "array of" index. Note DEPEND_0 is treated as a * special case of join. * Note this dataset is mutable, and clients should not mutate it once the reference is made public. * @author jbf */ public class JoinDataSet extends AbstractDataSet { /** * if we haven't joined any datasets, then report this size when length(i) is * queried. QDataSet supports DataSet[0,20,20]. Somewhere there is code * that assumes a qube... */ private static final int NO_DATASET_SIZE = 999; /** * return a copy of the dataset, creating a new JoinDataSet and * copying each slice into the JoinDataSet. * @param rds any dataset * @return a copy of the original dataset. * @deprecated see WritableJoinDataSet */ public static QDataSet deepCopy( QDataSet rds ) { if ( DataSetUtil.isQube(rds) ) { return ArrayDataSet.copy(rds); } JoinDataSet result= new JoinDataSet( rds.rank() ); for ( int i=0; i datasets; /** * rank of the dataset. Joined DataSets should have rank rank-1. */ int rank; /** * Creates a new instance of JoinDataSet * @param rank The rank of the JoinDataSet. Each dataset joined must have rank rank-1. */ public JoinDataSet( int rank ) { this.rank= rank; putProperty(QDataSet.JOIN_0, DDataSet.create( new int[0] ) ); // rank 0 dataset allows properties like CACHE_TAG to be stored here. //putProperty(QDataSet.JOIN_0, "DEPEND_1" ); datasets= new ArrayList<>(); } /** * create a new JoinDataSet, and join the first dataset. *
     *ds1= Ops.rand(30);
     *jds= new JoinDataSet( ds1 );
     *assert( ds1.rank()==1 );
     *assert( jds.rank()==2 );
     *assert( jds.slice(0).equals(ds1) );
     *
* @param ds1 rank N-1 dataset that will be the first slice to add to this rank N dataset. */ public JoinDataSet( QDataSet ds1 ) { this( ds1.rank()+1 ); join(ds1); } /** * copy the JoinDataSet without copying each dataset it contains. * @param joinDataSet another JoinDataSet * @return a copy of the dataset. */ public static JoinDataSet copy(JoinDataSet joinDataSet) { JoinDataSet result= new JoinDataSet(joinDataSet.rank()); result.datasets.addAll( joinDataSet.datasets ); DataSetUtil.putProperties( joinDataSet.properties, result ); DataSetUtil.putProperties( DataSetUtil.getProperties(joinDataSet), result ); result.putProperty(QDataSet.DEPEND_0, joinDataSet.property(QDataSet.DEPEND_0)); result.putProperty(QDataSet.JOIN_0, joinDataSet.property(QDataSet.JOIN_0) ); //might need to clear it if DEPEND_0 is set. return result; } /** * copy all the records into this JoinDataSet. Note this is * a shallow copy, and changes to one of the element datasets is visible * in both JoinDataSets. * TODO: this is probably under implemented, for example element properties. * @param ds1 */ public void joinAll( JoinDataSet ds1 ) { for ( int j=0; j=datasets.size() ) { throw new IndexOutOfBoundsException("no dataset at index: "+i0); } return datasets.get(i0).property(name); } else { return result; } } @Override public Object property(String name) { Object result= properties.get(name); if ( result==null && name.equals(QDataSet.UNITS) && datasets.size()>0 ) { return datasets.get(0).property(name); // all joined datasets must have the same length. } else { return result; } } /** * We override putProperty here because we remove the JOIN_0 if DEPEND_0 is set. * @param name * @param value */ @Override public final void putProperty(String name, Object value) { super.putProperty(name, value); if ( name.equals(QDataSet.DEPEND_0) ) { super.putProperty(QDataSet.JOIN_0, null); } } @Override public int length() { return datasets.size(); } @Override public int length(int i0) { if ( datasets.isEmpty() && i0==0 ) { return NO_DATASET_SIZE; } return datasets.get(i0).length(); } @Override public int length(int i0, int i1) { if ( datasets.isEmpty() && i0==0 ) { return NO_DATASET_SIZE; } return datasets.get(i0).length(i1); } @Override public int length(int i0, int i1, int i2 ) { if ( datasets.isEmpty() && i0==0 ) { return NO_DATASET_SIZE; } return datasets.get(i0).length(i1,i2); } @Override public String toString() { return DataSetUtil.toString(this); } @Override public JoinDataSet trim( int imin, int imax ) { JoinDataSet result= new JoinDataSet(this.rank); result.datasets= new ArrayList(imax-imin); result.datasets.addAll( this.datasets.subList(imin, imax) ); result.properties.putAll( this.properties ); QDataSet dep0= (QDataSet) property( QDataSet.DEPEND_0 ); if ( dep0!=null ) result.properties.put( QDataSet.DEPEND_0, dep0.trim(imin,imax) ); return result; } /** * slice the dataset by returning the joined dataset at this index. If the * dataset is a MutablePropertiesDataSet, then add the properties of this * join dataset to it. The result is made a mutable properties dataset if it * is not already, the danger here is that we may mutate the original data. * Capabilities will fix this. * @param idx the index for the slice * @return the rank N-1 slice at the position. */ @Override public QDataSet slice( int idx ) { QDataSet result= datasets.get(idx); MutablePropertyDataSet mpds= DataSetOps.makePropertiesMutable(result); Map props= DataSetOps.sliceProperties0( idx, properties ); DataSetUtil.putProperties(props, mpds); mpds.makeImmutable(); return result; } }