Clover coverage report - Code Coverage for hivemind release 1.1-beta-1
Coverage timestamp: Thu Apr 28 2005 19:53:41 EDT
file stats: LOC: 278   Methods: 11
NCLOC: 167   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
SchemaElement.java 100% 100% 100% 100%
coverage
 1   
 // Copyright 2004, 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.hivemind.impl;
 16   
 
 17   
 import java.util.ArrayList;
 18   
 import java.util.HashMap;
 19   
 import java.util.HashSet;
 20   
 import java.util.Iterator;
 21   
 import java.util.List;
 22   
 import java.util.Map;
 23   
 import java.util.Set;
 24   
 
 25   
 import org.apache.hivemind.ApplicationRuntimeException;
 26   
 import org.apache.hivemind.Attribute;
 27   
 import org.apache.hivemind.Element;
 28   
 import org.apache.hivemind.Location;
 29   
 import org.apache.hivemind.schema.AttributeModel;
 30   
 import org.apache.hivemind.schema.ElementModel;
 31   
 import org.apache.hivemind.schema.Rule;
 32   
 import org.apache.hivemind.schema.SchemaProcessor;
 33   
 import org.apache.hivemind.schema.Translator;
 34   
 import org.apache.hivemind.schema.rules.NullTranslator;
 35   
 
 36   
 /**
 37   
  * A wrapper around {@link org.apache.hivemind.schema.ElementModel}used by
 38   
  * {@link org.apache.hivemind.impl.SchemaProcessorImpl}.
 39   
  * 
 40   
  * @author Howard Lewis Ship
 41   
  */
 42   
 final class SchemaElement
 43   
 {
 44   
     private SchemaProcessor _processor;
 45   
 
 46   
     private ElementModel _model;
 47   
 
 48   
     private List _requiredAttributes = new ArrayList();
 49   
 
 50   
     private Set _knownAttributes = new HashSet();
 51   
 
 52   
     private String _keyAttribute;
 53   
 
 54   
     private Map _nestedElements;
 55   
 
 56   
     /**
 57   
      * Keyed on attribute name, value is string (possibly null) used to access a translator.
 58   
      */
 59   
     private Map _attributeTranslators = new HashMap();
 60   
 
 61   
     /**
 62   
      * Map of Maps. The outer key is an attribute name string, this indicates that the attribute
 63   
      * values should be unique. Inner map is keyed on attribute value (as a string), the value is
 64   
      * the {@link org.apache.hivemind.Location}defining that value.
 65   
      */
 66   
     private Map _attributeValues = new HashMap();
 67   
 
 68  9868
     SchemaElement(SchemaProcessor processor, ElementModel model)
 69   
     {
 70  9868
         _processor = processor;
 71  9868
         _model = model;
 72  9868
         _keyAttribute = model.getKeyAttribute();
 73   
 
 74  9868
         List attributeModels = model.getAttributeModels();
 75  9868
         int count = attributeModels.size();
 76   
 
 77  9868
         for (int i = 0; i < count; i++)
 78   
         {
 79  10166
             AttributeModel am = (AttributeModel) attributeModels.get(i);
 80   
 
 81  10166
             String name = am.getName();
 82   
 
 83  10166
             _knownAttributes.add(name);
 84   
 
 85  10166
             if (am.isRequired())
 86  5522
                 _requiredAttributes.add(name);
 87   
 
 88   
             // If the attribute should be unique, add a map for that attribute
 89   
             // to track unique values for that attribute.
 90   
 
 91  10166
             if (am.isUnique())
 92  119
                 _attributeValues.put(name, new HashMap());
 93   
 
 94  10166
             if (name.equals(_keyAttribute))
 95   
             {
 96  117
                 _requiredAttributes.add(name);
 97  117
                 _attributeValues.put(name, new HashMap());
 98   
             }
 99   
 
 100  10166
             _attributeTranslators.put(name, am.getTranslator());
 101   
         }
 102   
     }
 103   
 
 104   
     /**
 105   
      * Returns a {@link SchemaElement}for a nested element, or null if no such element exists.
 106   
      */
 107  449
     SchemaElement getNestedElement(String elementName)
 108   
     {
 109  449
         if (_nestedElements == null)
 110  427
             buildNestedElements();
 111   
 
 112  449
         return (SchemaElement) _nestedElements.get(elementName);
 113   
     }
 114   
 
 115  427
     private void buildNestedElements()
 116   
     {
 117  427
         _nestedElements = new HashMap();
 118   
 
 119  427
         List l = _model.getElementModel();
 120  427
         int count = l.size();
 121   
 
 122  427
         for (int i = 0; i < count; i++)
 123   
         {
 124  8889
             ElementModel nested = (ElementModel) l.get(i);
 125   
 
 126  8889
             SchemaElement nestedElement = new SchemaElement(_processor, nested);
 127   
 
 128   
             // TODO: Check for duplicates here, or at parse!
 129   
 
 130  8889
             _nestedElements.put(nested.getElementName(), nestedElement);
 131   
         }
 132   
 
 133   
     }
 134   
 
 135   
     /**
 136   
      * Validates the attributes of the element; checks that all required attributes are present and
 137   
      * that all attributes are defined. Validation errors result in logged error messages.
 138   
      */
 139  3395
     void validateAttributes(Element element)
 140   
     {
 141  3395
         List l = element.getAttributes();
 142  3395
         int count = l.size();
 143  3395
         Set required = new HashSet(_requiredAttributes);
 144  3395
         List errors = new ArrayList();
 145   
 
 146  3395
         for (int i = 0; i < count; i++)
 147   
         {
 148  6103
             Attribute a = (Attribute) l.get(i);
 149  6103
             String name = a.getName();
 150   
 
 151  6103
             if (!_knownAttributes.contains(name))
 152  1
                 errors.add(ImplMessages.unknownAttribute(name));
 153   
 
 154  6103
             checkUniquness(name, a.getValue(), element.getLocation(), errors);
 155   
 
 156  6103
             required.remove(name);
 157   
         }
 158   
 
 159  3395
         Iterator it = required.iterator();
 160   
 
 161  3395
         while (it.hasNext())
 162   
         {
 163  1
             String name = (String) it.next();
 164  1
             errors.add(ImplMessages.missingAttribute(name));
 165   
         }
 166   
 
 167  3395
         count = errors.size();
 168   
 
 169  3395
         if (count == 0)
 170  3393
             return;
 171   
 
 172  2
         StringBuffer buffer = new StringBuffer();
 173   
 
 174  2
         buffer.append(ImplMessages.elementErrors(_processor, element));
 175   
 
 176  2
         for (int i = 0; i < count; i++)
 177   
         {
 178  3
             buffer.append(' ');
 179  3
             buffer.append(errors.get(i).toString());
 180   
         }
 181   
 
 182   
         // TODO: refactor to use the ErrorHandler rather than throw an exception
 183   
         // (these errors are somewhat recoverable).
 184   
 
 185  2
         throw new ApplicationRuntimeException(buffer.toString(), element.getLocation(), null);
 186   
     }
 187   
 
 188  6103
     private void checkUniquness(String name, String value, Location location, List errors)
 189   
     {
 190  6103
         Map valuesMap = (Map) _attributeValues.get(name);
 191   
 
 192   
         // If null, then not checking on uniqueness.
 193   
 
 194  6103
         if (valuesMap == null)
 195  5057
             return;
 196   
 
 197  1046
         Object translatedValue = getAttributeTranslator(name).translate(
 198   
                 _processor.getContributingModule(),
 199   
                 Object.class,
 200   
                 value,
 201   
                 location);
 202   
 
 203  1046
         Location prior = (Location) valuesMap.get(translatedValue);
 204   
 
 205  1046
         if (prior == null)
 206   
         {
 207  1045
             valuesMap.put(translatedValue, location);
 208  1045
             return;
 209   
         }
 210   
 
 211   
         // A conflict.
 212   
 
 213  1
         errors.add(ImplMessages.uniqueAttributeConstraintBroken(
 214   
                 name,
 215   
                 translatedValue.toString(),
 216   
                 prior));
 217   
     }
 218   
 
 219  3393
     void fireBegin(Element element)
 220   
     {
 221  3393
         List rules = _model.getRules();
 222  3393
         int count = rules.size();
 223   
 
 224  3393
         for (int i = 0; i < count; i++)
 225   
         {
 226  15799
             Rule r = (Rule) rules.get(i);
 227   
 
 228  15799
             r.begin(_processor, element);
 229   
 
 230   
         }
 231   
     }
 232   
 
 233  3392
     void fireEnd(Element element)
 234   
     {
 235  3392
         List rules = _model.getRules();
 236  3392
         int count = rules.size();
 237   
 
 238  3392
         for (int i = count - 1; i >= 0; i--)
 239   
         {
 240  15795
             Rule r = (Rule) rules.get(i);
 241   
 
 242  15795
             r.end(_processor, element);
 243   
 
 244   
         }
 245   
     }
 246   
 
 247   
     private Translator _nullTranslator = new NullTranslator();
 248   
 
 249   
     private Translator _contentTranslator;
 250   
 
 251  21
     public Translator getContentTranslator()
 252   
     {
 253  21
         if (_contentTranslator == null)
 254  16
             _contentTranslator = getTranslator(_model.getContentTranslator());
 255   
 
 256  21
         return _contentTranslator;
 257   
     }
 258   
 
 259  7613
     private Translator getTranslator(String translator)
 260   
     {
 261  7613
         if (translator == null)
 262  13
             return _nullTranslator;
 263   
 
 264  7600
         return _processor.getTranslator(translator);
 265   
     }
 266   
 
 267  7597
     public Translator getAttributeTranslator(String attributeName)
 268   
     {
 269  7597
         String translator = (String) _attributeTranslators.get(attributeName);
 270   
 
 271  7597
         return getTranslator(translator);
 272   
     }
 273   
 
 274  578
     public String getKeyAttribute()
 275   
     {
 276  578
         return _keyAttribute;
 277   
     }
 278   
 }