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