text: //=========================================================================
  //  Copyright (c) Kitware, Inc.
  //  All rights reserved.
  //  See LICENSE.txt for details.
  //
  //  This software is distributed WITHOUT ANY WARRANTY; without even
  //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  //  PURPOSE.  See the above copyright notice for more information.
  //=========================================================================
  
  
  #include "smtk/io/XmlDocV1Parser.h"
  
  #define PUGIXML_HEADER_ONLY
  #include "pugixml/src/pugixml.cpp"
  
  #include "smtk/attribute/RefItemDefinition.h"
  #include "smtk/attribute/Attribute.h"
  #include "smtk/attribute/Definition.h"
  #include "smtk/attribute/DoubleItem.h"
  #include "smtk/attribute/DoubleItemDefinition.h"
  #include "smtk/attribute/DirectoryItem.h"
  #include "smtk/attribute/DirectoryItemDefinition.h"
  #include "smtk/attribute/FileItem.h"
  #include "smtk/attribute/FileItemDefinition.h"
  #include "smtk/attribute/GroupItem.h"
  #include "smtk/attribute/GroupItemDefinition.h"
  #include "smtk/attribute/IntItem.h"
  #include "smtk/attribute/IntItemDefinition.h"
  #include "smtk/attribute/Item.h"
  #include "smtk/attribute/ItemDefinition.h"
  #include "smtk/attribute/System.h"
  #include "smtk/attribute/StringItem.h"
  #include "smtk/attribute/StringItemDefinition.h"
  #include "smtk/attribute/MeshItem.h"
  #include "smtk/attribute/MeshItemDefinition.h"
  #include "smtk/attribute/MeshSelectionItem.h"
  #include "smtk/attribute/MeshSelectionItemDefinition.h"
  #include "smtk/attribute/ModelEntityItem.h"
  #include "smtk/attribute/ModelEntityItemDefinition.h"
  #include "smtk/attribute/ValueItem.h"
  #include "smtk/attribute/ValueItemDefinition.h"
  #include "smtk/attribute/VoidItem.h"
  #include "smtk/attribute/VoidItemDefinition.h"
  
  #include "smtk/model/EntityRef.h"
  #include "smtk/model/Entity.h"
  #include "smtk/model/EntityTypeBits.h"
  #include "smtk/model/Manager.h"
  
  #include "smtk/common/StringUtil.h"
  #include "smtk/common/View.h"
  
  #include <iostream>
  #include <algorithm>
  
  using namespace pugi;
  using namespace smtk::io;
  using namespace smtk::common;
  using namespace smtk;
  
  // Some helper functions
  namespace {
  
    int getValueFromXMLElement(xml_node &node, int)
    {
      return node.text().as_int();
    }
  
  //----------------------------------------------------------------------------
    double getValueFromXMLElement(xml_node &node, double)
    {
      return node.text().as_double();
    }
  
  //----------------------------------------------------------------------------
    const char *getValueFromXMLElement(xml_node &node, std::string)
    {
      return node.text().get();
    }
  
  //----------------------------------------------------------------------------
    std::vector<int> getValueFromXMLElement(xml_node &node, const std::string& sep, std::vector<int>)
    {
      std::vector<int> result;
      std::vector<std::string> vals;
      std::stringstream convert;
      int val;
      vals = smtk::common::StringUtil::split(node.text().get(), sep, false, true);
      std::vector<std::string>::iterator it;
      for (it = vals.begin(); it != vals.end(); ++it)
        {
        convert.str(*it);
        convert >> val;
        result.push_back(val);
        convert.clear();
        }
      return result;
    }
  
  //----------------------------------------------------------------------------
    std::vector<double> getValueFromXMLElement(xml_node &node, const std::string& sep, std::vector<double>)
    {
      std::vector<double> result;
      std::vector<std::string> vals;
      std::stringstream convert;
      double val;
      vals = smtk::common::StringUtil::split(node.text().get(), sep, false, true);
      std::vector<std::string>::iterator it;
      for (it = vals.begin(); it != vals.end(); ++it)
        {
        convert.str(*it);
        convert >> val;
        result.push_back(val);
        convert.clear();
        }
      return result;
    }
  
  //----------------------------------------------------------------------------
    std::vector<std::string> getValueFromXMLElement(xml_node &node, const std::string& sep, std::vector<std::string>)
    {
      std::vector<std::string> vals;
      vals = smtk::common::StringUtil::split(node.text().get(), sep, false, false);
      return vals;
    }
  
  //----------------------------------------------------------------------------
    template<typename ItemDefType, typename BasicType>
    void processDerivedValueDef(pugi::xml_node &node,
                                ItemDefType idef, Logger &logger)
    {
      xml_node dnode, child, rnode;
      xml_attribute xatt;
      // Is the item discrete?
      dnode = node.child("DiscreteInfo");
      if (dnode)
        {
        BasicType val;
        int i;
        xml_node vnode;
        std::string cname;
        for (child = dnode.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          cname = child.name();
          if ( cname == "Structure")
            {
            vnode = child.child("Value");
            }
          else if (cname == "Value")
            {
            vnode = child;
            }
          else
            {
            continue; // XML Element I don't care about
            }
          if (!vnode)
            {
            smtkErrorMacro(logger,
                           "Missing XML Node \"Value\" in DiscreteInfo section of Item Definition : "
                           << idef->name());
            continue;
            }
  
          xatt = vnode.attribute("Enum");
          val = getValueFromXMLElement(vnode, BasicType());
          if (xatt)
            {
            idef->addDiscreteValue(val, xatt.value());
            }
          else
            {
            idef->addDiscreteValue(val);
            }
          if (cname != "Structure")
            {
            continue;
            }
          // Ok lets read in the items associated with this value
          // First grab the associated enum
          std::string v = idef->discreteEnum(i);
          xml_node inode, items = child.child("Items");
          if (!items)
            {
            continue;
            }
          for (inode = items.child("Item"); inode; inode = inode.next_sibling("Item"))
            {
            std::string iname = inode.text().get();
            idef->addConditionalItem(v, iname);
            }
          }
        xatt = dnode.attribute("DefaultIndex");
        if (xatt)
          {
          idef->setDefaultDiscreteIndex(xatt.as_int());
          }
        return;
        }
      // Does this def have a default value
      dnode = node.child("DefaultValue");
      if (dnode)
        {
        xatt = dnode.attribute("Sep");
        std::string sep = xatt ? xatt.value() : ",";
        std::vector<BasicType> defs = getValueFromXMLElement(dnode, sep, std::vector<BasicType>());
        if (defs.size() == 1 || defs.size() == idef->numberOfRequiredValues())
          {
          idef->setDefaultValue(defs);
          }
        else
          {
          smtkErrorMacro(logger,
            "XML DefaultValue has incorrect size: " << defs.size()
            << " for item " << idef->type());
          }
        }
      // Does this node have a range?
      rnode = node.child("RangeInfo");
      if (rnode)
        {
        bool inclusive;
        child = rnode.child("Min");
        if (child)
          {
          xatt = child.attribute("Inclusive");
          if (xatt)
            {
            inclusive = xatt.as_bool();
            }
          else
            {
            inclusive = false;
            }
          idef->setMinRange(getValueFromXMLElement(child, BasicType()), inclusive);
          }
  
        child = rnode.child("Max");
        if (child)
          {
          xatt = child.attribute("Inclusive");
          if (xatt)
            {
            inclusive = xatt.as_bool();
            }
          else
            {
            inclusive = false;
            }
          idef->setMaxRange(getValueFromXMLElement(child, BasicType()), inclusive);
          }
        }
    }
  //----------------------------------------------------------------------------
    template<typename ItemType, typename BasicType>
    void processDerivedValue(pugi::xml_node &node,
                             ItemType item, attribute::System &asys,
                             std::vector<ItemExpressionInfo> &itemExpressionInfo,
                             Logger &logger)
    {
      if (item->isDiscrete())
        {
        return; // nothing left to do
        }
  
      xml_attribute xatt;
      xml_node valsNode;
      std::size_t i, n = item->numberOfValues();
      xml_node val, noVal;
      std::size_t  numRequiredVals = item->numberOfRequiredValues();
      std::string nodeName, expName;
      attribute::AttributePtr expAtt;
      bool allowsExpressions = item->allowsExpressions();
      ItemExpressionInfo info;
      if (item->isExtensible())
        {
        // The node should have an attribute indicating how many values are
        // associated with the item
        xatt = node.attribute("NumberOfValues");
        if (!xatt)
          {
          smtkErrorMacro(logger,
                         "XML Attribute NumberOfValues is missing for Item: "
                         << item->name());
          return;
          }
        n = xatt.as_uint();
        item->setNumberOfValues(n);
        }
  
      if (!n)
        {
        return;
        }
      valsNode = node.child("Values");
      if (valsNode)
        {
        for (val = valsNode.first_child(); val; val = val.next_sibling())
          {
          nodeName = val.name();
          if (nodeName == "UnsetVal")
            {
            continue;
            }
          xatt = val.attribute("Ith");
          if (!xatt)
            {
            smtkErrorMacro(logger,
                           "XML Attribute Ith is missing for Item: " << item->name());
            continue;
            }
          i = xatt.as_uint();
          if (i >= n)
            {
            smtkErrorMacro(logger, "XML Attribute Ith = " << i
                           << " is out of range for Item: " << item->name());
            continue;
            }
          if (nodeName == "Val")
            {
            item->setValue(static_cast<int>(i), getValueFromXMLElement(val, BasicType()));
            }
          else if (allowsExpressions && (nodeName == "Expression"))
            {
            expName = val.text().get();
            expAtt = asys.findAttribute(expName);
            if (!expAtt)
              {
              info.item = item; info.pos = static_cast<int>(i); info.expName = expName;
              itemExpressionInfo.push_back(info);
              }
            else
              {
              item->setExpression(static_cast<int>(i), expAtt);
              }
            }
          else
            {
            smtkErrorMacro(logger, "Unsupported Value Node Type  Item: "
                           << item->name());
            }
          }
        }
      else if ((numRequiredVals == 1) && !item->isExtensible())
        {
        // Lets see if there is an unset val element
        noVal = node.child("UnsetVal");
        if (!noVal)
          {
          // Is this an exapression?
          xatt = node.attribute("Expression");
          if (allowsExpressions && xatt)
            {
            expName = node.text().get();
            expAtt = asys.findAttribute(expName);
            if (!expAtt)
              {
              info.item = item; info.pos = 0; info.expName = expName;
              itemExpressionInfo.push_back(info);
              }
            else
              {
              item->setExpression(expAtt);
              }
            }
          else
            {
            item->setValue(getValueFromXMLElement(node, BasicType()));
            }
          }
        }
      else
        {
        smtkErrorMacro(logger, "XML Node Values is missing for Item: " << item->name());
        }
    }
  };
  //----------------------------------------------------------------------------
  XmlDocV1Parser::XmlDocV1Parser(smtk::attribute::System &mySystem):
    m_reportAsError(true), m_system(mySystem)
  {
  }
  
  //----------------------------------------------------------------------------
  XmlDocV1Parser::~XmlDocV1Parser()
  {
  }
  //----------------------------------------------------------------------------
  xml_node XmlDocV1Parser::getRootNode(xml_document &doc)
  {
    xml_node amnode = doc.child("SMTK_AttributeManager");
    return amnode;
  }
  
  //----------------------------------------------------------------------------
  bool XmlDocV1Parser::canParse(xml_document &doc)
  {
    // Get the attribute system node
    xml_node amnode = doc.child("SMTK_AttributeManager");
    if (amnode.empty())
      {
      return false;
      }
  
    pugi::xml_attribute xatt = amnode.attribute("Version");
    if (!xatt)
      {
      return false;
      }
  
    int versionNum = xatt.as_int();
    if (versionNum != 1)
      {
      return false;
      }
  
    return true;
  }
  
  //----------------------------------------------------------------------------
  bool XmlDocV1Parser::canParse(xml_node &node)
  {
    // Check the name of the node
    std::string name = node.name();
    if (name != "SMTK_AttributeManager")
      {
      return false;
      }
  
    pugi::xml_attribute xatt = node.attribute("Version");
    if (!xatt)
      {
      return false;
      }
  
    int versionNum = xatt.as_int();
    if (versionNum != 1)
      {
      return false;
      }
  
    return true;
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::process(xml_document &doc)
  {
    // Get the attribute system node
    xml_node amnode = doc.child("SMTK_AttributeManager");
  
    // Check that there is content
    if (amnode.empty())
      {
      smtkWarningMacro(m_logger, "Missing SMTK_AttributeManager element");
      return;
      }
  
    this->process(amnode);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::process(xml_node &amnode)
  {
    // Reset the message log
    this->m_logger.reset();
    // Clear the vectors for dealing with attribute references
    this->m_itemExpressionDefInfo.clear();
    this->m_attRefDefInfo.clear();
    this->m_itemExpressionInfo.clear();
    this->m_attRefInfo.clear();
    this->m_logger.reset();
    xml_node node, cnode;
  
    // Get the category information, starting with current set
    std::set<std::string> secCatagories = m_system.categories();
    std::string s;
    node = amnode.child("Categories");
    if (node)
      {
      // Get the default category if one is specified
      s = node.attribute("Default").value();
      if (s != "")
        {
        this->m_defaultCategory = s;
        secCatagories.insert(s.c_str());
        }
      for (cnode = node.first_child(); cnode; cnode = cnode.next_sibling())
        {
        if (cnode.text().empty())
          {
          continue;
          }
        secCatagories.insert(cnode.text().get());
        }
      }
  
    // Process Analysis Info
    std::set<std::string> catagories;
    node = amnode.child("Analyses");
    if (node)
      {
      xml_node anode;
      for (anode = node.first_child(); anode; anode = anode.next_sibling())
        {
        s = anode.attribute("Type").value();
        catagories.clear();
        for (cnode = anode.first_child(); cnode; cnode = cnode.next_sibling())
          {
          if (cnode.text().empty())
            {
            continue;
            }
          catagories.insert(cnode.text().get());
          }
        this->m_system.defineAnalysis(s, catagories);
        }
      }
  
    // Process AdvanceLevel Info
    node = amnode.child("AdvanceLevels");
    if (node)
      {
      xml_node anode;
      for (anode = node.first_child(); anode; anode = anode.next_sibling())
        {
        s = anode.attribute("Label").value();
        int val = anode.text().as_int();
        if(s.empty())
          {
          std::stringstream tmp;
          tmp << "Level " << val;
          s = tmp.str();
          }
        this->m_system.addAdvanceLevel(val, s);
  
        xml_attribute xatt = anode.attribute("Color");
        if(xatt)
          {
          double color[4];
          s = xatt.value();
          if(!s.empty() && this->decodeColorInfo(s, color) == 0)
            {
            this->m_system.setAdvanceLevelColor(val, color);
            }
          }
        }
      }
  
    this->processAttributeInformation(amnode);
    this->processViews(amnode);
    this->processModelInfo(amnode);
  
    // Now we need to check to see if there are any catagories in the system
    // that were not explicitly listed in the catagories section - first update catagories
    this->m_system.updateCategories();
  
    std::set<std::string>::const_iterator it;
    const std::set<std::string> &cats = this->m_system.categories();
    for (it = cats.begin(); it != cats.end(); it++)
      {
      if (secCatagories.find(*it) == secCatagories.end())
        {
        smtkErrorMacro(this->m_logger, "Category: " << *it
                       << " was not listed in System's Category Section");
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processAttributeInformation(xml_node &root)
  {
    // Process definitions first
    xml_node child, node = root.child("Definitions");
    std::size_t i;
    if (node)
      {
      for (child = node.first_child(); child; child = child.next_sibling())
        {
        this->processDefinition(child);
        }
  
      // At this point we have all the definitions read in so lets
      // fix up all of the attribute definition references
      attribute::DefinitionPtr def;
      for (i = 0; i < this->m_itemExpressionDefInfo.size(); i++)
        {
        def = this->m_system.findDefinition(this->m_itemExpressionDefInfo[i].second);
        if (def)
          {
          this->m_itemExpressionDefInfo[i].first->setExpressionDefinition(def);
          }
        else
          {
          smtkErrorMacro(this->m_logger,
                         "Referenced Attribute Definition: "
                         << this->m_itemExpressionDefInfo[i].second
                         << " is missing and required by Item Definition: "
                         << this->m_itemExpressionDefInfo[i].first->name());
          }
        }
  
      for (i = 0; i < this->m_attRefDefInfo.size(); i++)
        {
        def = this->m_system.findDefinition(this->m_attRefDefInfo[i].second);
        if (def)
          {
          this->m_attRefDefInfo[i].first->setAttributeDefinition(def);
          }
        else
          {
          smtkErrorMacro(this->m_logger,
                         "Referenced Attribute Definition: "
                         << this->m_attRefDefInfo[i].second
                         << " is missing and required by Item Definition: "
                         << this->m_attRefDefInfo[i].first->name());
          }
        }
      }
    node = root.child("Attributes");
    if (!node)
      {
      return;
      }
  
    for (child = node.first_child(); child; child = child.next_sibling())
      {
      this->processAttribute(child);
      }
  
    // At this point we have all the attributes read in so lets
    // fix up all of the attribute  references
    attribute::AttributePtr att;
    for (i = 0; i < this->m_itemExpressionInfo.size(); i++)
      {
      att = this->m_system.findAttribute(this->m_itemExpressionInfo[i].expName);
      if (att)
        {
        this->m_itemExpressionInfo[i].
          item->setExpression(m_itemExpressionInfo[i].pos, att);
        }
      else
        {
        smtkErrorMacro(this->m_logger,
                       "Expression Attribute: "
                       << this->m_itemExpressionInfo[i].expName
                       << " is missing and required by Item : "
                       << this->m_itemExpressionInfo[i].item->name());
        }
      }
  
    for (i = 0; i < this->m_attRefInfo.size(); i++)
      {
      att = this->m_system.findAttribute(this->m_attRefInfo[i].attName);
      if (att)
        {
        this->m_attRefInfo[i].item->setValue(this->m_attRefInfo[i].pos, att);
        }
      else
        {
        smtkErrorMacro(this->m_logger,
                       "Referenced Attribute: "
                       << this->m_attRefInfo[i].attName
                       << " is missing and required by Item: "
                       << this->m_attRefInfo[i].item->name());
        }
      }
  
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processDefinition(xml_node &defNode)
  {
    xml_node node;
    attribute::DefinitionPtr def, baseDef;
    xml_attribute xatt;
    std::string type, baseType;
    xatt = defNode.attribute("Type");
    if (xatt)
      {
      type = xatt.value();
      }
    else
      {
      smtkErrorMacro(this->m_logger, "Definition missing Type XML Attribute");
      return;
      }
    baseType = defNode.attribute("BaseType").value();
    if (baseType != "")
      {
      baseDef = this->m_system.findDefinition(baseType);
      if (!baseDef)
        {
        smtkErrorMacro(this->m_logger, "Could not find Base Definition: "
                       << baseType << " needed to create Definition: "
                       << type);
        return;
        }
      def = this->m_system.createDefinition(type, baseDef);
      }
    else
      {
      def = this->m_system.createDefinition(type);
      }
    if (!def)
      {
      if (m_reportAsError)
        {
        smtkErrorMacro(this->m_logger, "Definition: "
                       << type << " already exists in the System");
        }
      else
        {
        smtkWarningMacro(this->m_logger, "Definition: "
                         << type << " already exists in the System");
        }
      return;
      }
    xatt = defNode.attribute("Label");
    if (xatt)
      {
      def->setLabel(xatt.value());
      }
    xatt = defNode.attribute("Version");
    if (xatt)
      {
      def->setVersion(xatt.as_int());
      }
  
    xatt = defNode.attribute("Abstract");
    if (xatt)
      {
      def->setIsAbstract(xatt.as_bool());
      }
  
    xatt = defNode.attribute("AdvanceLevel");
    if (xatt)
      {
      def->setAdvanceLevel(xatt.as_int());
      }
  
    xatt = defNode.attribute("Unique");
    if (xatt)
      {
      def->setIsUnique(xatt.as_bool());
      }
  
    xatt = defNode.attribute("Nodal");
    if (xatt)
      {
      def->setIsNodal(xatt.as_bool());
      }
  
    // Read old-style association mask first.
    // It will be overwritten if a new-style AssociationsDef
    // is also provided.
    xatt = defNode.attribute("Associations");
    if (xatt)
      {
      model::BitFlags mask =
        this->decodeModelEntityMask(xatt.value());
      def->setAssociationMask(mask);
      }
  
    double color[4];
  
    node = defNode.child("NotApplicableColor");
    if (node && this->getColor(node, color, "NotApplicableColor"))
      {
      def->setNotApplicableColor(color);
      }
  
    node = defNode.child("DefaultColor");
    if (node && this->getColor(node, color, "DefaultColor"))
      {
      def->setDefaultColor(color);
      }
  
    node = defNode.child("BriefDescription");
    if (node)
      {
      def->setBriefDescription(node.text().get());
      }
  
    node = defNode.child("DetailedDescription");
    if (node)
      {
      def->setDetailedDescription(node.text().get());
      }
  
    // See if we allow any associations
    node = defNode.child("AssociationsDef");
    if (node)
      {
      std::string assocName = node.attribute("Name").value();
      if (assocName.empty())
        assocName = def->type() + "Associations";
      smtk::attribute::ModelEntityItemDefinitionPtr assocDef =
        smtk::dynamic_pointer_cast<smtk::attribute::ModelEntityItemDefinition>(
          smtk::attribute::ModelEntityItemDefinition::New(assocName));
      this->processModelEntityDef(node, assocDef);
      def->setAssociationRule(assocDef);
      }
  
    // Now lets process its items
    xml_node itemsNode = defNode.child("ItemDefinitions");
    std::string itemName;
    smtk::attribute::Item::Type itype;
    smtk::attribute::ItemDefinitionPtr idef;
    for (node = itemsNode.first_child(); node; node = node.next_sibling())
      {
      itype = smtk::attribute::Item::string2Type(node.name());
      itemName = node.attribute("Name").value();
      switch (itype)
        {
        case smtk::attribute::Item::ATTRIBUTE_REF:
          idef = def->addItemDefinition<smtk::attribute::RefItemDefinition>(itemName);
          this->processRefDef(node, smtk::dynamic_pointer_cast<smtk::attribute::RefItemDefinition>(idef));
          break;
        case smtk::attribute::Item::DOUBLE:
          idef = def->addItemDefinition<smtk::attribute::DoubleItemDefinition>(itemName);
          this->processDoubleDef(node, smtk::dynamic_pointer_cast<smtk::attribute::DoubleItemDefinition>(idef));
          break;
        case smtk::attribute::Item::DIRECTORY:
          idef = def->addItemDefinition<smtk::attribute::DirectoryItemDefinition>(itemName);
          this->processDirectoryDef(node, smtk::dynamic_pointer_cast<smtk::attribute::DirectoryItemDefinition>(idef));
          break;
        case smtk::attribute::Item::FILE:
          idef = def->addItemDefinition<smtk::attribute::FileItemDefinition>(itemName);
          this->processFileDef(node, smtk::dynamic_pointer_cast<smtk::attribute::FileItemDefinition>(idef));
          break;
        case smtk::attribute::Item::GROUP:
          idef = def->addItemDefinition<smtk::attribute::GroupItemDefinition>(itemName);
          this->processGroupDef(node, smtk::dynamic_pointer_cast<smtk::attribute::GroupItemDefinition>(idef));
          break;
        case smtk::attribute::Item::INT:
          idef = def->addItemDefinition<smtk::attribute::IntItemDefinition>(itemName);
          this->processIntDef(node, smtk::dynamic_pointer_cast<smtk::attribute::IntItemDefinition>(idef));
          break;
        case smtk::attribute::Item::STRING:
          idef = def->addItemDefinition<smtk::attribute::StringItemDefinition>(itemName);
          this->processStringDef(node, smtk::dynamic_pointer_cast<smtk::attribute::StringItemDefinition>(idef));
          break;
        case smtk::attribute::Item::MODEL_ENTITY:
          idef = def->addItemDefinition<smtk::attribute::ModelEntityItemDefinition>(itemName);
          this->processModelEntityDef(node, smtk::dynamic_pointer_cast<smtk::attribute::ModelEntityItemDefinition>(idef));
          break;
        case smtk::attribute::Item::VOID:
          idef = def->addItemDefinition<smtk::attribute::VoidItemDefinition>(itemName);
          this->processItemDef(node, idef);
        break;
        case smtk::attribute::Item::MESH_SELECTION:
          idef = def->addItemDefinition<smtk::attribute::MeshSelectionItemDefinition>(itemName);
          this->processMeshSelectionDef(node, smtk::dynamic_pointer_cast<smtk::attribute::MeshSelectionItemDefinition>(idef));
          break;
        case smtk::attribute::Item::MESH_ENTITY:
          idef = def->addItemDefinition<smtk::attribute::MeshItemDefinition>(itemName);
          this->processMeshEntityDef(node, smtk::dynamic_pointer_cast<smtk::attribute::MeshItemDefinition>(idef));
          break;
      default:
        smtkErrorMacro(this->m_logger, "Unsupported Item definition Type: "
                       << node.name()
                       << " needed to create Definition: " << type);
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processItemDef(xml_node &node,
                                      smtk::attribute::ItemDefinitionPtr idef)
  {
    xml_attribute xatt;
    xml_node catNodes, child;
    xatt = node.attribute("Label");
    if (xatt)
      {
      idef->setLabel(xatt.value());
      }
    xatt = node.attribute("Version");
    if (xatt)
      {
      idef->setVersion(xatt.as_int());
      }
    xatt = node.attribute("Optional");
    if (xatt)
      {
      idef->setIsOptional(xatt.as_bool());
      idef->setIsEnabledByDefault(node.attribute("IsEnabledByDefault").as_bool());
      }
    // If using AdvanceLevel then we are setting
    // both read and write
    xatt = node.attribute("AdvanceLevel");
    if (xatt)
      {
      idef->setAdvanceLevel(0, xatt.as_int());
      idef->setAdvanceLevel(1, xatt.as_int());
      }
    else
      {
      xatt = node.attribute("AdvanceReadLevel");
      if (xatt)
        {
        idef->setAdvanceLevel(0, xatt.as_int());
        }
      xatt = node.attribute("AdvanceWriteLevel");
      if (xatt)
        {
        idef->setAdvanceLevel(1, xatt.as_int());
        }
      }
  
    child = node.child("BriefDescription");
    if (child)
      {
      idef->setBriefDescription(child.text().get());
      }
  
    child = node.child("DetailedDescription");
    if (child)
      {
      idef->setDetailedDescription(child.text().get());
      }
  
    catNodes = node.child("Categories");
    if (catNodes)
      {
      for (child = catNodes.first_child(); child; child = child.next_sibling())
        {
        idef->addCategory(child.text().get());
        }
      }
    else if (this->m_defaultCategory != "" &&
             !smtk::dynamic_pointer_cast<attribute::GroupItemDefinition>(idef))
      { // group item definitions don't get categories
      idef->addCategory(this->m_defaultCategory.c_str());
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processDoubleDef(pugi::xml_node &node,
                                           attribute::DoubleItemDefinitionPtr idef)
  {
    // First process the common value item def stuff
    this->processValueDef(node, idef);
    processDerivedValueDef<attribute::DoubleItemDefinitionPtr, double>
      (node, idef, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processIntDef(pugi::xml_node &node,
                                        attribute::IntItemDefinitionPtr idef)
  {
    // First process the common value item def stuff
    this->processValueDef(node, idef);
    processDerivedValueDef<attribute::IntItemDefinitionPtr, int>
      (node, idef, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processStringDef(pugi::xml_node &node,
                                           attribute::StringItemDefinitionPtr idef)
  {
    // First process the common value item def stuff
    this->processValueDef(node, idef);
    if( xml_attribute xatt = node.attribute("MultipleLines") )
      {
      (void)xatt;
      idef->setIsMultiline(true);
      }
    processDerivedValueDef<attribute::StringItemDefinitionPtr, std::string>
      (node, idef, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processModelEntityDef(pugi::xml_node &node,
                                           attribute::ModelEntityItemDefinitionPtr idef)
  {
    xml_node labels, mmask, child;
    xml_attribute xatt;
    int i;
    this->processItemDef(node, idef);
  
    mmask = node.child("MembershipMask");
    if (mmask)
      {
      idef->setMembershipMask(
        this->decodeModelEntityMask(
          mmask.text().as_string()));
      }
  
    xatt = node.attribute("NumberOfRequiredValues");
    if (xatt)
      {
      idef->setNumberOfRequiredValues(xatt.as_int());
      }
    else
      {
      smtkErrorMacro(this->m_logger,
                     "Missing XML Attribute NumberOfRequiredValues for Item Definition : "
                     << idef->name());
      }
  
    xatt = node.attribute("Extensible");
    if (xatt)
      {
      idef->setIsExtensible(xatt.as_bool());
      xatt = node.attribute("MaxNumberOfValues");
      if (xatt)
        {
        idef->setMaxNumberOfValues(xatt.as_uint());
        }
      }
  
    // Lets see if there are labels
    if(node.child("Labels"))
      {
      smtkErrorMacro(this->m_logger,
                     "Labels has been changed to ComponentLabels : "
                     << idef->name());
      }
    labels = node.child("ComponentLabels");
    if (labels)
      {
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        idef->setCommonValueLabel(xatt.value());
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          idef->setValueLabel(i, child.value());
          }
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processMeshSelectionDef(pugi::xml_node &node,
                                           attribute::MeshSelectionItemDefinitionPtr idef)
  {
    (void)node;
    smtkWarningMacro(this->m_logger,
                   "The Mesh Selection defs should only be availabe starting Attribute Version 2 Format"
                   << idef->name());
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processMeshEntityDef(pugi::xml_node &node,
                                           attribute::MeshItemDefinitionPtr idef)
  {
    (void)node;
    smtkWarningMacro(this->m_logger,
                   "The Mesh Entity defs should only be availabe starting Attribute Version 2 Format"
                   << idef->name());
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processValueDef(pugi::xml_node &node,
                                          attribute::ValueItemDefinitionPtr idef)
  {
    xml_node labels, child;
    xml_attribute xatt;
    std::size_t i;
    this->processItemDef(node, idef);
  
    xatt = node.attribute("NumberOfRequiredValues");
    std::size_t numberOfComponents = 0;
    if (xatt)
      {
      numberOfComponents = xatt.as_uint();
      idef->setNumberOfRequiredValues(numberOfComponents);
      }
  
    xatt = node.attribute("Extensible");
    if (xatt)
      {
      idef->setIsExtensible(xatt.as_bool());
      xatt = node.attribute("MaxNumberOfValues");
      if (xatt)
        {
        idef->setMaxNumberOfValues(xatt.as_uint());
        }
      }
  
    // Lets see if there are labels
    if(node.child("Labels"))
      {
      smtkErrorMacro(this->m_logger,
                     "Labels has been changed to ComponentLabels : "
                     << idef->name());
      }
    labels = node.child("ComponentLabels");
    if (labels)
      {
      if((numberOfComponents == 1) && !idef->isExtensible())
        {
        smtkErrorMacro(this->m_logger,
                       "Should not use Labels when NumberOfRequiredValues=1 : "
                       << idef->name());
        }
  
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        idef->setCommonValueLabel(xatt.value());
        if(labels.first_child())
          {
          smtkErrorMacro(this->m_logger,
                         "Cannot combine CommonLabel with Label child nodes : "
                         << idef->name());
          }
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          if(i<numberOfComponents)
            {
            idef->setValueLabel(i, child.text().get());
            }
          }
        if(i!=numberOfComponents)
          {
          smtkErrorMacro(this->m_logger,
                         "Wrong number of component values for : "
                         << idef->name());
          }
        }
      }
    child = node.child("ExpressionType");
    if (child)
      {
      // Is the attribute definition already in the system?
      std::string etype = child.text().get();
      attribute::DefinitionPtr adef = this->m_system.findDefinition(etype);
      if (adef)
        {
        idef->setExpressionDefinition(adef);
        }
      else
        {
        // We need to queue up this item to be assigned its definition later
        this->m_itemExpressionDefInfo.push_back(ItemExpressionDefInfo(idef, etype));
        }
      }
    xatt = node.attribute("Units");
    if (xatt)
      {
      idef->setUnits(xatt.value());
      }
  
    // Now lets process its children items
    xml_node cinode, citemsNode = node.child("ChildrenDefinitions");
    std::string citemName;
    smtk::attribute::Item::Type citype;
    smtk::attribute::ItemDefinitionPtr cidef;
    for (cinode = citemsNode.first_child(); cinode; cinode = cinode.next_sibling())
      {
      citype = smtk::attribute::Item::string2Type(cinode.name());
      citemName = cinode.attribute("Name").value();
      switch (citype)
        {
        case smtk::attribute::Item::ATTRIBUTE_REF:
          if( (cidef = idef->addItemDefinition<smtk::attribute::RefItemDefinition>(citemName)) )
            {
            this->processRefDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::RefItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::DOUBLE:
          if( (cidef = idef->addItemDefinition<smtk::attribute::DoubleItemDefinition>(citemName)) )
            {
            this->processDoubleDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::DoubleItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::DIRECTORY:
          if( (cidef = idef->addItemDefinition<smtk::attribute::DirectoryItemDefinition>(citemName)) )
            {
            this->processDirectoryDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::DirectoryItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::FILE:
          if( (cidef = idef->addItemDefinition<smtk::attribute::FileItemDefinition>(citemName)) )
            {
            this->processFileDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::FileItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::GROUP:
          if( (cidef = idef->addItemDefinition<smtk::attribute::GroupItemDefinition>(citemName)) )
            {
            this->processGroupDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::GroupItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::INT:
          if( (cidef = idef->addItemDefinition<smtk::attribute::IntItemDefinition>(citemName)) )
            {
            this->processIntDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::IntItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::STRING:
          if( (cidef = idef->addItemDefinition<smtk::attribute::StringItemDefinition>(citemName)) )
            {
            this->processStringDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::StringItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::MODEL_ENTITY:
          if( (cidef = idef->addItemDefinition<smtk::attribute::ModelEntityItemDefinition>(citemName)) )
            {
            this->processModelEntityDef(cinode, smtk::dynamic_pointer_cast<smtk::attribute::ModelEntityItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
          break;
        case smtk::attribute::Item::VOID:
          if( (cidef = idef->addItemDefinition<smtk::attribute::VoidItemDefinition>(citemName)) )
            {
            this->processItemDef(cinode, cidef);
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
        break;
        case smtk::attribute::Item::MESH_SELECTION:
          if( (cidef = idef->addItemDefinition<smtk::attribute::MeshSelectionItemDefinition>(citemName)) )
            {
            this->processItemDef(cinode, cidef);
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
        break;
        case smtk::attribute::Item::MESH_ENTITY:
          if( (cidef = idef->addItemDefinition<smtk::attribute::MeshItemDefinition>(citemName)) )
            {
            this->processMeshEntityDef(cinode,
              smtk::dynamic_pointer_cast<smtk::attribute::MeshItemDefinition>(cidef));
            }
          else
            {
            smtkErrorMacro(this->m_logger, "Item definition " << citemName << " already exists");
            }
        break;
      default:
        smtkErrorMacro(this->m_logger, "Unsupported Item definition Type: "
                       << cinode.name()
                       << " needed to create Definition: " << citype);
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processRefDef(pugi::xml_node &node,
                                     attribute::RefItemDefinitionPtr idef)
  {
    xml_node labels, child;
    xml_attribute xatt;
    int i;
    this->processItemDef(node, idef);
  
    // Has the attribute definition been set?
    child = node.child("AttDef");
    if (child)
      {
      // Is the attribute definition already in the system?
      std::string etype = child.text().get();
      attribute::DefinitionPtr adef = this->m_system.findDefinition(etype);
      if (adef)
        {
        idef->setAttributeDefinition(adef);
        }
      else
        {
        // We need to queue up this item to be assigned its definition later
        this->m_attRefDefInfo.push_back(AttRefDefInfo(idef, etype));
        }
      }
  
    xatt = node.attribute("NumberOfRequiredValues");
    if (xatt)
      {
      idef->setNumberOfRequiredValues(xatt.as_int());
      }
    else
      {
      smtkErrorMacro(this->m_logger,
                     "Missing XML Attribute NumberOfRequiredValues for Item Definition : "
                     << idef->name());
      }
  
    // Lets see if there are labels
    if(node.child("Labels"))
      {
      smtkErrorMacro(this->m_logger,
                     "Labels has been changed to ComponentLabels : "
                     << idef->name());
      }
    labels = node.child("ComponentLabels");
    if (labels)
      {
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        idef->setCommonValueLabel(xatt.value());
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          idef->setValueLabel(i, child.value());
          }
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processDirectoryDef(pugi::xml_node &node,
                                              attribute::DirectoryItemDefinitionPtr idef)
  {
    xml_node labels, child;
    xml_attribute xatt;
    int i;
    this->processItemDef(node, idef);
  
    xatt = node.attribute("NumberOfRequiredValues");
    if (xatt)
      {
      idef->setNumberOfRequiredValues(xatt.as_int());
      }
    else
      {
      smtkErrorMacro(this->m_logger,
                     "Missing XML Attribute NumberOfRequiredValues for Item Definition : "
                     << idef->name());
      }
  
    xatt = node.attribute("ShouldExist");
    if (xatt)
      {
      idef->setShouldExist(xatt.as_bool());
      }
  
    xatt = node.attribute("ShouldBeRelative");
    if (xatt)
      {
      idef->setShouldBeRelative(xatt.as_bool());
      }
  
    // Lets see if there are labels
    labels = node.child("Labels");
    if (labels)
      {
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        idef->setCommonValueLabel(xatt.value());
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          idef->setValueLabel(i, child.value());
          }
        }
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processFileDef(pugi::xml_node &node,
                                         attribute::FileItemDefinitionPtr idef)
  {
    xml_node labels, defaultNode, child;
    xml_attribute xatt;
    int i;
    this->processItemDef(node, idef);
  
    xatt = node.attribute("NumberOfRequiredValues");
    if (xatt)
      {
      idef->setNumberOfRequiredValues(xatt.as_int());
      }
    else
      {
      smtkErrorMacro(this->m_logger,
                     "Missing XML Attribute NumberOfRequiredValues for Item Definition : "
                     << idef->name());
      }
  
    xatt = node.attribute("ShouldExist");
    if (xatt)
      {
      idef->setShouldExist(xatt.as_bool());
      }
  
    xatt = node.attribute("ShouldBeRelative");
    if (xatt)
      {
      idef->setShouldBeRelative(xatt.as_bool());
      }
  
    // Lets see if there are labels
    if(node.child("Labels"))
      {
      smtkErrorMacro(this->m_logger,
                     "Labels has been changed to ComponentLabels : "
                     << idef->name());
      }
    labels = node.child("ComponentLabels");
    if (labels)
      {
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        idef->setCommonValueLabel(xatt.value());
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          idef->setValueLabel(i, child.value());
          }
        }
      }
  
    // Check for filters
    xatt = node.attribute("FileFilters");
    if (xatt)
      {
      idef->setFileFilters(xatt.as_string());
      }
  
    // Check for default value
    defaultNode = node.child("DefaultValue");
    if (defaultNode)
      {
      idef->setDefaultValue(defaultNode.text().get());
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processGroupDef(pugi::xml_node &node,
                                          attribute::GroupItemDefinitionPtr def)
  {
    xml_node labels, child;
    xml_attribute xatt;
    int i;
    this->processItemDef(node, def);
  
    xatt = node.attribute("NumberOfRequiredGroups");
    if (xatt)
      {
      def->setNumberOfRequiredGroups(xatt.as_uint());
      }
  
    xatt = node.attribute("Extensible");
    if (xatt)
      {
      def->setIsExtensible(xatt.as_bool());
      xatt = node.attribute("MaxNumberOfGroups");
      if (xatt)
        {
        def->setMaxNumberOfGroups(xatt.as_uint());
        }
      }
    // Lets see if there are labels
    if(node.child("Labels"))
      {
      smtkErrorMacro(this->m_logger,
                     "Labels has been changed to ComponentLabels : "
                     << def->name());
      }
    labels = node.child("ComponentLabels");
    if (labels)
      {
      // Are we using a common label?
      xatt = labels.attribute("CommonLabel");
      if (xatt)
        {
        def->setCommonSubGroupLabel(xatt.value());
        }
      else
        {
        for (child = labels.first_child(), i = 0; child; child = child.next_sibling(), i++)
          {
          def->setSubGroupLabel(i, child.value());
          }
        }
      }
    xml_node itemsNode = node.child("ItemDefinitions");
    std::string itemName;
    smtk::attribute::Item::Type itype;
    smtk::attribute::ItemDefinitionPtr idef;
    for (child = itemsNode.first_child(); child; child = child.next_sibling())
      {
      itype = smtk::attribute::Item::string2Type(child.name());
      itemName = child.attribute("Name").value();
      switch (itype)
        {
        case smtk::attribute::Item::ATTRIBUTE_REF:
          idef = def->addItemDefinition<smtk::attribute::RefItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Ref Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processRefDef(child, smtk::dynamic_pointer_cast<smtk::attribute::RefItemDefinition>(idef));
          break;
        case smtk::attribute::Item::DOUBLE:
          idef = def->addItemDefinition<smtk::attribute::DoubleItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Double Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processDoubleDef(child, smtk::dynamic_pointer_cast<smtk::attribute::DoubleItemDefinition>(idef));
          break;
        case smtk::attribute::Item::DIRECTORY:
          idef = def->addItemDefinition<smtk::attribute::DirectoryItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Directory Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processDirectoryDef(child,
                                    smtk::dynamic_pointer_cast<smtk::attribute::DirectoryItemDefinition>(idef));
          break;
        case smtk::attribute::Item::FILE:
          idef = def->addItemDefinition<smtk::attribute::FileItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create File Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processFileDef(child, smtk::dynamic_pointer_cast<smtk::attribute::FileItemDefinition>(idef));
          break;
        case smtk::attribute::Item::GROUP:
          idef = def->addItemDefinition<smtk::attribute::GroupItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Group Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processGroupDef(child, smtk::dynamic_pointer_cast<smtk::attribute::GroupItemDefinition>(idef));
          break;
        case smtk::attribute::Item::INT:
          idef = def->addItemDefinition<smtk::attribute::IntItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Int Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processIntDef(child, smtk::dynamic_pointer_cast<smtk::attribute::IntItemDefinition>(idef));
          break;
        case smtk::attribute::Item::STRING:
          idef = def->addItemDefinition<smtk::attribute::StringItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create String Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processStringDef(child, smtk::dynamic_pointer_cast<smtk::attribute::StringItemDefinition>(idef));
          break;
        case smtk::attribute::Item::MODEL_ENTITY:
          idef = def->addItemDefinition<smtk::attribute::ModelEntityItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create String Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processModelEntityDef(child,
                                      smtk::dynamic_pointer_cast<smtk::attribute::ModelEntityItemDefinition>(idef));
          break;
        case smtk::attribute::Item::VOID:
          idef = def->addItemDefinition<smtk::attribute::VoidItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create Void Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processItemDef(child, idef);
          break;
        case smtk::attribute::Item::MESH_SELECTION:
          idef = def->addItemDefinition<smtk::attribute::MeshSelectionItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create String Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processItemDef(child, idef);
          break;
        case smtk::attribute::Item::MESH_ENTITY:
          idef = def->addItemDefinition<smtk::attribute::MeshItemDefinition>(itemName);
          if (!idef)
            {
            smtkErrorMacro(this->m_logger,
                           "Failed to create String Item definition Type: " << child.name()
                           << " needed to create Group Definition: " << def->name());
            continue;
            }
          this->processMeshEntityDef(child,
            smtk::dynamic_pointer_cast<smtk::attribute::MeshItemDefinition>(idef));
          break;
        default:
          smtkErrorMacro(this->m_logger,
                         "Unsupported Item definition Type: " << child.name()
                         << " needed to create Group Definition: " << def->name());
        }
      }
  }
  
  //----------------------------------------------------------------------------
  smtk::common::UUID XmlDocV1Parser::getAttributeID(xml_node &attNode)
  {
    // In Version 1 Format we didn't use UIDs so we need to give
    // attributes new IDs
    xml_attribute xatt;
    std::string name;
  
    xatt = attNode.attribute("Name");
    if (xatt)
      {
      name = xatt.value();
      }
      smtkWarningMacro(this->m_logger,
                     "Attribute: " << name
                     << " is being assigned a new ID (Version 1 Format)!");
  
    return smtk::common::UUID::null();
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processAttribute(xml_node &attNode)
  {
    xml_node itemsNode, assocsNode, iNode, node;
    std::string name, type;
    xml_attribute xatt;
    attribute::AttributePtr att;
    attribute::DefinitionPtr def;
    smtk::common::UUID id;
    int i, n;
  
    xatt = attNode.attribute("Name");
    if (!xatt)
      {
      smtkErrorMacro(this->m_logger,
                     "Invalid Attribute! - Missing XML Attribute Name");
      return;
      }
    name = xatt.value();
    xatt = attNode.attribute("Type");
    if (!xatt)
      {
      smtkErrorMacro(this->m_logger,
                     "Invalid Attribute: " << name
                     << "  - Missing XML Attribute Type");
      return;
      }
    type = xatt.value();
  
    id = this->getAttributeID(attNode);
  
    def = this->m_system.findDefinition(type);
    if (!def)
      {
      smtkErrorMacro(this->m_logger,
                     "Attribute: " << name << " of Type: " << type
                     << "  - can not find attribute definition");
      return;
      }
  
    // Is the definition abstract?
    if (def->isAbstract())
      {
      smtkErrorMacro(this->m_logger,
                     "Attribute: " << name << " of Type: " << type
                     << "  - is based on an abstract definition");
      return;
      }
  
    // Do we have a valid uuid?
    if (id.isNull())
      {
      att = this->m_system.createAttribute(name, def);
      }
    else
      {
      att = this->m_system.createAttribute(name, def, id);
      }
  
  
    if (!att)
      {
      smtkErrorMacro(this->m_logger,
                     "Attribute: " << name << " of Type: " << type
                     << "  - could not be created - is the name in use");
      return;
      }
    xatt = attNode.attribute("OnInteriorNodes");
    if (xatt)
      {
      att->setAppliesToInteriorNodes(xatt.as_bool());
      }
  
    xatt = attNode.attribute("OnBoundaryNodes");
    if (xatt)
      {
      att->setAppliesToBoundaryNodes(xatt.as_bool());
      }
  
    double color[4];
  
    node = attNode.child("Color");
    if (node && this->getColor(node, color, "Color"))
      {
      att->setColor(color);
      }
  
    itemsNode = attNode.child("Items");
    if (itemsNode)
      {
      // Process all of the items in the attribute w/r to the XML
      // NOTE That the writer processes the items in order - lets assume
      // that for speed and if that fails we can try to search for the correct
      // xml node
      n = static_cast<int>(att->numberOfItems());
      for (i = 0, iNode = itemsNode.first_child(); (i < n) && iNode;
        i++, iNode = iNode.next_sibling())
        {
        // See if the name of the item matches the name of node
        xatt = iNode.attribute("Name");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
            "Bad Item for Attribute : " << name
            << "- missing XML Attribute Name");
          node = itemsNode.find_child_by_attribute("Name", att->item(i)->name().c_str());
          }
        else
          {
          // Is the ith xml node the same as the ith item of the attribute?
          if (att->item(i)->name() == xatt.value())
            {
            node = iNode;
            }
          else
            {
            node = itemsNode.find_child_by_attribute("Name", att->item(i)->name().c_str());
            }
          }
        if (!node)
          {
          smtkErrorMacro(this->m_logger,
            "Can not locate XML Item node :" << att->item(i)->name()
            << " for Attribute : " << name);
          continue;
          }
        this->processItem(node, att->item(i));
        }
      if (iNode || (i != n))
        {
        smtkErrorMacro(this->m_logger,
          "Number of Items does not match XML for Attribute : " << name);
        }
      }
  
    assocsNode = attNode.child("Associations");
    if (assocsNode)
      {
      this->processItem(assocsNode, att->associations());
      }
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processItem(xml_node &node,
                                   smtk::attribute::ItemPtr item)
  {
    xml_attribute xatt;
    if (item->isOptional())
      {
      xatt = node.attribute("Enabled");
      if (xatt)
        {
        item->setIsEnabled(xatt.as_bool());
        }
      }
    // If using AdvanceLevel then we are setting
    // both read and write
    xatt = node.attribute("AdvanceLevel");
    if (xatt)
      {
      item->setAdvanceLevel(0, xatt.as_int());
      item->setAdvanceLevel(1, xatt.as_int());
      }
    else
      {
      xatt = node.attribute("AdvanceReadLevel");
      if (xatt)
        {
        item->setAdvanceLevel(0, xatt.as_int());
        }
      xatt = node.attribute("AdvanceWriteLevel");
      if (xatt)
        {
        item->setAdvanceLevel(1, xatt.as_int());
        }
      }
  
    switch (item->type())
      {
      case smtk::attribute::Item::ATTRIBUTE_REF:
        this->processRefItem(node, smtk::dynamic_pointer_cast<smtk::attribute::RefItem>(item));
        break;
      case smtk::attribute::Item::DOUBLE:
        this->processDoubleItem(node, smtk::dynamic_pointer_cast<smtk::attribute::DoubleItem>(item));
        break;
      case smtk::attribute::Item::DIRECTORY:
        this->processDirectoryItem(node, smtk::dynamic_pointer_cast<smtk::attribute::DirectoryItem>(item));
        break;
      case smtk::attribute::Item::FILE:
        this->processFileItem(node, smtk::dynamic_pointer_cast<smtk::attribute::FileItem>(item));
        break;
      case smtk::attribute::Item::GROUP:
        this->processGroupItem(node, smtk::dynamic_pointer_cast<smtk::attribute::GroupItem>(item));
        break;
      case smtk::attribute::Item::INT:
        this->processIntItem(node, smtk::dynamic_pointer_cast<smtk::attribute::IntItem>(item));
        break;
      case smtk::attribute::Item::STRING:
        this->processStringItem(node, smtk::dynamic_pointer_cast<smtk::attribute::StringItem>(item));
        break;
      case smtk::attribute::Item::MODEL_ENTITY:
        this->processModelEntityItem(node, smtk::dynamic_pointer_cast<smtk::attribute::ModelEntityItem>(item));
        break;
      case smtk::attribute::Item::MESH_SELECTION:
        this->processMeshSelectionItem(node, smtk::dynamic_pointer_cast<smtk::attribute::MeshSelectionItem>(item));
        break;
      case smtk::attribute::Item::MESH_ENTITY:
        this->processMeshEntityItem(node, smtk::dynamic_pointer_cast<smtk::attribute::MeshItem>(item));
        break;
      case smtk::attribute::Item::VOID:
        // Nothing to do!
        break;
      default:
        smtkErrorMacro(this->m_logger,
                       "Unsupported Item Type: "
                       << smtk::attribute::Item::type2String(item->type()));
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processValueItem(pugi::xml_node &node,
                                           attribute::ValueItemPtr item)
  {
    std::size_t  numRequiredVals = item->numberOfRequiredValues();
    std::size_t i=0, n = item->numberOfValues();
    xml_attribute xatt;
    if (item->isExtensible())
      {
      // The node should have an attribute indicating how many values are
      // associated with the item
      xatt = node.attribute("NumberOfValues");
      if (!xatt)
        {
        smtkErrorMacro(this->m_logger,
                       "XML Attribute NumberOfValues is missing for Item: "
                       << item->name());
        return;
        }
      n = xatt.as_uint();
      item->setNumberOfValues(n);
      }
  
    if (!item->isDiscrete())
      {
      return; // there is nothing to be done
      }
  
    // OK Time to process the children items of this Discrete Item
    xml_node val, values, childNode, childrenNodes, inode;
    childrenNodes = node.child("ChildrenItems");
    if (childrenNodes)
      {
      // Process all of the children items in the item w/r to the XML
      // NOTE That the writer processes the items in order - lets assume
      // that for speed and if that fails we can try to search for the correct
      // xml node
      std::map<std::string, smtk::attribute::ItemPtr>::const_iterator iter;
      const std::map<std::string, smtk::attribute::ItemPtr> &childrenItems = item->childrenItems();
      for (childNode = childrenNodes.first_child(), iter = childrenItems.begin();
           (iter != childrenItems.end()) && childNode;
           iter++, childNode = childNode.next_sibling())
        {
        // See if the name of the item matches the name of node
        xatt = childNode.attribute("Name");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "Bad Child Item for Item : " << item->name()
                         << "- missing XML Attribute Name");
          inode = childrenNodes.find_child_by_attribute("Name", iter->second->name().c_str());
          }
        else
          {
          // Is the ith xml node the same as the ith item of the attribute?
          if (iter->second->name() == xatt.value())
            {
            inode = childNode;
            }
          else
            {
            inode = childrenNodes.find_child_by_attribute("Name", iter->second->name().c_str());
            }
          }
        if (!inode)
          {
          smtkErrorMacro(this->m_logger,
                         "Can not locate XML Child Item node :" << iter->second->name()
                         << " for Item : " << item->name());
          continue;
          }
        this->processItem(inode, iter->second);
        }
      if (childNode || (iter != childrenItems.end()))
        {
        smtkErrorMacro(this->m_logger,
                       "Number of Children Items does not match XML for Item : " << item->name());
        }
      }
    int index=0;
    if (!n)
      {
      return;
      }
    // There are 2 possible formats - a general one that must be used when n > 1
    // and a special compact one that could be used for n == 1
    // Lets check the general one first - note we only need to process the values
    // that have been set
    values = node.child("DiscreteValues");
    if (values)
      {
      for (val = values.child("Index"); val; val = val.next_sibling("Index"))
        {
        xatt = val.attribute("Ith");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute Ith is missing for Item: " << item->name());
          continue;
          }
        i = xatt.as_int();
        if (i >= n)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute Ith = " << i
                         << " and is out of range for Item: " << item->name());
          continue;
          }
        index = val.text().as_int();
        if (!item->setDiscreteIndex(static_cast<int>(i), index))
          {
          smtkErrorMacro(this->m_logger,
                         "Discrete Index " << index
                         << " for  ith value : " << i
                         << " is not valid for Item: " << item->name());
          }
        }
      return;
      }
    if (numRequiredVals == 1) // Special Common Case
      {
      if (!item->setDiscreteIndex(node.text().as_int()))
        {
        smtkErrorMacro(this->m_logger,
                       "Discrete Index " << index
                       << " for  ith value : " << i
                       << " is not valid for Item: " << item->name());
        }
      return;
      }
    smtkErrorMacro(this->m_logger, "Missing Discrete Values for Item: " << item->name());
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processRefItem(pugi::xml_node &node,
                                                 attribute::RefItemPtr item)
  {
    xml_attribute xatt;
    xml_node valsNode;
    std::size_t i, n = item->numberOfValues();
    xml_node val;
    std::size_t  numRequiredVals = item->numberOfRequiredValues();
    std::string attName;
    attribute::AttributePtr att;
    AttRefInfo info;
    if (!numRequiredVals)
      {
      // The node should have an attribute indicating how many values are
      // associated with the item
      xatt = node.attribute("NumberOfValues");
      if (!xatt)
        {
        smtkErrorMacro(this->m_logger,
                       "XML Attribute NumberOfValues is missing for Item: "
                       << item->name());
        return;
        }
      n = xatt.as_uint();
      item->setNumberOfValues(n);
      }
  
    if (!n)
      {
      return;
      }
    valsNode = node.child("Values");
    if (valsNode)
      {
      for (val = valsNode.child("Val"); val; val = val.next_sibling("Val"))
        {
        xatt = val.attribute("Ith");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute Ith is missing for Item: " << item->name());
          continue;
          }
        i = xatt.as_uint();
        if (i >= n)
          {
          smtkErrorMacro(this->m_logger, "XML Attribute Ith = " << i
                         << " is out of range for Item: " << item->name());
          continue;
          }
        attName = val.text().get();
        att = this->m_system.findAttribute(attName);
        if (!att)
          {
          info.item = item; info.pos = static_cast<int>(i); info.attName = attName;
          this->m_attRefInfo.push_back(info);
          }
        else
          {
          item->setValue(static_cast<int>(i), att);
          }
        }
      }
    else if (numRequiredVals == 1)
      {
      val = node.child("Val");
      if (val)
        {
        attName = val.text().get();
        att = this->m_system.findAttribute(attName);
        if (!att)
          {
          info.item = item; info.pos = 0; info.attName = attName;
          this->m_attRefInfo.push_back(info);
          }
        else
          {
          item->setValue(att);
          }
        }
      }
    else
      {
      smtkErrorMacro(this->m_logger, "XML Node Values is missing for Item: " << item->name());
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processDirectoryItem(pugi::xml_node &node,
                                               attribute::DirectoryItemPtr item)
  {
    xml_attribute xatt;
    xml_node valsNode;
    std::size_t i, n = item->numberOfValues();
    xml_node val;
    std::size_t  numRequiredVals = item->numberOfRequiredValues();
    if (!numRequiredVals)
      {
      // The node should have an attribute indicating how many values are
      // associated with the item
      xatt = node.attribute("NumberOfValues");
      if (!xatt)
        {
        smtkErrorMacro(this->m_logger,
                       "XML Attribute NumberOfValues is missing for Item: "
                       << item->name());
        return;
        }
      n = xatt.as_uint();
      item->setNumberOfValues(n);
      }
  
    if (!n)
      {
      return;
      }
    valsNode = node.child("Values");
    if (valsNode)
      {
      for (val = valsNode.child("Val"); val; val = val.next_sibling("Val"))
        {
        xatt = val.attribute("Ith");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute Ith is missing for Item: " << item->name());
          continue;
          }
        i = xatt.as_uint();
        if (i >= n)
          {
          smtkErrorMacro(this->m_logger, "XML Attribute Ith = " << i
                         << " is out of range for Item: " << item->name());
          continue;
          }
        item->setValue(static_cast<int>(i), val.text().get());
        }
      }
    else if (numRequiredVals == 1)
      {
      item->setValue(node.text().get());
      }
    else
      {
      smtkErrorMacro(this->m_logger, "XML Node Values is missing for Item: " << item->name());
      }
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processDoubleItem(pugi::xml_node &node,
                                            attribute::DoubleItemPtr item)
  {
    this->processValueItem(node,
                           dynamic_pointer_cast<smtk::attribute::ValueItem>(item));
    processDerivedValue<attribute::DoubleItemPtr, double>
      (node, item, this->m_system, this->m_itemExpressionInfo, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processIntItem(pugi::xml_node &node,
                                         attribute::IntItemPtr item)
  {
    this->processValueItem(node,
                           dynamic_pointer_cast<smtk::attribute::ValueItem>(item));
    processDerivedValue<attribute::IntItemPtr, int>
      (node, item, this->m_system, this->m_itemExpressionInfo, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processStringItem(pugi::xml_node &node,
                                            attribute::StringItemPtr item)
  {
    this->processValueItem(node,
                           dynamic_pointer_cast<smtk::attribute::ValueItem>(item));
    processDerivedValue<attribute::StringItemPtr, std::string>
      (node, item, this->m_system, this->m_itemExpressionInfo, this->m_logger);
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processModelEntityItem(pugi::xml_node &node,
                                            attribute::ModelEntityItemPtr item)
  {
    (void)node;
    smtkWarningMacro(this->m_logger,
                   "All Model Entity Items will be ignored for Attribute Version 1 Format"
                   << item->name());
    return;
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processMeshSelectionItem(pugi::xml_node &node,
    attribute::MeshSelectionItemPtr item)
  {
    (void)node;
    smtkWarningMacro(this->m_logger,
                   "All Mesh Selection Items will be ignored for Attribute Version 1 Format"
                   << item->name());
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processMeshEntityItem(pugi::xml_node &node,
    attribute::MeshItemPtr item)
  {
    (void)node;
    smtkWarningMacro(this->m_logger,
                   "All Mesh Entity Items will be ignored for Attribute Version 1 Format"
                   << item->name());
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processFileItem(pugi::xml_node &node,
                                          attribute::FileItemPtr item)
  {
    xml_attribute xatt;
    xml_node valsNode;
    std::size_t i, n = item->numberOfValues();
    xml_node val;
    std::size_t  numRequiredVals = item->numberOfRequiredValues();
    if (!numRequiredVals)
      {
      // The node should have an attribute indicating how many values are
      // associated with the item
      xatt = node.attribute("NumberOfValues");
      if (!xatt)
        {
        smtkErrorMacro(this->m_logger,
                       "XML Attribute NumberOfValues is missing for Item: "
                       << item->name());
        return;
        }
      n = xatt.as_uint();
      item->setNumberOfValues(n);
      }
  
    if (!n)
      {
      return;
      }
    valsNode = node.child("Values");
    if (valsNode)
      {
      for (val = valsNode.child("Val"); val; val = val.next_sibling("Val"))
        {
        xatt = val.attribute("Ith");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute Ith is missing for Item: " << item->name());
          continue;
          }
        i = xatt.as_uint();
        if (i >= n)
          {
          smtkErrorMacro(this->m_logger, "XML Attribute Ith = " << i
                         << " is out of range for Item: " << item->name());
          continue;
          }
        item->setValue(static_cast<int>(i), val.text().get());
        }
      }
    else if (numRequiredVals == 1)
      {
      item->setValue(node.text().get());
      }
    else
      {
      smtkErrorMacro(this->m_logger, "XML Node Values is missing for Item: " << item->name());
      }
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processGroupItem(pugi::xml_node &node,
                                           attribute::GroupItemPtr item)
  {
    std::size_t i, j, m, n;
    std::size_t  numRequiredGroups = item->numberOfRequiredGroups();
    xml_node itemNode;
    xml_attribute xatt;
    n = item->numberOfGroups();
    m = item->numberOfItemsPerGroup();
    if (item->isExtensible())
      {
      // If node has no children, then number of groups is zero
      if (!node.first_child())
        {
        n = 0;
        }
      else
        {
        // The node should have an attribute indicating how many groups are
        // associated with the item
        xatt = node.attribute("NumberOfGroups");
        if (!xatt)
          {
          smtkErrorMacro(this->m_logger,
                         "XML Attribute NumberOfGroups is missing for Group Item: "
                         << item->name());
          return;
          }
        n = xatt.as_uint();
        }
  
      if (!item->setNumberOfGroups(n))
        {
        smtkErrorMacro(this->m_logger,
                       "Invalid number of sub-groups for Group Item: " << item->name());
        return;
        }
      }
  
    if (!n) // There are no sub-groups for this item
      {
      return;
      }
    // There are 2 formats - one is for any number of sub groups and the other
    // is a custon case is for 1 subGroup
    xml_node cluster, clusters = node.child("GroupClusters");
    if (clusters)
      {
      for (cluster = clusters.first_child(), i = 0; cluster;
           cluster = cluster.next_sibling(), ++i)
        {
        if (i >= n)
          {
          smtkErrorMacro(this->m_logger,
                         "Too many sub-groups for Group Item: " << item->name());
          continue;
          }
        for (itemNode = cluster.first_child(), j = 0; itemNode;
             itemNode = itemNode.next_sibling(), j++)
          {
          if (j >= m)
            {
          smtkErrorMacro(this->m_logger,
                         "Too many item nodes for subGroup: " << i
                         << " for Group Item: " << item->name());
            continue;
            }
          this->processItem(itemNode, item->item(static_cast<int>(i),static_cast<int>(j)));
          }
        }
      }
    else if (numRequiredGroups == 1)
      {
      for (itemNode = node.first_child(), j = 0; itemNode;
           itemNode = itemNode.next_sibling(), j++)
        {
        if (j >= m)
          {
          smtkErrorMacro(this->m_logger,
                         "Too many item nodes for subGroup: 0"
                         << " for Group Item: " << item->name());
            continue;
            }
          this->processItem(itemNode, item->item(static_cast<int>(j)));
          }
      }
    else
      {
      smtkErrorMacro(this->m_logger,"XML Node GroupClusters is missing for Item: " << item->name());
      }
  }
  //----------------------------------------------------------------------------
  bool XmlDocV1Parser::getColor(xml_node &node, double color[4],
                                   const std::string &colorName)
  {
    std::string s = node.text().get();
    if(s.empty())
      {
      smtkErrorMacro(this->m_logger, "Color Format Problem - empty input for "
                     << colorName);
      return false;
      }
  
    int i = this->decodeColorInfo(s, color);
    if (i)
      {
      smtkErrorMacro(this->m_logger, "Color Format Problem - only found " << 4-i
                     << " components for " << colorName << " from string " << s);
      return false;
      }
    return true;
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processViews(xml_node &root)
  {
    xml_node views = root.child("RootView");
    if (!views)
      {
      return;
      }
    smtk::common::ViewPtr rootView = this->createView(views, "Group");
    rootView->details().setAttribute("TopLevel", "true");
    
    if (!rootView)
      {
      smtkErrorMacro(this->m_logger, "Can't process Root View");
      return;
      }
    
    xml_node node;
    xml_attribute xatt;
    node = views.child("DefaultColor");
    if (node)
      {
      rootView->details().addChild("DefaultColor").setContents(node.text().get());
      }
    node = views.child("InvalidColor");
    if (node)
      {
      rootView->details().addChild("InvalidColor").setContents(node.text().get());
      }
    
    node = views.child("AdvancedFontEffects");
    if (node)
      {
      smtk::common::View::Component comp = rootView->details().addChild("AdvancedFontEffects");
      if(node.attribute("Bold"))
        {
        comp.setAttribute("Bold", "t");
        }
      if(node.attribute("Italic"))
        {
        comp.setAttribute("Italic", "t");
        }
      }
    node = views.child("MaxValueLabelLength");
    if (node)
       {
       rootView->details().addChild("MaxValueLabelLength").setContents(node.text().get());
       }
    node = views.child("MinValueLabelLength");
    if (node)
       {
       rootView->details().addChild("MinValueLabelLength").setContents(node.text().get());
       }
  
    this->processGroupView(views,rootView);
  
  }
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processAttributeView(xml_node &node,
                                            smtk::common::ViewPtr view)
  {
    xml_attribute xatt;
    attribute::DefinitionPtr def;
    xml_node child, attTypes;
    std::string defType;
    xatt = node.attribute("ModelEntityFilter");
    if (xatt)
      {
      view->details().setAttribute("ModelEntityFilter", xatt.value());
  
      xatt = node.attribute("CreateEntities");
      if (xatt)
        {
        view->details().setAttribute("CreateEntities", xatt.value());
        }
      }
    attTypes = node.child("AttributeTypes");
    if (!attTypes)
      {
      return;
      }
    smtk::common::View::Component &comp = view->details().addChild("AttributeTypes");
    
    for (child = attTypes.child("Type"); child; child = child.next_sibling("Type"))
      {
      comp.addChild("Att").setAttribute("Type", child.text().get());
      }
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processInstancedView(xml_node &node,
                                            smtk::common::ViewPtr view)
  {
    xml_attribute xatt;
    xml_node child, instances = node.child("InstancedAttributes");
  
    if (!instances)
      {
      return; // No instances are in the view
      }
    smtk::common::View::Component &comp = view->details().addChild("InstancedAttributes");
    for (child = instances.child("Att"); child; child = child.next_sibling("Att"))
      {
      xatt = child.attribute("Type");
      if (!xatt)
        {
        smtkErrorMacro(this->m_logger,
                       "XML Attribute Type is missing"
                       << "and is required to create attribute: " << child.text().get()
                       << " for Instanced View: " << view->title());
        continue;
        }
     
      comp.addChild("Att").setAttribute("Type", xatt.value())
        .setAttribute("Name",child.text().get());
      }
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processModelEntityView(xml_node &node,
                                              smtk::common::ViewPtr view)
  {
    xml_attribute xatt = node.attribute("ModelEntityFilter");
    xml_node child = node.child("Definition");
    if (xatt)
      {
      view->details().setAttribute("ModelEntityFilter", xatt.value());
      }
  
    if (child)
      {
      view->details().addChild("Type").setContents(child.text().get());
      }    
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processSimpleExpressionView(xml_node &node,
                                                   smtk::common::ViewPtr view)
  {
    xml_node child = node.child("Definition");
    if (child)
      {
      view->details().addChild("Att").setAttribute("Type",child.text().get());
      }
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processGroupView(xml_node &node,
                                        smtk::common::ViewPtr group)
  {
    // Group style (Optional), Tabbed (default) or Tiled
    xml_attribute xatt;
    xatt = node.attribute("Style");
    if (xatt)
      {
      group->details().setAttribute("Style", xatt.value());
      }
  
    // Add Views Component
    smtk::common::View::Component &vcomp = group->details().addChild("Views");
    xml_node child;
    smtk::common::ViewPtr childView;
    std::string childName;
    for (child = node.first_child(); child; child = child.next_sibling())
      {
      childName = child.name();
      if (childName == "AttributeView")
        {
        childView = this->createView(child, "Attribute");
        if (childView)
          {
          vcomp.addChild("View").setAttribute("Title", childView->title());
          this->processAttributeView(child, childView);
          }
        continue;
        }
  
      if (childName == "GroupView")
        {
        childView = this->createView(child, "Group");
        if (childView)
          {
          vcomp.addChild("View").setAttribute("Title", childView->title());
          this->processGroupView(child, childView);
          }
        continue;
        }
  
      if (childName == "InstancedView")
        {
        childView = this->createView(child, "Instanced");
        if (childView)
          {
          vcomp.addChild("View").setAttribute("Title", childView->title());
          this->processInstancedView(child, childView);
          }
        continue;
        }
  
      if (childName == "ModelEntityView")
        {
        childView = this->createView(child, "ModelEntity");
        if (childView)
          {
          vcomp.addChild("View").setAttribute("Title", childView->title());
          this->processModelEntityView(child, childView);
          }
        continue;
        }
  
      if (childName == "SimpleExpressionView")
        {
        childView = this->createView(child, "SimpleExpression");
        if (childView)
          {
          vcomp.addChild("View").setAttribute("Title", childView->title());
          this->processSimpleExpressionView(child, childView);
          }
        continue;
        }
      }
  }
  
  //----------------------------------------------------------------------------
  smtk::common::ViewPtr  XmlDocV1Parser::createView(xml_node &node,
                                                    const std::string &viewType)
  {
    xml_attribute xatt;
    std::string val;
    xatt = node.attribute("Title"); // Required
    if (!xatt)
      {
      smtkErrorMacro(this->m_logger, "View is missing XML Attribute Title");
      smtk::common::ViewPtr dummy;
      return dummy;
      }
    val = xatt.value();
    smtk::common::ViewPtr view = smtk::common::View::New(viewType, val);
  
    xatt = node.attribute("Icon"); // optional
    if (xatt)
      {
      val = xatt.value();
      view->details().setAttribute("Icon", val);
      }
    this->m_system.addView(view);
    return view;
  }
  
  //----------------------------------------------------------------------------
  void XmlDocV1Parser::processModelInfo(xml_node &root)
  {
    xml_node modelInfo = root.child("ModelInfo");
    if (modelInfo)
      {
      smtkWarningMacro(this->m_logger, "Model Information is not supported in this version");
      }
  }
  
  //----------------------------------------------------------------------------
  int XmlDocV1Parser::decodeColorInfo(const std::string &s, double *color)
  {
    // Assume that the string is seperated by spaces and or commas
    std::istringstream iss(s);
    int i = 0;
    char c;
    while (!((i == 4) || iss.eof()))
      {
      iss.get(c);
      if ((c == ' ') || (c == ','))
        {
        continue;
        }
      iss.putback(c);
      iss >> color[i];
      i++;
      }
    return 4 - i; // If we processed all the components this would be 0
  }
  //----------------------------------------------------------------------------
  smtk::model::BitFlags
  XmlDocV1Parser::decodeModelEntityMask(const std::string &s)
  {
    smtk::model::BitFlags flags = smtk::model::Entity::specifierStringToFlag(s);
    if (!s.empty() && flags == 0 && s != "none" && s != "none|nodim")
      {
      smtkErrorMacro(this->m_logger,
        "Decoding Model Entity Mask - Option \""
        << s << "\" is not supported");
      }
    return flags;
  }
  //----------------------------------------------------------------------------
  