2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

Clover coverage report - Code Coverage for hivemind release 1.2.1
Coverage timestamp: Fri Feb 10 2006 16:33:43 PST
file stats: LOC: 278   Methods: 11
NCLOC: 167   Classes: 1
 
 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  10452 SchemaElement(SchemaProcessor processor, ElementModel model)
 69    {
 70  10452 _processor = processor;
 71  10452 _model = model;
 72  10452 _keyAttribute = model.getKeyAttribute();
 73   
 74  10452 List attributeModels = model.getAttributeModels();
 75  10452 int count = attributeModels.size();
 76   
 77  10452 for (int i = 0; i < count; i++)
 78    {
 79  10792 AttributeModel am = (AttributeModel) attributeModels.get(i);
 80   
 81  10792 String name = am.getName();
 82   
 83  10792 _knownAttributes.add(name);
 84   
 85  10792 if (am.isRequired())
 86  5848 _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  10792 if (am.isUnique())
 92  126 _attributeValues.put(name, new HashMap());
 93   
 94  10792 if (name.equals(_keyAttribute))
 95    {
 96  124 _requiredAttributes.add(name);
 97  124 _attributeValues.put(name, new HashMap());
 98    }
 99   
 100  10792 _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  474 SchemaElement getNestedElement(String elementName)
 108    {
 109  474 if (_nestedElements == null)
 110  452 buildNestedElements();
 111   
 112  474 return (SchemaElement) _nestedElements.get(elementName);
 113    }
 114   
 115  452 private void buildNestedElements()
 116    {
 117  452 _nestedElements = new HashMap();
 118   
 119  452 List l = _model.getElementModel();
 120  452 int count = l.size();
 121   
 122  452 for (int i = 0; i < count; i++)
 123    {
 124  9414 ElementModel nested = (ElementModel) l.get(i);
 125   
 126  9414 SchemaElement nestedElement = new SchemaElement(_processor, nested);
 127   
 128    // TODO: Check for duplicates here, or at parse!
 129   
 130  9414 _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  3720 void validateAttributes(Element element)
 140    {
 141  3720 List l = element.getAttributes();
 142  3720 int count = l.size();
 143  3720 Set required = new HashSet(_requiredAttributes);
 144  3720 List errors = new ArrayList();
 145   
 146  3720 for (int i = 0; i < count; i++)
 147    {
 148  6708 Attribute a = (Attribute) l.get(i);
 149  6708 String name = a.getName();
 150   
 151  6708 if (!_knownAttributes.contains(name))
 152  1 errors.add(ImplMessages.unknownAttribute(name));
 153   
 154  6708 checkUniquness(name, a.getValue(), element.getLocation(), errors);
 155   
 156  6708 required.remove(name);
 157    }
 158   
 159  3720 Iterator it = required.iterator();
 160   
 161  3720 while (it.hasNext())
 162    {
 163  1 String name = (String) it.next();
 164  1 errors.add(ImplMessages.missingAttribute(name));
 165    }
 166   
 167  3720 count = errors.size();
 168   
 169  3720 if (count == 0)
 170  3718 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  6708 private void checkUniquness(String name, String value, Location location, List errors)
 189    {
 190  6708 Map valuesMap = (Map) _attributeValues.get(name);
 191   
 192    // If null, then not checking on uniqueness.
 193   
 194  6708 if (valuesMap == null)
 195  5599 return;
 196   
 197  1109 Object translatedValue = getAttributeTranslator(name).translate(
 198    _processor.getContributingModule(),
 199    Object.class,
 200    value,
 201    location);
 202   
 203  1109 Location prior = (Location) valuesMap.get(translatedValue);
 204   
 205  1109 if (prior == null)
 206    {
 207  1108 valuesMap.put(translatedValue, location);
 208  1108 return;
 209    }
 210   
 211    // A conflict.
 212   
 213  1 errors.add(ImplMessages.uniqueAttributeConstraintBroken(
 214    name,
 215    translatedValue.toString(),
 216    prior));
 217    }
 218   
 219  3718 void fireBegin(Element element)
 220    {
 221  3718 List rules = _model.getRules();
 222  3718 int count = rules.size();
 223   
 224  3718 for (int i = 0; i < count; i++)
 225    {
 226  16918 Rule r = (Rule) rules.get(i);
 227   
 228  16918 r.begin(_processor, element);
 229   
 230    }
 231    }
 232   
 233  3717 void fireEnd(Element element)
 234    {
 235  3717 List rules = _model.getRules();
 236  3717 int count = rules.size();
 237   
 238  3717 for (int i = count - 1; i >= 0; i--)
 239    {
 240  16914 Rule r = (Rule) rules.get(i);
 241   
 242  16914 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  8312 private Translator getTranslator(String translator)
 260    {
 261  8312 if (translator == null)
 262  14 return _nullTranslator;
 263   
 264  8298 return _processor.getTranslator(translator);
 265    }
 266   
 267  8296 public Translator getAttributeTranslator(String attributeName)
 268    {
 269  8296 String translator = (String) _attributeTranslators.get(attributeName);
 270   
 271  8296 return getTranslator(translator);
 272    }
 273   
 274  613 public String getKeyAttribute()
 275    {
 276  613 return _keyAttribute;
 277    }
 278    }