Clover coverage report - Code Coverage for hivemind release 1.0
Coverage timestamp: Wed Sep 22 2004 08:05:25 EDT
file stats: LOC: 254   Methods: 10
NCLOC: 149   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 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
 38   
  * by {@link org.apache.hivemind.impl.SchemaProcessorImpl}.
 39   
  *
 40   
  * @author Howard Lewis Ship
 41   
  */
 42   
 final class SchemaElement
 43   
 {
 44   
     private SchemaProcessor _processor;
 45   
     private ElementModel _model;
 46   
     private List _requiredAttributes = new ArrayList();
 47   
     private Set _knownAttributes = new HashSet();
 48   
     private Map _nestedElements;
 49   
     /**
 50   
      * Keyed on attribute name, value is string (possibly null) used to access a translator.
 51   
      */
 52   
     private Map _attributeTranslators = new HashMap();
 53   
 
 54   
     /**
 55   
      * Map of Maps.  The outer key is an attribute name string, this indicates
 56   
      * that the attribute values should be unique.  Inner map is keyed on attribute value
 57   
      * (as a string), the value is the {@link org.apache.hivemind.Location} defining
 58   
      * that value.
 59   
      */
 60   
     private Map _attributeValues = new HashMap();
 61   
 
 62  7395
     SchemaElement(SchemaProcessor processor, ElementModel model)
 63   
     {
 64  7395
         _processor = processor;
 65  7395
         _model = model;
 66   
 
 67  7395
         List attributeModels = model.getAttributeModels();
 68  7395
         int count = attributeModels.size();
 69   
 
 70  7395
         for (int i = 0; i < count; i++)
 71   
         {
 72  7948
             AttributeModel am = (AttributeModel) attributeModels.get(i);
 73   
 
 74  7948
             String name = am.getName();
 75   
 
 76  7948
             _knownAttributes.add(name);
 77   
 
 78  7948
             if (am.isRequired())
 79  4626
                 _requiredAttributes.add(name);
 80   
 
 81   
             // If the attribute should be unique, add a map for that attribute
 82   
             // to track unique values for that attribute.
 83   
 
 84  7948
             if (am.isUnique())
 85  1
                 _attributeValues.put(name, new HashMap());
 86   
 
 87  7948
             _attributeTranslators.put(name, am.getTranslator());
 88   
         }
 89   
     }
 90   
 
 91   
     /**
 92   
      * Returns a {@link SchemaElement} for a nested element, or
 93   
      * null if no such element exists.
 94   
      */
 95  366
     SchemaElement getNestedElement(String elementName)
 96   
     {
 97  366
         if (_nestedElements == null)
 98  350
             buildNestedElements();
 99   
 
 100  366
         return (SchemaElement) _nestedElements.get(elementName);
 101   
     }
 102   
 
 103  350
     private void buildNestedElements()
 104   
     {
 105  350
         _nestedElements = new HashMap();
 106   
 
 107  350
         List l = _model.getElementModel();
 108  350
         int count = l.size();
 109   
 
 110  350
         for (int i = 0; i < count; i++)
 111   
         {
 112  6580
             ElementModel nested = (ElementModel) l.get(i);
 113   
 
 114  6580
             SchemaElement nestedElement = new SchemaElement(_processor, nested);
 115   
 
 116   
             // TODO: Check for duplicates here, or at parse!
 117   
 
 118  6580
             _nestedElements.put(nested.getElementName(), nestedElement);
 119   
         }
 120   
 
 121   
     }
 122   
 
 123   
     /**
 124   
      * Validates the attributes of the element; checks that all
 125   
      * required attributes are present and that all attributes are defined.
 126   
      * Validation errors result in logged error messages.
 127   
      * 
 128   
      */
 129  2729
     void validateAttributes(Element element)
 130   
     {
 131  2729
         List l = element.getAttributes();
 132  2729
         int count = l.size();
 133  2729
         Set required = new HashSet(_requiredAttributes);
 134  2729
         List errors = new ArrayList();
 135   
 
 136  2729
         for (int i = 0; i < count; i++)
 137   
         {
 138  5003
             Attribute a = (Attribute) l.get(i);
 139  5003
             String name = a.getName();
 140   
 
 141  5003
             if (!_knownAttributes.contains(name))
 142  1
                 errors.add(ImplMessages.unknownAttribute(name));
 143   
 
 144  5003
             checkUniquness(name, a.getValue(), element.getLocation(), errors);
 145   
 
 146  5003
             required.remove(name);
 147   
         }
 148   
 
 149  2729
         Iterator it = required.iterator();
 150   
 
 151  2729
         while (it.hasNext())
 152   
         {
 153  1
             String name = (String) it.next();
 154  1
             errors.add(ImplMessages.missingAttribute(name));
 155   
         }
 156   
 
 157  2729
         count = errors.size();
 158   
 
 159  2729
         if (count == 0)
 160  2727
             return;
 161   
 
 162  2
         StringBuffer buffer = new StringBuffer();
 163   
 
 164  2
         buffer.append(ImplMessages.elementErrors(_processor, element));
 165   
 
 166  2
         for (int i = 0; i < count; i++)
 167   
         {
 168  3
             buffer.append(' ');
 169  3
             buffer.append(errors.get(i).toString());
 170   
         }
 171   
 
 172   
         // TODO: refactor to use the ErrorHandler rather than throw an exception
 173   
         // (these errors are somewhat recoverable).
 174   
 
 175  2
         throw new ApplicationRuntimeException(buffer.toString(), element.getLocation(), null);
 176   
     }
 177   
 
 178  5003
     private void checkUniquness(String name, String value, Location location, List errors)
 179   
     {
 180  5003
         Map valuesMap = (Map) _attributeValues.get(name);
 181   
 
 182   
         // If null, then not checking on uniqueness.
 183   
 
 184  5003
         if (valuesMap == null)
 185  5000
             return;
 186   
 
 187  3
         Location prior = (Location) valuesMap.get(value);
 188   
 
 189  3
         if (prior == null)
 190   
         {
 191  2
             valuesMap.put(value, location);
 192  2
             return;
 193   
         }
 194   
 
 195   
         // A conflict.
 196   
 
 197  1
         errors.add(ImplMessages.uniqueAttributeConstraintBroken(name, value, prior));
 198   
     }
 199   
 
 200  2727
     void fireBegin(Element element)
 201   
     {
 202  2727
         List rules = _model.getRules();
 203  2727
         int count = rules.size();
 204   
 
 205  2727
         for (int i = 0; i < count; i++)
 206   
         {
 207  17549
             Rule r = (Rule) rules.get(i);
 208   
 
 209  17549
             r.begin(_processor, element);
 210   
 
 211   
         }
 212   
     }
 213   
 
 214  2726
     void fireEnd(Element element)
 215   
     {
 216  2726
         List rules = _model.getRules();
 217  2726
         int count = rules.size();
 218   
 
 219  2726
         for (int i = count - 1; i >= 0; i--)
 220   
         {
 221  17545
             Rule r = (Rule) rules.get(i);
 222   
 
 223  17545
             r.end(_processor, element);
 224   
 
 225   
         }
 226   
     }
 227   
 
 228   
     private Translator _nullTranslator = new NullTranslator();
 229   
     private Translator _contentTranslator;
 230   
 
 231  15
     public Translator getContentTranslator()
 232   
     {
 233  15
         if (_contentTranslator == null)
 234  10
             _contentTranslator = getTranslator(_model.getContentTranslator());
 235   
 
 236  15
         return _contentTranslator;
 237   
     }
 238   
 
 239  5377
     private Translator getTranslator(String translator)
 240   
     {
 241  5377
         if (translator == null)
 242  4
             return _nullTranslator;
 243   
 
 244  5373
         return _processor.getTranslator(translator);
 245   
     }
 246   
 
 247  5367
     public Translator getAttributeTranslator(String attributeName)
 248   
     {
 249  5367
         String translator = (String) _attributeTranslators.get(attributeName);
 250   
 
 251  5367
         return getTranslator(translator);
 252   
     }
 253   
 }
 254