Coverage Report - org.kuali.student.core.assembly.data.Data
 
Classes in this File Line Coverage Branch Coverage Complexity
Data
28%
68/237
25%
16/64
1.326
Data$1
0%
0/4
0%
0/2
1.326
Data$2
50%
5/10
N/A
1.326
Data$2$1
28%
2/7
N/A
1.326
Data$3
0%
0/10
N/A
1.326
Data$3$1
0%
0/7
N/A
1.326
Data$BooleanValue
30%
3/10
0%
0/2
1.326
Data$DataType
100%
3/3
N/A
1.326
Data$DataValue
40%
4/10
0%
0/2
1.326
Data$DateValue
40%
4/10
0%
0/2
1.326
Data$DoubleValue
40%
4/10
0%
0/2
1.326
Data$FloatValue
0%
0/10
0%
0/2
1.326
Data$IntegerKey
40%
4/10
0%
0/4
1.326
Data$IntegerValue
0%
0/10
0%
0/2
1.326
Data$Key
N/A
N/A
1.326
Data$LongValue
0%
0/10
0%
0/2
1.326
Data$Property
N/A
N/A
1.326
Data$ShortValue
0%
0/10
0%
0/2
1.326
Data$StringKey
70%
7/10
50%
2/4
1.326
Data$StringValue
40%
4/10
N/A
1.326
Data$TimeValue
0%
0/10
0%
0/2
1.326
Data$TimestampValue
0%
0/10
0%
0/2
1.326
Data$Value
N/A
N/A
1.326
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.core.assembly.data;
 17  
 
 18  
 import javax.xml.bind.annotation.XmlRootElement;
 19  
 import javax.xml.bind.annotation.XmlType;
 20  
 import java.io.Serializable;
 21  
 import java.sql.Time;
 22  
 import java.sql.Timestamp;
 23  
 import java.util.*;
 24  
 import java.util.Map.Entry;
 25  
 
 26  
 /**
 27  
  * @author wilj
 28  
  */
 29  
 @SuppressWarnings({"serial", "unchecked"})
 30  0
 public class Data implements Serializable, Iterable<Data.Property>, HasChangeCallbacks {
 31  223
     @XmlType(name = "lookUpDataType")
 32  40
     public enum DataType {
 33  4
         STRING, INTEGER, LONG, FLOAT, DOUBLE, BOOLEAN, DATE, TRUNCATED_DATE, DATA, LIST
 34  
     }
 35  
 
 36  
     @XmlRootElement
 37  
     public static class BooleanValue implements Value {
 38  
         private Boolean value;
 39  
 
 40  0
         protected BooleanValue() {
 41  
 
 42  0
         }
 43  
 
 44  3
         public BooleanValue(final Boolean value) {
 45  3
             this.value = value;
 46  3
         }
 47  
 
 48  
         @Override
 49  
         public <T> T get() {
 50  0
             return (T) value;
 51  
         }
 52  
 
 53  
         @Override
 54  
         public Class getType() {
 55  0
             return Boolean.class;
 56  
         }
 57  
 
 58  
         @Override
 59  
         public String toString() {
 60  0
             if (value == null) {
 61  0
                 return "";
 62  
             } else {
 63  0
                 return String.valueOf(value);
 64  
             }
 65  
         }
 66  
     }
 67  
 
 68  
     @XmlRootElement
 69  
     public static class DataValue implements Value {
 70  
         private Data value;
 71  
 
 72  0
         protected DataValue() {
 73  
 
 74  0
         }
 75  
 
 76  2
         public DataValue(final Data value) {
 77  2
             this.value = value;
 78  2
         }
 79  
 
 80  
         @Override
 81  
         public <T> T get() {
 82  2
             return (T) value;
 83  
         }
 84  
 
 85  
         @Override
 86  
         public Class getType() {
 87  0
             return Data.class;
 88  
         }
 89  
 
 90  
         @Override
 91  
         public String toString() {
 92  0
             if (value == null) {
 93  0
                 return null;
 94  
             } else {
 95  0
                 return value.toString();
 96  
             }
 97  
         }
 98  
     }
 99  
 
 100  
     @XmlRootElement
 101  
     public static class DateValue implements Value {
 102  
         private Date value;
 103  
 
 104  0
         protected DateValue() {
 105  
 
 106  0
         }
 107  
 
 108  1
         public DateValue(final Date value) {
 109  1
             this.value = value;
 110  1
         }
 111  
 
 112  
         @Override
 113  
         public <T> T get() {
 114  1
             return (T) value;
 115  
         }
 116  
 
 117  
         @Override
 118  
         public Class getType() {
 119  0
             return Date.class;
 120  
         }
 121  
 
 122  
         @Override
 123  
         public String toString() {
 124  0
             if (value == null) {
 125  0
                 return null;
 126  
             } else {
 127  0
                 return String.valueOf(value);
 128  
             }
 129  
         }
 130  
     }
 131  
 
 132  
     @XmlRootElement
 133  
     public static class DoubleValue implements Value {
 134  
         private Double value;
 135  
 
 136  0
         protected DoubleValue() {
 137  
 
 138  0
         }
 139  
 
 140  1
         public DoubleValue(final Double value) {
 141  1
             this.value = value;
 142  1
         }
 143  
 
 144  
         @Override
 145  
         public <T> T get() {
 146  1
             return (T) value;
 147  
         }
 148  
 
 149  
         @Override
 150  
         public Class getType() {
 151  0
             return Double.class;
 152  
         }
 153  
 
 154  
         @Override
 155  
         public String toString() {
 156  0
             if (value == null) {
 157  0
                 return null;
 158  
             } else {
 159  0
                 return String.valueOf(value);
 160  
             }
 161  
         }
 162  
     }
 163  
 
 164  
     @XmlRootElement
 165  
     public static class FloatValue implements Value {
 166  
         private Float value;
 167  
 
 168  0
         protected FloatValue() {
 169  
 
 170  0
         }
 171  
 
 172  0
         public FloatValue(final Float value) {
 173  0
             this.value = value;
 174  0
         }
 175  
 
 176  
         @Override
 177  
         public <T> T get() {
 178  0
             return (T) value;
 179  
         }
 180  
 
 181  
         @Override
 182  
         public Class getType() {
 183  0
             return Float.class;
 184  
         }
 185  
 
 186  
         @Override
 187  
         public String toString() {
 188  0
             if (value == null) {
 189  0
                 return null;
 190  
             } else {
 191  0
                 return String.valueOf(value);
 192  
             }
 193  
         }
 194  
     }
 195  
 
 196  
     public static class IntegerKey implements Key {
 197  
         private Integer key;
 198  
 
 199  0
         protected IntegerKey() {
 200  
 
 201  0
         }
 202  
 
 203  1
         public IntegerKey(final Integer key) {
 204  1
             this.key = key;
 205  1
         }
 206  
 
 207  
         /*
 208  
          * (non-Javadoc)
 209  
          * 
 210  
          * @see java.lang.Object#equals(java.lang.Object)
 211  
          */
 212  
 
 213  
         @Override
 214  
         public boolean equals(final Object obj) {
 215  0
             return obj instanceof IntegerKey && key.equals(((IntegerKey) obj).key);
 216  
         }
 217  
 
 218  
         @Override
 219  
         public <T> T get() {
 220  0
             return (T) key;
 221  
         }
 222  
 
 223  
         @Override
 224  
         public Class getType() {
 225  0
             return Integer.class;
 226  
         }
 227  
 
 228  
         /*
 229  
          * (non-Javadoc)
 230  
          * 
 231  
          * @see java.lang.Object#hashCode()
 232  
          */
 233  
 
 234  
         @Override
 235  
         public int hashCode() {
 236  2
             return key.hashCode();
 237  
         }
 238  
 
 239  
         /*
 240  
          * (non-Javadoc)
 241  
          * 
 242  
          * @see java.lang.Object#toString()
 243  
          */
 244  
 
 245  
         @Override
 246  
         public String toString() {
 247  0
             return String.valueOf(key);
 248  
         }
 249  
 
 250  
     }
 251  
 
 252  
     @XmlRootElement
 253  
     public static class IntegerValue implements Value {
 254  
         private Integer value;
 255  
 
 256  0
         protected IntegerValue() {
 257  
 
 258  0
         }
 259  
 
 260  0
         public IntegerValue(final Integer value) {
 261  0
             this.value = value;
 262  0
         }
 263  
 
 264  
         @Override
 265  
         public <T> T get() {
 266  0
             return (T) value;
 267  
         }
 268  
 
 269  
         @Override
 270  
         public Class getType() {
 271  0
             return Integer.class;
 272  
         }
 273  
 
 274  
         @Override
 275  
         public String toString() {
 276  0
             if (value == null) {
 277  0
                 return null;
 278  
             } else {
 279  0
                 return String.valueOf(value);
 280  
             }
 281  
         }
 282  
     }
 283  
 
 284  
     public interface Key extends Serializable {
 285  
 
 286  
         <T> T get();
 287  
 
 288  
         Class getType();
 289  
     }
 290  
 
 291  
     @XmlRootElement
 292  
     public static class LongValue implements Value {
 293  
         private Long value;
 294  
 
 295  0
         protected LongValue() {
 296  
 
 297  0
         }
 298  
 
 299  0
         public LongValue(final Long value) {
 300  0
             this.value = value;
 301  0
         }
 302  
 
 303  
         @Override
 304  
         public <T> T get() {
 305  0
             return (T) value;
 306  
         }
 307  
 
 308  
         @Override
 309  
         public Class getType() {
 310  0
             return Long.class;
 311  
         }
 312  
 
 313  
         @Override
 314  
         public String toString() {
 315  0
             if (value == null) {
 316  0
                 return null;
 317  
             } else {
 318  0
                 return String.valueOf(value);
 319  
             }
 320  
         }
 321  
     }
 322  
 
 323  
     public interface Property {
 324  
         <T> T getKey();
 325  
 
 326  
         Class getKeyType();
 327  
 
 328  
         Key getWrappedKey();
 329  
 
 330  
         <T> T getValue();
 331  
 
 332  
         Class getValueType();
 333  
 
 334  
         Value getWrappedValue();
 335  
     }
 336  
 
 337  
     @XmlRootElement
 338  
     public static class ShortValue implements Value {
 339  
         private Short value;
 340  
 
 341  0
         protected ShortValue() {
 342  
 
 343  0
         }
 344  
 
 345  0
         public ShortValue(final Short value) {
 346  0
             this.value = value;
 347  0
         }
 348  
 
 349  
         @Override
 350  
         public <T> T get() {
 351  0
             return (T) value;
 352  
         }
 353  
 
 354  
         @Override
 355  
         public Class getType() {
 356  0
             return Short.class;
 357  
         }
 358  
 
 359  
         @Override
 360  
         public String toString() {
 361  0
             if (value == null) {
 362  0
                 return null;
 363  
             } else {
 364  0
                 return String.valueOf(value);
 365  
             }
 366  
         }
 367  
     }
 368  
 
 369  
     @XmlRootElement
 370  
     public static class StringKey implements Key {
 371  
         private String key;
 372  
 
 373  0
         protected StringKey() {
 374  
 
 375  0
         }
 376  
 
 377  63
         public StringKey(final String key) {
 378  63
             this.key = key;
 379  63
         }
 380  
 
 381  
         /*
 382  
          * (non-Javadoc)
 383  
          * 
 384  
          * @see java.lang.Object#equals(java.lang.Object)
 385  
          */
 386  
 
 387  
         @Override
 388  
         public boolean equals(final Object obj) {
 389  36
             return obj instanceof StringKey && key.equals(((StringKey) obj).key);
 390  
         }
 391  
 
 392  
         @Override
 393  
         public <T> T get() {
 394  2
             return (T) key;
 395  
         }
 396  
 
 397  
         @Override
 398  
         public Class<?> getType() {
 399  0
             return String.class;
 400  
         }
 401  
 
 402  
         /*
 403  
          * (non-Javadoc)
 404  
          * 
 405  
          * @see java.lang.Object#hashCode()
 406  
          */
 407  
 
 408  
         @Override
 409  
         public int hashCode() {
 410  97
             return key.hashCode();
 411  
         }
 412  
 
 413  
         /*
 414  
          * (non-Javadoc)
 415  
          * 
 416  
          * @see java.lang.Object#toString()
 417  
          */
 418  
 
 419  
         @Override
 420  
         public String toString() {
 421  14
             return key;
 422  
         }
 423  
 
 424  
     }
 425  
 
 426  
     @XmlRootElement
 427  
     public static class StringValue implements Value {
 428  
         private String value;
 429  
 
 430  0
         protected StringValue() {
 431  
 
 432  0
         }
 433  
 
 434  52
         public StringValue(final String value) {
 435  52
             this.value = value;
 436  52
         }
 437  
 
 438  
         @Override
 439  
         public <T> T get() {
 440  26
             return (T) value;
 441  
         }
 442  
 
 443  
         @Override
 444  
         public Class getType() {
 445  0
             return String.class;
 446  
         }
 447  
 
 448  
         @Override
 449  
         public String toString() {
 450  0
             return value;
 451  
         }
 452  
 
 453  
         public void setValue(String value) {
 454  0
             this.value = value;
 455  0
         }
 456  
     }
 457  
 
 458  
     @XmlRootElement
 459  
     public static class TimestampValue implements Value {
 460  
         private Timestamp value;
 461  
 
 462  0
         protected TimestampValue() {
 463  
 
 464  0
         }
 465  
 
 466  0
         public TimestampValue(final Timestamp value) {
 467  0
             this.value = value;
 468  0
         }
 469  
 
 470  
         @Override
 471  
         public <T> T get() {
 472  0
             return (T) value;
 473  
         }
 474  
 
 475  
         @Override
 476  
         public Class getType() {
 477  0
             return Timestamp.class;
 478  
         }
 479  
 
 480  
         @Override
 481  
         public String toString() {
 482  0
             if (value == null) {
 483  0
                 return null;
 484  
             } else {
 485  0
                 return String.valueOf(value);
 486  
             }
 487  
         }
 488  
     }
 489  
 
 490  
     @XmlRootElement
 491  
     public static class TimeValue implements Value {
 492  
         private Time value;
 493  
 
 494  0
         protected TimeValue() {
 495  
 
 496  0
         }
 497  
 
 498  0
         public TimeValue(final Time value) {
 499  0
             this.value = value;
 500  0
         }
 501  
 
 502  
         @Override
 503  
         public <T> T get() {
 504  0
             return (T) value;
 505  
         }
 506  
 
 507  
         @Override
 508  
         public Class getType() {
 509  0
             return Time.class;
 510  
         }
 511  
 
 512  
         @Override
 513  
         public String toString() {
 514  0
             if (value == null) {
 515  0
                 return null;
 516  
             } else {
 517  0
                 return String.valueOf(value);
 518  
             }
 519  
         }
 520  
     }
 521  
 
 522  
     public interface Value extends Serializable {
 523  
         <T> T get();
 524  
 
 525  
         Class getType();
 526  
     }
 527  
 
 528  2
     public static final Key WILDCARD_KEY = new Data.StringKey(QueryPath.getWildCard());
 529  
 
 530  
     private transient Set<ChangeCallback> changeCallbacks;
 531  
 
 532  
     private String className;
 533  
 
 534  
     private Map<Key, Value> map;
 535  
 
 536  5
     private Data parent = null;
 537  
 
 538  5
     private Key parentKey = null;
 539  
 
 540  
     public Data() {
 541  5
         this(Data.class.getName());
 542  5
     }
 543  
 
 544  5
     public Data(final String className) {
 545  5
         this.className = className;
 546  5
         map = new LinkedHashMap<Key, Value>();
 547  5
     }
 548  
 
 549  
     protected void _getQueryPath(final QueryPath path) {
 550  27
         if (parent != null) {
 551  0
             parent._getQueryPath(path);
 552  0
             path.add(parentKey);
 553  
         }
 554  27
     }
 555  
 
 556  
     protected void execChangeCallbacks(ChangeType type, QueryPath path) {
 557  27
         if (changeCallbacks != null) {
 558  0
             for (ChangeCallback c : changeCallbacks) {
 559  0
                 c.onChange(type, path);
 560  
             }
 561  
         }
 562  27
         if (parent != null) {
 563  0
             parent.execChangeCallbacks(type, path);
 564  
         }
 565  27
     }
 566  
 
 567  
     public ChangeCallbackRegistration addChangeCallback(final ChangeCallback callback) {
 568  0
         if (changeCallbacks == null) {
 569  0
             changeCallbacks = new HashSet<ChangeCallback>();
 570  
         }
 571  0
         changeCallbacks.add(callback);
 572  0
         return new ChangeCallbackRegistration() {
 573  
             @Override
 574  
             public void remove() {
 575  0
                 if (changeCallbacks != null) {
 576  0
                     changeCallbacks.remove(callback);
 577  
                 }
 578  0
             }
 579  
         };
 580  
     }
 581  
 
 582  
     private void put(Key key, Value value) {
 583  27
         Value existing = map.put(key, value);
 584  27
         ChangeType type = existing == null ? ChangeType.ADD : ChangeType.UPDATE;
 585  27
         QueryPath path = getQueryPath();
 586  27
         path.add(key);
 587  27
         execChangeCallbacks(type, path);
 588  27
     }
 589  
 
 590  
     public void remove(Key key) {
 591  
         // TODO probably need to add all of the other remove(type) methods
 592  0
         map.remove(key);
 593  0
         QueryPath path = getQueryPath();
 594  0
         path.add(key);
 595  0
         execChangeCallbacks(ChangeType.REMOVE, path);
 596  0
     }
 597  
 
 598  
     public void add(final Boolean value) {
 599  0
         put(new IntegerKey(map.size()), new BooleanValue(value));
 600  0
     }
 601  
 
 602  
     public void add(final Data value) {
 603  1
         final Key k = new IntegerKey(map.size());
 604  1
         put(k, new DataValue(value));
 605  1
         if (value != null) {
 606  1
             value.parent = this;
 607  1
             value.parentKey = k;
 608  
         }
 609  1
     }
 610  
 
 611  
     public void add(final Date value) {
 612  0
         put(new IntegerKey(map.size()), new DateValue(value));
 613  0
     }
 614  
 
 615  
     public void add(final Double value) {
 616  0
         put(new IntegerKey(map.size()), new DoubleValue(value));
 617  0
     }
 618  
 
 619  
     public void add(final Float value) {
 620  0
         put(new IntegerKey(map.size()), new FloatValue(value));
 621  0
     }
 622  
 
 623  
     public void add(final Integer value) {
 624  0
         put(new IntegerKey(map.size()), new IntegerValue(value));
 625  0
     }
 626  
 
 627  
     public void add(final Long value) {
 628  0
         put(new IntegerKey(map.size()), new LongValue(value));
 629  0
     }
 630  
 
 631  
     public void add(final Short value) {
 632  0
         put(new IntegerKey(map.size()), new ShortValue(value));
 633  0
     }
 634  
 
 635  
     public void add(final String value) {
 636  0
         put(new IntegerKey(map.size()), new StringValue(value));
 637  0
     }
 638  
 
 639  
     public void add(final Time value) {
 640  0
         put(new IntegerKey(map.size()), new TimeValue(value));
 641  0
     }
 642  
 
 643  
     public void add(final Timestamp value) {
 644  0
         put(new IntegerKey(map.size()), new TimestampValue(value));
 645  0
     }
 646  
 
 647  
     public Data copy() {
 648  0
         return copy(new Data(this.className), true);
 649  
     }
 650  
 
 651  
     public Data copy(Data target, boolean recurse) {
 652  
         // note, this was the clone() method, but my eclipse code cleanup insists on @Override, and the compiler gives an
 653  
         // error
 654  0
         for (final Entry<Key, Value> e : map.entrySet()) {
 655  0
             if (recurse && e.getValue().getType().equals(Data.class)) {
 656  0
                 Data value = e.getValue().get();
 657  0
                 if (value != null) {
 658  0
                     value = value.copy();
 659  
                 }
 660  0
                 target.map.put(e.getKey(), new DataValue(value));
 661  0
             } else {
 662  0
                 target.map.put(e.getKey(), e.getValue());
 663  
             }
 664  
         }
 665  0
         return target;
 666  
     }
 667  
 
 668  
     public <T> T get(final Integer key) {
 669  0
         final Value v = map.get(new IntegerKey(key));
 670  0
         T result = null;
 671  0
         if (v != null) {
 672  0
             result = (T) v.get();
 673  
         }
 674  0
         return result;
 675  
     }
 676  
 
 677  
     public <T> T get(final Key key) {
 678  27
         final Value v = map.get(key);
 679  27
         T result = null;
 680  27
         if (v != null) {
 681  22
             result = (T) v.get();
 682  
         }
 683  27
         return result;
 684  
     }
 685  
 
 686  
     public <T> T get(final String key) {
 687  11
         final Value v = map.get(new StringKey(key));
 688  11
         T result = null;
 689  11
         if (v != null) {
 690  7
             result = (T) v.get();
 691  
         }
 692  11
         return result;
 693  
     }
 694  
 
 695  
     public String getClassName() {
 696  0
         return this.className;
 697  
     }
 698  
 
 699  
     public Data getParent() {
 700  0
         return parent;
 701  
     }
 702  
 
 703  
     public QueryPath getQueryPath() {
 704  27
         final QueryPath result = new QueryPath();
 705  27
         _getQueryPath(result);
 706  27
         return result;
 707  
     }
 708  
 
 709  
 
 710  
     /**
 711  
      * @return an Iterator that does not contain any _runtimeData
 712  
      */
 713  
     public Iterator<Property> realPropertyIterator() {
 714  1
         HashMap<Key, Value> propertyMap = new HashMap<Key, Value>(map);
 715  
 //            propertyMap.remove("_runtimeData");
 716  1
         propertyMap.remove(new StringKey("_runtimeData"));
 717  
 
 718  1
         final Iterator<Map.Entry<Key, Value>> impl = propertyMap.entrySet().iterator();
 719  
 
 720  1
         return new Iterator<Property>() {
 721  
             Map.Entry<Key, Value> current;
 722  
 
 723  
             @Override
 724  
             public boolean hasNext() {
 725  2
                 return impl.hasNext();
 726  
             }
 727  
 
 728  
             @Override
 729  
             public Property next() {
 730  1
                 final Map.Entry<Key, Value> entry = impl.next();
 731  1
                 current = entry;
 732  1
                 return new Property() {
 733  
                     @Override
 734  
                     public <T> T getKey() {
 735  0
                         return (T) entry.getKey().get();
 736  
                     }
 737  
 
 738  
                     @Override
 739  
                     public Class<?> getKeyType() {
 740  0
                         return entry.getKey().getType();
 741  
                     }
 742  
 
 743  
                     @Override
 744  
                     public <T> T getValue() {
 745  1
                         return (T) entry.getValue().get();
 746  
                     }
 747  
 
 748  
                     @Override
 749  
                     public Class<?> getValueType() {
 750  0
                         return entry.getValue().getType();
 751  
                     }
 752  
 
 753  
                     @Override
 754  
                     public Key getWrappedKey() {
 755  0
                         return entry.getKey();
 756  
                     }
 757  
 
 758  
                     @Override
 759  
                     public Value getWrappedValue() {
 760  0
                         return entry.getValue();
 761  
                     }
 762  
                 };
 763  
             }
 764  
 
 765  
             @Override
 766  
             public void remove() {
 767  0
                 impl.remove();
 768  0
                 QueryPath path = getQueryPath();
 769  0
                 path.add(current.getKey());
 770  0
                 execChangeCallbacks(ChangeType.REMOVE, path);
 771  0
             }
 772  
         };
 773  
     }
 774  
 
 775  
     /*
 776  
     * (non-Javadoc)
 777  
     *
 778  
     * @see java.lang.Iterable#iterator()
 779  
     */
 780  
 
 781  
     @Override
 782  
     public Iterator<Property> iterator() {
 783  0
         final Iterator<Map.Entry<Key, Value>> impl = map.entrySet().iterator();
 784  
 
 785  0
         return new Iterator<Property>() {
 786  
             Map.Entry<Key, Value> current;
 787  
 
 788  
             @Override
 789  
             public boolean hasNext() {
 790  0
                 return impl.hasNext();
 791  
             }
 792  
 
 793  
             @Override
 794  
             public Property next() {
 795  0
                 final Map.Entry<Key, Value> entry = impl.next();
 796  0
                 current = entry;
 797  0
                 return new Property() {
 798  
                     @Override
 799  
                     public <T> T getKey() {
 800  0
                         return (T) entry.getKey().get();
 801  
                     }
 802  
 
 803  
                     @Override
 804  
                     public Class<?> getKeyType() {
 805  0
                         return entry.getKey().getType();
 806  
                     }
 807  
 
 808  
                     @Override
 809  
                     public <T> T getValue() {
 810  0
                         return (T) entry.getValue().get();
 811  
                     }
 812  
 
 813  
                     @Override
 814  
                     public Class<?> getValueType() {
 815  0
                         return entry.getValue().getType();
 816  
                     }
 817  
 
 818  
                     @Override
 819  
                     public Key getWrappedKey() {
 820  0
                         return entry.getKey();
 821  
                     }
 822  
 
 823  
                     @Override
 824  
                     public Value getWrappedValue() {
 825  0
                         return entry.getValue();
 826  
                     }
 827  
                 };
 828  
             }
 829  
 
 830  
             @Override
 831  
             public void remove() {
 832  0
                 impl.remove();
 833  0
                 QueryPath path = getQueryPath();
 834  0
                 path.add(current.getKey());
 835  0
                 execChangeCallbacks(ChangeType.REMOVE, path);
 836  0
             }
 837  
         };
 838  
     }
 839  
 
 840  
     public <T> T query(final QueryPath path) {
 841  1
         T result = null;
 842  1
         Data d = this;
 843  1
         for (final Iterator itr = path.iterator(); itr.hasNext() && d != null;) {
 844  1
             final Key k = (Key) itr.next();
 845  1
             if (itr.hasNext()) {
 846  1
                 Object obj = d.get(k);
 847  1
                 if (obj != null && !(obj instanceof Data)) {
 848  
                     // TODO what should be done if we try to query
 849  
                     // cluset/clus/0/_runtimeData where cluset/0 returns a string instead of Data
 850  
                     // throw an exception here?
 851  0
                     throw new java.lang.IllegalArgumentException();
 852  
                 } else {
 853  1
                     d = d.get(k);
 854  
                 }
 855  1
             } else {
 856  0
                 result = (T) d.get(k);
 857  
             }
 858  1
         }
 859  1
         return result;
 860  
     }
 861  
 
 862  
     public <T> T query(final String path) {
 863  1
         return (T) query(QueryPath.parse(path));
 864  
     }
 865  
 
 866  
     public Class<?> getType(final QueryPath path) {
 867  0
         Value result = null;
 868  0
         Data d = this;
 869  0
         for (final Iterator itr = path.iterator(); itr.hasNext();) {
 870  0
             final Key k = (Key) itr.next();
 871  0
             if (itr.hasNext()) {
 872  0
                 d = d.get(k);
 873  
             } else {
 874  0
                 result = map.get(k);
 875  
             }
 876  0
         }
 877  0
         return result.getType();
 878  
 
 879  
     }
 880  
 
 881  
     public void set(final Integer key, final Boolean value) {
 882  0
         put(new IntegerKey(key), new BooleanValue(value));
 883  0
     }
 884  
 
 885  
     public void set(final Integer key, final Data value) {
 886  0
         final Key k = new IntegerKey(key);
 887  0
         put(k, new DataValue(value));
 888  0
         if (value != null) {
 889  0
             value.parent = this;
 890  0
             value.parentKey = k;
 891  
         }
 892  0
     }
 893  
 
 894  
     public void set(final Integer key, final Date value) {
 895  0
         put(new IntegerKey(key), new DateValue(value));
 896  0
     }
 897  
 
 898  
     public void set(final Integer key, final Double value) {
 899  0
         put(new IntegerKey(key), new DoubleValue(value));
 900  0
     }
 901  
 
 902  
     public void set(final Integer key, final Float value) {
 903  0
         put(new IntegerKey(key), new FloatValue(value));
 904  0
     }
 905  
 
 906  
     public void set(final Integer key, final Integer value) {
 907  0
         put(new IntegerKey(key), new IntegerValue(value));
 908  0
     }
 909  
 
 910  
     public void set(final Integer key, final Long value) {
 911  0
         put(new IntegerKey(key), new LongValue(value));
 912  0
     }
 913  
 
 914  
     public void set(final Integer key, final Short value) {
 915  0
         put(new IntegerKey(key), new ShortValue(value));
 916  0
     }
 917  
 
 918  
     public void set(final Integer key, final String value) {
 919  0
         put(new IntegerKey(key), new StringValue(value));
 920  0
     }
 921  
 
 922  
     public void set(final Integer key, final Time value) {
 923  0
         put(new IntegerKey(key), new TimeValue(value));
 924  0
     }
 925  
 
 926  
     public void set(final Integer key, final Timestamp value) {
 927  0
         put(new IntegerKey(key), new TimestampValue(value));
 928  0
     }
 929  
 
 930  
     public void set(final Key key, final Boolean value) {
 931  0
         put(key, new BooleanValue(value));
 932  0
     }
 933  
 
 934  
     public void set(final Key key, final Data value) {
 935  0
         put(key, new DataValue(value));
 936  0
         if (value != null) {
 937  0
             value.parent = this;
 938  0
             value.parentKey = key;
 939  
         }
 940  0
     }
 941  
 
 942  
     public void set(final Key key, final Date value) {
 943  0
         put(key, new DateValue(value));
 944  0
     }
 945  
 
 946  
     public void set(final Key key, final Double value) {
 947  0
         put(key, new DoubleValue(value));
 948  0
     }
 949  
 
 950  
     public void set(final Key key, final Float value) {
 951  0
         put(key, new FloatValue(value));
 952  0
     }
 953  
 
 954  
     public void set(final Key key, final Integer value) {
 955  0
         put(key, new IntegerValue(value));
 956  0
     }
 957  
 
 958  
     public void set(final Key key, final Long value) {
 959  0
         put(key, new LongValue(value));
 960  0
     }
 961  
 
 962  
     public void set(final Key key, final Short value) {
 963  0
         put(key, new ShortValue(value));
 964  0
     }
 965  
 
 966  
     public void set(final Key key, final String value) {
 967  0
         put(key, new StringValue(value));
 968  0
     }
 969  
 
 970  
     public void set(final Key key, final Time value) {
 971  0
         put(key, new TimeValue(value));
 972  0
     }
 973  
 
 974  
     public void set(final Key key, final Timestamp value) {
 975  0
         put(key, new TimestampValue(value));
 976  0
     }
 977  
 
 978  
     public void set(final Key key, final Value value) {
 979  0
         put(key, value);
 980  0
         if (value instanceof DataValue) {
 981  0
             final Data d = value.get();
 982  0
             if (d != null) {
 983  0
                 d.parent = this;
 984  0
                 d.parentKey = key;
 985  
             }
 986  
         }
 987  0
     }
 988  
 
 989  
     public void set(final String key, final Boolean value) {
 990  0
         put(new StringKey(key), new BooleanValue(value));
 991  0
     }
 992  
 
 993  
     public void set(final String key, final Data value) {
 994  1
         final Key k = new StringKey(key);
 995  1
         put(k, new DataValue(value));
 996  1
         if (value != null) {
 997  1
             value.parent = this;
 998  1
             value.parentKey = k;
 999  
         }
 1000  1
     }
 1001  
 
 1002  
     public void set(final String key, final Date value) {
 1003  1
         put(new StringKey(key), new DateValue(value));
 1004  1
     }
 1005  
 
 1006  
     public void set(final String key, final Double value) {
 1007  1
         put(new StringKey(key), new DoubleValue(value));
 1008  1
     }
 1009  
 
 1010  
     public void set(final String key, final Float value) {
 1011  0
         put(new StringKey(key), new FloatValue(value));
 1012  0
     }
 1013  
 
 1014  
     public void set(final String key, final Integer value) {
 1015  0
         put(new StringKey(key), new IntegerValue(value));
 1016  0
     }
 1017  
 
 1018  
     public void set(final String key, final Long value) {
 1019  0
         put(new StringKey(key), new LongValue(value));
 1020  0
     }
 1021  
 
 1022  
     public void set(final String key, final Short value) {
 1023  0
         put(new StringKey(key), new ShortValue(value));
 1024  0
     }
 1025  
 
 1026  
     public void set(final String key, final String value) {
 1027  23
         put(new StringKey(key), new StringValue(value));
 1028  23
     }
 1029  
 
 1030  
     public void set(final String key, final Time value) {
 1031  0
         put(new StringKey(key), new TimeValue(value));
 1032  0
     }
 1033  
 
 1034  
     public void set(final String key, final Timestamp value) {
 1035  0
         put(new StringKey(key), new TimestampValue(value));
 1036  0
     }
 1037  
 
 1038  
     public Integer size() {
 1039  0
         return map.size();
 1040  
     }
 1041  
 
 1042  
     public String toString() {
 1043  0
             return _toXmlString("");
 1044  
     }
 1045  
         
 1046  
     /**
 1047  
      * Converts the data map to a bracketed string representation
 1048  
      * @return
 1049  
      */
 1050  
     private String _toString(){
 1051  0
         StringBuffer dataString = new StringBuffer();
 1052  
 
 1053  0
         dataString.append("{");
 1054  0
         for (Iterator itr = this.iterator(); itr.hasNext();) {
 1055  0
             Property p = (Property) itr.next();
 1056  0
             dataString.append(p.getKey() + "=" + p.getValue());
 1057  0
             if (itr.hasNext()) {
 1058  0
                 dataString.append(", ");
 1059  
             }
 1060  0
         }
 1061  0
         dataString.append("}");
 1062  
 
 1063  0
         return dataString.toString();
 1064  
     }
 1065  
     
 1066  
     /**
 1067  
      * Converts the data map to an xml representation
 1068  
      * 
 1069  
      */
 1070  
     private String _toXmlString(String indent){
 1071  0
         StringBuffer dataString = new StringBuffer();
 1072  
                 
 1073  0
             for (Iterator itr = this.iterator(); itr.hasNext();) {
 1074  0
             Property p = (Property) itr.next();
 1075  0
             Object value = p.getValue();
 1076  0
             if (value instanceof Data){                    
 1077  0
                     if (p.getKey() instanceof Integer){
 1078  0
                             dataString.append(indent + "<listitem index=\"" + p.getKey() + "\">\n");
 1079  0
                             dataString.append(((Data)value)._toXmlString(indent + "  "));
 1080  0
                         dataString.append(indent + "</listitem>\n");                            
 1081  
                     } else {
 1082  0
                             dataString.append(indent + "<" + p.getKey() + ">\n");
 1083  0
                                 dataString.append(((Data)value)._toXmlString(indent + "  "));
 1084  0
                             dataString.append(indent + "</" + p.getKey() + ">\n");
 1085  
                     }
 1086  0
             } else if (p.getKey() instanceof Integer){
 1087  0
                     dataString.append(indent + "<listitem index=\"" + p.getKey() + "\" value=\""+ value + "\"/>\n");
 1088  
             } else {
 1089  0
                     dataString.append(indent + "<" + p.getKey() + " value=\""+ value + "\"/>\n");                    
 1090  
             }
 1091  0
         }
 1092  
 
 1093  0
         return dataString.toString();
 1094  
     }
 1095  
 
 1096  
     public boolean containsKey(Key key) {
 1097  0
         return map.containsKey(key);
 1098  
     }
 1099  
 
 1100  
     public boolean containsValue(Value value) {
 1101  0
         return map.containsValue(value);
 1102  
     }
 1103  
 
 1104  
     /**
 1105  
      * @return set of top level keys known to this data branch
 1106  
      */
 1107  
     public Set keySet() {
 1108  2
         return map.keySet();
 1109  
     }
 1110  
 
 1111  
     public boolean isEmpty() {
 1112  0
         return map.isEmpty();
 1113  
     }
 1114  
 }