Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 225   Methods: 19
NCLOC: 119   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
DrJavaProperty.java 46.9% 61.3% 89.5% 61.9%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.config;
 38   
 39    import java.util.Set;
 40    import java.util.Map;
 41    import java.util.HashSet;
 42    import java.util.HashMap;
 43    import java.util.Iterator;
 44    import edu.rice.cs.plt.lambda.Lambda;
 45   
 46    /** Class representing values that can be inserted as variables in external processes.
 47    * @version $Id: DrJavaProperty.java 5175 2010-01-20 08:46:32Z mgricken $
 48    */
 49    public abstract class DrJavaProperty implements Cloneable {
 50    /** Whether the invalidation listening mechanism has been deactivated due to an error. */
 51    public volatile boolean DEACTIVATED_DUE_TO_ERROR = false;
 52   
 53    /** Name of the property. Must be unique. */
 54    protected String _name;
 55    /** Value of the property. */
 56    protected String _value = "--uninitialized--";
 57    /** Is the value current? */
 58    protected boolean _isCurrent = false;
 59    /** Help page for this property. */
 60    protected String _help = "Help unavailable.";
 61    /** Map of attributes. */
 62    protected HashMap<String,String> _attributes = new HashMap<String,String>();
 63    /** Set of other properties that are listening to this property, i.e.
 64    * when this property is invalidated, the other properties are too. */
 65    protected Set<DrJavaProperty> _listening = new HashSet<DrJavaProperty>();
 66   
 67    /** Create a property. */
 68  6106 public DrJavaProperty(String name, String help) {
 69  0 if (name == null) { throw new IllegalArgumentException("DrJavaProperty name is null"); }
 70  6106 _name = name;
 71  6106 if (help != null) { _help = help; }
 72  6106 resetAttributes();
 73    }
 74   
 75    /** Create a property. */
 76  320 public DrJavaProperty(String name, String value, String help) {
 77  320 this(name, help);
 78  0 if (value == null) { throw new IllegalArgumentException("DrJavaProperty value is null"); }
 79  320 if (help != null) { _help = help; }
 80  320 _value = value;
 81  320 _isCurrent = true;
 82    }
 83   
 84    /** Return the name of the property. */
 85  43442 public String getName() { return _name; }
 86   
 87    /** Return the value of the property. If it is not current, update first.
 88    * @param pm PropertyMaps used for substitution when replacing variables */
 89  456 public String getCurrent(PropertyMaps pm) {
 90  456 if (!isCurrent()) {
 91  456 update(pm);
 92  0 if (_value == null) { throw new IllegalArgumentException("DrJavaProperty value is null"); }
 93  456 _isCurrent = true;
 94    }
 95  456 return _value;
 96    }
 97   
 98    /** Return the value of the property lazily. The value may be stale.
 99    * @param pm PropertyMaps used for substitution when replacing variables */
 100  64 public String getLazy(PropertyMaps pm) {
 101  0 if (_value == null) { throw new IllegalArgumentException("DrJavaProperty value is null"); }
 102  64 return _value;
 103    }
 104   
 105    /** Update the property so the value is current.
 106    * @param pm PropertyMaps used for substitution when replacing variables */
 107    public abstract void update(PropertyMaps pm);
 108   
 109    /** Reset attributes to their defaults. Should be overridden by properties that use attributes. */
 110  1238 public void resetAttributes() { _attributes.clear(); }
 111   
 112    /** Set an attribute's value. The attribute must already exist in the table.
 113    * @param key name of the attribute
 114    * @param value new value of the attribute
 115    * @throws IllegalArgumentException if attribute with specified key does not already exist in table
 116    */
 117  346 public void setAttribute(String key, String value) {
 118  346 if (!_attributes.containsKey(key)) {
 119  1 throw new IllegalArgumentException("Attribute " + key + " not known to property " + _name);
 120    }
 121  345 _attributes.put(key, value);
 122    }
 123   
 124    /** Set all attribute values. The attributes must already exist in the table.
 125    * @param attrs attribute key-value pairs
 126    * @param replaceLambda lambda that can be used to replace the variables in a value
 127    * @throws IllegalArgumentException if an attribute with a specified key does not already exist in table
 128    */
 129  7 public void setAttributes(HashMap<String,String> attrs, Lambda<String,String> replaceLambda) {
 130  7 for(Map.Entry<String,String> e: attrs.entrySet()) {
 131  10 setAttribute(e.getKey(), replaceLambda.value(e.getValue()));
 132    }
 133    }
 134   
 135    /** Return an attribute's value.
 136    * @param key name of the attribute
 137    * @throws IllegalArgumentException if attribute with specified key does not already exist in table
 138    */
 139  0 public String getAttribute(String key) {
 140  0 if (!_attributes.containsKey(key)) {
 141  0 throw new IllegalArgumentException("Attribute " + key + " not known to property " + _name);
 142    }
 143  0 return _attributes.get(key);
 144    }
 145   
 146    /** Return the value, which might be stale or null. */
 147  32 public String toString() { return _value; }
 148   
 149    /** Return the value, which might be stale. */
 150  274 public String getHelp() { return _help; }
 151   
 152    /** Return true if the value is current. */
 153  6 public boolean isCurrent() { return _isCurrent; }
 154   
 155    /** Mark the value as stale and invalidate other properties that are listening. */
 156  6 public void invalidate() {
 157  6 _invalidate();
 158  6 invalidateOthers(new HashSet<DrJavaProperty>());
 159    }
 160   
 161    /** Just invalidate. */
 162  357 protected void _invalidate() { _isCurrent = false; }
 163   
 164  298 public DrJavaProperty listenToInvalidatesOf(DrJavaProperty other) {
 165  298 if (other == this) {
 166  0 DEACTIVATED_DUE_TO_ERROR = true;
 167  0 RuntimeException e =
 168    new IllegalArgumentException("Property cannot listen for invalidation of itself. " +
 169    "Variables for external processes will not function correctly anymore. " +
 170    "This is a SERIOUS programming error. Please notify the DrJava team.");
 171  0 edu.rice.cs.drjava.ui.DrJavaErrorHandler.record(e);
 172  0 throw e;
 173    }
 174  298 other._listening.add(this);
 175  298 return this;
 176    }
 177   
 178    /** @return true if the specified property is equal to this one. */
 179  156 public boolean equals(Object other) {
 180  0 if (other == null || other.getClass() != this.getClass()) return false;
 181   
 182  156 DrJavaProperty o = (DrJavaProperty) other;
 183  156 return _name.equals(o._name);
 184   
 185    }
 186   
 187    /** @return the hash code. name is never mutated remains constant, so its hash code can be used. */
 188  1366 public int hashCode() { return _name.hashCode(); }
 189   
 190    /** Invalidate those properties that are listening to this property.
 191    * @param alreadyVisited set of properties already visited, to avoid cycles. */
 192  534 protected void invalidateOthers(Set<DrJavaProperty> alreadyVisited) {
 193  0 if (DEACTIVATED_DUE_TO_ERROR) { return; }
 194  534 if (alreadyVisited.contains(this)) {
 195  0 Iterator<DrJavaProperty> it = alreadyVisited.iterator();
 196  0 StringBuilder sb = new StringBuilder("Invalidating ");
 197  0 sb.append(getName());
 198  0 sb.append(" after already having invalidated ");
 199  0 boolean first = true;
 200  0 while (it.hasNext()) {
 201  0 if (first) { first = false; }
 202  0 else { sb.append(", "); }
 203  0 sb.append(it.next().getName());
 204    }
 205  0 sb.append(". Variables for external processes will not function correctly anymore. " +
 206    "This is a SERIOUS programming error. Please notify the DrJava team.");
 207  0 DEACTIVATED_DUE_TO_ERROR = true;
 208  0 RuntimeException e = new InfiniteLoopException(sb.toString());
 209  0 edu.rice.cs.drjava.ui.DrJavaErrorHandler.record(e);
 210  0 throw e;
 211    }
 212  534 alreadyVisited.add(this);
 213  534 Iterator<DrJavaProperty> it = _listening.iterator();
 214  534 while(it.hasNext()) {
 215  351 DrJavaProperty prop = it.next();
 216  351 prop._invalidate();
 217  351 prop.invalidateOthers(alreadyVisited);
 218    }
 219    }
 220   
 221    /** Exception thrown if an infinite loop of invalidation listening is detected. */
 222    public static class InfiniteLoopException extends RuntimeException {
 223  0 public InfiniteLoopException(String s) { super(s); }
 224    }
 225    }