/**
   * Return all matching properties from provided root attribute and xPath.
   *
   * @param root The root attribute to start searching from
   * @param xpath The xPath matching the attribute
   * @return The matching attributes collection
   */
  private Collection<Property> getProperties(ComplexAttribute root, StepList xpath) {

    final StepList steps = new StepList(xpath);

    Iterator<Step> stepsIterator = steps.iterator();
    Collection<Property> properties = null;
    Step step = null;
    if (stepsIterator.hasNext()) {
      step = stepsIterator.next();
      properties = ((ComplexAttribute) root).getProperties(Types.toTypeName(step.getName()));
    }

    while (stepsIterator.hasNext()) {
      step = stepsIterator.next();
      Collection<Property> nestedProperties = new ArrayList<Property>();
      for (Property property : properties) {
        assert property instanceof ComplexAttribute;
        Collection<Property> tempProperties =
            ((ComplexAttribute) property).getProperties(Types.toTypeName(step.getName()));
        if (!tempProperties.isEmpty()) {
          nestedProperties.addAll(tempProperties);
        }
      }
      properties.clear();
      if (nestedProperties.isEmpty()) {
        return properties;
      }
      properties.addAll(nestedProperties);
    }
    return properties;
  }
  /**
   * Returns first matching attribute from provided root and xPath.
   *
   * @param root The root attribute to start searching from
   * @param xpath The xPath matching the attribute
   * @return The first matching attribute
   */
  private Property getProperty(Attribute root, StepList xpath) {
    Property property = root;

    final StepList steps = new StepList(xpath);

    Iterator<Step> stepsIterator = steps.iterator();

    while (stepsIterator.hasNext()) {
      assert property instanceof ComplexAttribute;
      Step step = stepsIterator.next();
      property = ((ComplexAttribute) property).getProperty(Types.toTypeName(step.getName()));
      if (property == null) {
        return null;
      }
    }
    return property;
  }