1 // This builder does several things:
3 // 1) The MultiViewMap constructor is private because
4 // there is a lot of consistency checking to do in
5 // the inputs (like whether a view is specified
6 // twice) so do all that in a builder and the map
7 // itself can assume valid inputs at the constructor.
9 // 2) The inputs to construct a MultiViewMap are tedious
10 // to code, so this builder lets you write the
11 // specifications succinctly.
13 // 3) If you are creating many MultiViewMap's of the same
14 // type and views, it is best to have one builder that
15 // generates each fresh map rather than build up all
16 // the small specification objects again.
20 import java.util.BitSet;
21 import java.util.Vector;
24 public class MultiViewMapBuilder<T> {
26 private Class[] keyTypes;
27 private Vector<BitSet> partialViews;
28 private BitSet fullView;
30 private JoinOp<T> joinOp;
32 private boolean checkTypes;
33 private boolean checkConsistency;
36 // define the types and ordering of the multikey
37 public MultiViewMapBuilder( Class[] keyTypes, JoinOp<T> joinOp ) {
38 assert( keyTypes != null );
39 assert( joinOp != null );
41 if( keyTypes.length == 0 ) {
42 throw new IllegalArgumentException( "The multikey must have at least one key type." );
45 this.keyTypes = keyTypes;
46 this.partialViews = new Vector<BitSet>();
48 this.checkTypes = false;
49 this.checkConsistency = false;
51 fullView = new BitSet( keyTypes.length );
52 for( int i = 0; i < keyTypes.length; ++i ) {
58 public final BitSet addPartialView( Integer... keyIndices ) {
59 if( keyIndices.length == 0 ) {
60 throw new IllegalArgumentException( "A view must have at least one key index." );
63 // build a view from the arg list
64 BitSet view = new BitSet( keyTypes.length );
65 for( Integer i : keyIndices ) {
66 if( i < 0 || i >= keyTypes.length ) {
67 throw new IllegalArgumentException( "Key index in view is out of bounds." );
70 throw new IllegalArgumentException( "Key index in view is specified more than once." );
75 if( keyIndices.length == keyTypes.length &&
76 view.cardinality() == keyTypes.length ) {
77 throw new IllegalArgumentException( "The full view is always included implicitly." );
80 for( BitSet existingView : partialViews ) {
81 if( view.equals( existingView ) ) {
82 throw new IllegalArgumentException( "View matches an existing view." );
86 return addPartialView( view );
90 public final BitSet addPartialView( BitSet view ) {
91 partialViews.add( view );
92 return (BitSet) view.clone();
96 public final BitSet getFullView() {
101 public void setCheckTypes( boolean checkTypes ) {
102 this.checkTypes = checkTypes;
106 public void setCheckConsistency( boolean checkConsistency ) {
107 this.checkConsistency = checkConsistency;
111 public MultiViewMap<T> build() {
112 if( partialViews.isEmpty() ) {
113 throw new IllegalArgumentException( "No partial views specified for this builder." );
115 return new MultiViewMap<T>( keyTypes,