Przeglądaj źródła

Merge pull request #11357 from kenrowland/HPCC-19969

HPCC-19969 Expand environment attribute type information

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday 7 lat temu
rodzic
commit
6921f4785f

+ 11 - 6
configuration/config2/SchemaItem.cpp

@@ -22,9 +22,6 @@
 #include <algorithm>
 
 
-// static class variables
-//std::map<std::string, std::vector<std::shared_ptr<SchemaValue>>> SchemaItem::m_uniqueAttributeValueSets;
-
 SchemaItem::SchemaItem(const std::string &name, const std::string &className, const std::shared_ptr<SchemaItem> &pParent) :
     m_pParent(pParent),
     m_hidden(false),
@@ -44,6 +41,7 @@ SchemaItem::SchemaItem(const std::string &name, const std::string &className, co
         //
         // Create a default type so that all values have a type
         std::shared_ptr<SchemaType> pDefaultType = std::make_shared<SchemaType>("default");
+        pDefaultType->setBaseType("string");
         std::shared_ptr<SchemaTypeLimits> pDefaultLimits = std::make_shared<SchemaTypeLimits>();
         pDefaultType->setLimits(pDefaultLimits);
         addSchemaValueType(pDefaultType);
@@ -58,7 +56,6 @@ SchemaItem::SchemaItem(const SchemaItem &item)
     m_hidden = item.m_hidden;
     m_maxInstances = item.m_maxInstances;
     m_minInstances = item.m_minInstances;
-    //m_nodeInsertData = item.m_nodeInsertData;
     m_properties = item.m_properties;
     m_types = item.m_types;
     m_schemaTypes = item.m_schemaTypes;
@@ -92,7 +89,15 @@ SchemaItem::SchemaItem(const SchemaItem &item)
 
 void SchemaItem::addSchemaValueType(const std::shared_ptr<SchemaType> &pType)
 {
-    m_types[pType->getName()] = pType;
+    auto it = m_types.find(pType->getName());
+    if (it == m_types.end())
+    {
+        m_types[pType->getName()] = pType;
+    }
+    else
+    {
+        throw(ParseException("Element: " + getProperty("name") + ", duplicate schema value type found: " + pType->getName()));
+    }
 }
 
 
@@ -140,7 +145,7 @@ void SchemaItem::addSchemaType(const std::shared_ptr<SchemaItem> &pItem, const s
     }
     else
     {
-        throw(ParseException("Element: " + getProperty("name") + ", duplicate config type found: " + typeName));
+        throw(ParseException("Element: " + getProperty("name") + ", duplicate schema complex type found: " + typeName));
     }
 }
 

+ 8 - 2
configuration/config2/SchemaType.hpp

@@ -37,9 +37,13 @@ class DECL_EXPORT SchemaType
 
         std::shared_ptr<SchemaTypeLimits> &getLimits() { return m_pLimits; }
         void setLimits(const std::shared_ptr<SchemaTypeLimits> &pLimits) { m_pLimits = pLimits; }
-        bool isValid() const { return m_pLimits!=nullptr; }
+        bool isValid() const { return  m_pLimits!=nullptr && !m_baseType.empty(); }
+        void setSubType(const std::string &subType) { m_subType = subType; }
+        const std::string &getSubType() const { return m_subType; }
+        void setBaseType(const std::string &baseType) { m_baseType = baseType; }
+        const std::string &getBaseType() const { return m_baseType; }
+        void setName(const std::string &name) { m_name = name; }
         const std::string &getName() const { return m_name; }
-        void setName(const std::string &name) { m_name = name;  }
         bool isValueValid(const std::string &testValue) const { return m_pLimits->isValueValid(testValue); }
         bool isEnumerated() const { return m_pLimits->isEnumerated(); }
         const std::vector<AllowedValue> getEnumeratedValues() const { return m_pLimits->getEnumeratedValues(); }
@@ -51,6 +55,8 @@ class DECL_EXPORT SchemaType
     private:
 
         std::string m_name;
+        std::string m_subType;
+        std::string m_baseType;
         std::shared_ptr<SchemaTypeLimits> m_pLimits;
 
 };

+ 7 - 0
configuration/config2/XMLEnvironmentLoader.cpp

@@ -75,6 +75,13 @@ void XMLEnvironmentLoader::parse(const pt::ptree &envTree, const std::shared_ptr
         if (!value.empty())
         {
             std::shared_ptr<SchemaValue> pCfgValue = pConfigItem->getItemSchemaValue();
+            if (!pCfgValue)
+            {
+                pCfgValue = std::make_shared<SchemaValue>("", false);
+                pCfgValue->setType(pConfigItem->getSchemaValueType("default"));
+                pConfigItem->setItemSchemaValue(pCfgValue);
+            }
+
             std::shared_ptr<EnvironmentValue> pEnvValue = std::make_shared<EnvironmentValue>(pEnvNode, pCfgValue, "");  // node's value has no name
             pEnvValue->setValue(value, nullptr);
             pEnvNode->setLocalEnvValue(pEnvValue);

+ 26 - 21
configuration/config2/XSDSchemaParser.cpp

@@ -39,16 +39,19 @@ bool XSDSchemaParser::doParse(const std::string &configPath, const std::string &
     std::shared_ptr<SchemaTypeIntegerLimits> pIntLimits;
 
     std::shared_ptr<SchemaType> pType = std::make_shared<SchemaType>("xs:string");
+    pType->setBaseType("string");
     pStringLimits = std::make_shared<SchemaTypeStringLimits>();
     pType->setLimits(pStringLimits);
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:token");
+    pType->setBaseType("string");
     pStringLimits = std::make_shared<SchemaTypeStringLimits>();
     pType->setLimits(pStringLimits);
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:boolean");
+    pType->setBaseType("boolean");
     std::shared_ptr<SchemaTypeLimits> pBoolLimits = std::make_shared<SchemaTypeStringLimits>();
     pBoolLimits->addAllowedValue("true");
     pBoolLimits->addAllowedValue("false");
@@ -56,28 +59,27 @@ bool XSDSchemaParser::doParse(const std::string &configPath, const std::string &
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:integer");
-    pIntLimits = std::make_shared<SchemaTypeIntegerLimits>();
-    pType->setLimits(pIntLimits);
-    m_pSchemaItem->addSchemaValueType(pType);
-
-    pType = std::make_shared<SchemaType>("xs:int");
+    pType->setBaseType("integer");
     pIntLimits = std::make_shared<SchemaTypeIntegerLimits>();
     pType->setLimits(pIntLimits);
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:nonNegativeInteger");
+    pType->setBaseType("integer");
     pIntLimits = std::make_shared<SchemaTypeIntegerLimits>();
     pIntLimits->setMinInclusive(0);
     pType->setLimits(pIntLimits);
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:positiveInteger");
+    pType->setBaseType("integer");
     pIntLimits = std::make_shared<SchemaTypeIntegerLimits>();
     pIntLimits->setMinInclusive(1);
     pType->setLimits(pIntLimits);
     m_pSchemaItem->addSchemaValueType(pType);
 
     pType = std::make_shared<SchemaType>("xs:unsignedInt");
+    pType->setBaseType("integer");
     pIntLimits = std::make_shared<SchemaTypeIntegerLimits>();
     pIntLimits->setMinInclusive(0);
     pType->setLimits(pIntLimits);
@@ -198,7 +200,7 @@ std::string XSDSchemaParser::getXSDAttributeValue(const pt::ptree &tree, const s
 
 void XSDSchemaParser::parseSimpleType(const pt::ptree &typeTree)
 {
-    std::shared_ptr<SchemaType> pCfgType = getSchemaType(typeTree, true);
+    std::shared_ptr<SchemaType> pCfgType = getType(typeTree, true);
     m_pSchemaItem->addSchemaValueType(pCfgType);
 }
 
@@ -247,18 +249,12 @@ void XSDSchemaParser::parseAttributeGroup(const pt::ptree &attributeTree)
 void XSDSchemaParser::parseComplexType(const pt::ptree &typeTree)
 {
     std::string complexTypeName = getXSDAttributeValue(typeTree, "<xmlattr>.name", false, "");
-    std::string className = typeTree.get("<xmlattr>.hpcc:class", "");
-    std::string catName = typeTree.get("<xmlattr>.hpcc:category", "");
-    std::string componentName = typeTree.get("<xmlattr>.hpcc:componentName", "");
-    std::string displayName = typeTree.get("<xmlattr>.hpcc:displayName", "");
     bool hidden = typeTree.get("<xmlattr>.hpcc:hidden", "false") == "true";
 
     if (!complexTypeName.empty())
     {
         std::shared_ptr<SchemaItem> pComplexType = std::make_shared<SchemaItem>(complexTypeName, "component", m_pSchemaItem);
-        pComplexType->setProperty("category", catName);
-        pComplexType->setProperty("componentName", componentName);
-        pComplexType->setProperty("displayName", displayName);
+        pComplexType->setProperty("itemType", complexTypeName);
         pComplexType->setHidden(hidden);
 
         pt::ptree childTree = typeTree.get_child("", pt::ptree());
@@ -270,7 +266,7 @@ void XSDSchemaParser::parseComplexType(const pt::ptree &typeTree)
         }
         else
         {
-            throw(ParseException("Complex type definition empty: " + displayName));
+            throw(ParseException("Complex type definition empty: " + complexTypeName));
         }
     }
 
@@ -301,7 +297,7 @@ void XSDSchemaParser::parseElement(const pt::ptree &elemTree)
     else
     {
         std::string className = elemTree.get("<xmlattr>.hpcc:class", "");
-        std::string displayName = elemTree.get("<xmlattr>.hpcc:displayName", "");
+        std::string displayName = elemTree.get("<xmlattr>.hpcc:displayName", elementName);
         std::string tooltip = elemTree.get("<xmlattr>.hpcc:tooltip", "");
         std::string typeName = elemTree.get("<xmlattr>.type", "");
         std::string componentName = elemTree.get("<xmlattr>.hpcc:componentName", "");
@@ -320,6 +316,7 @@ void XSDSchemaParser::parseElement(const pt::ptree &elemTree)
         if (!itemType.empty()) pNewSchemaItem->setProperty("itemType", itemType);
         if (!insertLimitType.empty()) pNewSchemaItem->setProperty("insertLimitType", insertLimitType);
         if (!insertLimitData.empty()) pNewSchemaItem->setProperty("insertLimitData", insertLimitData);
+        pNewSchemaItem->setProperty("category", category.empty() ? displayName : category );
         pNewSchemaItem->setMinInstances(minOccurs);
         pNewSchemaItem->setMaxInstances(maxOccurs);
         pNewSchemaItem->setHidden(elemTree.get("<xmlattr>.hpcc:hidden", "false") == "true");
@@ -544,19 +541,27 @@ void XSDSchemaParser::parseAppInfo(const pt::ptree &elemTree)
 }
 
 
-std::shared_ptr<SchemaType> XSDSchemaParser::getSchemaType(const pt::ptree &typeTree, bool nameRequired)
+std::shared_ptr<SchemaType> XSDSchemaParser::getType(const pt::ptree &typeTree, bool nameRequired)
 {
     std::string typeName = getXSDAttributeValue(typeTree, "<xmlattr>.name", nameRequired, "");
 
+    if (!nameRequired && !typeName.empty())
+    {
+        std::string msg = "Name (" + typeName + ") not allowed in local xs:simpleType definition";
+        throw(ParseException(msg));
+    }
+
     std::shared_ptr<SchemaType> pCfgType = std::make_shared<SchemaType>(typeName);
     std::shared_ptr<SchemaTypeLimits> pLimits;
     auto restriction = typeTree.find("xs:restriction");
     if (restriction != typeTree.not_found())
     {
-        std::string baseType = getXSDAttributeValue(restriction->second, "<xmlattr>.base");
-        std::shared_ptr<SchemaType> pType = std::make_shared<SchemaType>(*(m_pSchemaItem->getSchemaValueType(baseType)));
+        std::string xsdBaseType = getXSDAttributeValue(restriction->second, "<xmlattr>.base");
+        std::shared_ptr<SchemaType> pBaseType = m_pSchemaItem->getSchemaValueType(xsdBaseType);
+        pCfgType->setBaseType(pBaseType->getBaseType());
+        pCfgType->setSubType(typeName);
 
-        pLimits = pType->getLimits();
+        pLimits = pBaseType->getLimits();
 
         if (!restriction->second.empty())
         {
@@ -577,7 +582,7 @@ std::shared_ptr<SchemaType> XSDSchemaParser::getSchemaType(const pt::ptree &type
             }
             else
             {
-                std::string msg = "Unsupported base type(" + baseType + ")";
+                std::string msg = "Unsupported base type(" + xsdBaseType + ")";
                 throw(ParseException(msg));
             }
         }
@@ -714,7 +719,7 @@ std::shared_ptr<SchemaValue> XSDSchemaParser::getSchemaValue(const pt::ptree &at
     }
     else
     {
-        std::shared_ptr<SchemaType> pType = getSchemaType(attr.get_child("xs:simpleType", pt::ptree()), false);
+        std::shared_ptr<SchemaType> pType = getType(attr.get_child("xs:simpleType", pt::ptree()), false);
         if (!pType->isValid())
         {
             throw(ParseException("Attribute " + attrName + " does not have a valid type"));

+ 1 - 1
configuration/config2/XSDSchemaParser.hpp

@@ -56,7 +56,7 @@ class XSDSchemaParser : public SchemaParser
         virtual void parseAnnotation(const pt::ptree &elemTree);
         virtual void parseAppInfo(const pt::ptree &elemTree);
 
-        virtual std::shared_ptr<SchemaType> getSchemaType(const pt::ptree &typeTree, bool nameRequired=true);
+        virtual std::shared_ptr<SchemaType> getType(const pt::ptree &typeTree, bool nameRequired=true);
         virtual std::shared_ptr<SchemaValue> getSchemaValue(const pt::ptree &attr);
 
         virtual void parseKey(const pt::ptree &keyTree);

+ 11 - 8
esp/scm/ws_config2.ecm

@@ -26,10 +26,11 @@ ESPstruct StatusMsgType
     ESParray<string, parentId> ParentIdList;
 };
 
+
 ESPstruct StatusType
 {
     bool Error(false);    // true if a message exsits in status (below) with a message level of error or higher
-    ESParray<ESPstruct StatusMsgType, StatusMsg> Status;
+    ESParray<ESPstruct StatusMsgType, StatusMsg> StatusMessages;
 };
 
 
@@ -142,16 +143,17 @@ ESPstruct LimitsType
 
 ESPstruct TypeInfo
 {
-    string Name;
+    string BaseType;
+    string SubType;
     ESPstruct LimitsType Limits;
 };
 
 
 ESPstruct NodeInfoType
 {
-    string    Name("");
+    string    DisplayName("");
     string    NodeType("");
-    string    NodeName;
+    string    Name;
     string    Class("");
     string    Category("");
     bool      Hidden(false);
@@ -159,7 +161,7 @@ ESPstruct NodeInfoType
 };
 
 
-ESPstruct NodeType
+ESPstruct Node
 {
     string    NodeId;
     int       NumChildren(0);
@@ -212,13 +214,14 @@ ESPstruct AttributeValueType
 };
 
 
-ESPresponse [exceptions_inline] GetNodeResponse : StatusResponse
+ESPresponse [exceptions_inline] GetNodeResponse
 {
     string NodeId;
     ESPstruct NodeInfoType NodeInfo;
     ESParray<ESPstruct AttributeType, Attribute> Attributes;
-    ESParray<ESPstruct NodeType, Child> Children;
+    ESParray<ESPstruct Node, Child> Children;
     ESParray<ESPstruct InsertItemType, Item> Insertable;         // list of insertable elements under this node
+    ESPstruct StatusType Status;
     bool LocalValueDefined(false);                               // true if the node is configured to have a value (not usually true)
     ESPstruct AttributeType Value;                               // this would be <element>value</element> not normal, see valueDefined
 };
@@ -336,7 +339,7 @@ ESPstruct TreeElementType
     string    NodeId;
     ESPstruct NodeInfoType NodeInfo;
     ESParray<ESPstruct AttributeType, attribute> Attributes;
-    ESParray<ESPstruct TreeElementType, Node> Children;
+    ESParray<ESPstruct TreeElementType, Element> Children;
 };
 
 

+ 25 - 38
esp/services/ws_config2/ws_config2Service.cpp

@@ -341,7 +341,7 @@ bool Cws_config2Ex::onGetNode(IEspContext &context, IEspNodeRequest &req, IEspGe
 
     getNodeResponse(pNode, resp);
     pNode->validate(status, false);  // validate this node only
-    addStatusToResponse(status, pSession, reinterpret_cast<IEspStatusResponse &>(resp));
+    buildStatusResponse(status, pSession, resp.updateStatus());
 
     //
     // Finalize the response
@@ -373,7 +373,7 @@ bool Cws_config2Ex::onInsertNode(IEspContext &context, IEspInsertNodeRequest &re
         throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
     }
 
-    addStatusToResponse(status, pSession, reinterpret_cast<IEspStatusResponse &>(resp));
+    buildStatusResponse(status, pSession, resp.updateStatus());
     return true;
 }
 
@@ -394,7 +394,7 @@ bool Cws_config2Ex::onRemoveNode(IEspContext &context, IEspRemoveNodeRequest &re
 
     pSession->modified = true;
     pSession->m_pEnvMgr->validate(status, false);
-    addStatusToResponse(status, pSession, resp);
+    buildStatusResponse(status, pSession, resp.updateStatus());
     return true;
 }
 
@@ -406,7 +406,7 @@ bool Cws_config2Ex::onValidateEnvironment(IEspContext &context, IEspValidateEnvi
     ConfigMgrSession *pSession = getConfigSession(sessionId, true);
 
     pSession->m_pEnvMgr->validate(status, req.getIncludeHiddenNodes());
-    addStatusToResponse(status, pSession, resp);
+    buildStatusResponse(status, pSession, resp.updateStatus());
     return true;
 }
 
@@ -441,7 +441,7 @@ bool Cws_config2Ex::onSetValues(IEspContext &context, IEspSetValuesRequest &req,
 
     pNode->setAttributeValues(values, status, allowInvalid, forceCreate);
     pSession->modified = true;
-    addStatusToResponse(status, pSession, resp);
+    buildStatusResponse(status, pSession, resp.updateStatus());
     return true;
 }
 
@@ -542,11 +542,11 @@ bool Cws_config2Ex::onFetchNodes(IEspContext &context, IEspFetchNodesRequest &re
     return true;
 }
 
-void Cws_config2Ex::addStatusToResponse(const Status &status, ConfigMgrSession *pSession, IEspStatusResponse &resp) const
+
+void Cws_config2Ex::buildStatusResponse(const Status &status, ConfigMgrSession *pSession, IEspStatusType &respStatus) const
 {
     std::vector<statusMsg> statusMsgs = status.getMessages();
 
-
     IArrayOf<IEspStatusMsgType> msgs;
     for (auto msgIt=statusMsgs.begin(); msgIt!=statusMsgs.end(); ++msgIt)
     {
@@ -567,8 +567,8 @@ void Cws_config2Ex::addStatusToResponse(const Status &status, ConfigMgrSession *
         msgs.append(*pStatusMsg.getLink());
     }
 
-    resp.updateStatus().setStatus(msgs);
-    resp.updateStatus().setError(status.isError());
+    respStatus.setStatusMessages(msgs);
+    respStatus.setError(status.isError());
 }
 
 
@@ -644,7 +644,7 @@ void Cws_config2Ex::getNodeResponse(const std::shared_ptr<EnvironmentNode> &pNod
 
     //
     // Now the children
-    IArrayOf<IEspNodeType> childNodes;
+    IArrayOf<IEspNode> childNodes;
     if (pNode->hasChildren())
     {
         std::vector<std::shared_ptr<EnvironmentNode>> children;
@@ -653,7 +653,7 @@ void Cws_config2Ex::getNodeResponse(const std::shared_ptr<EnvironmentNode> &pNod
         {
             std::shared_ptr<EnvironmentNode> pChildEnvNode = *it;
             const std::shared_ptr<SchemaItem> pSchemaItem = pChildEnvNode->getSchemaItem();
-            Owned<IEspNodeType> pChildNode = createNodeType();
+            Owned<IEspNode> pChildNode = createNode();
             getNodeInfo(pChildEnvNode, pChildNode->updateNodeInfo());
             pChildNode->setNodeId(pChildEnvNode->getId().c_str());
             pChildNode->setNumChildren(pChildEnvNode->getNumChildren());
@@ -707,7 +707,11 @@ void Cws_config2Ex::getNodeResponse(const std::shared_ptr<EnvironmentNode> &pNod
 
         const std::shared_ptr<SchemaValue> &pNodeSchemaValue = pNodeSchemaItem->getItemSchemaValue();
         const std::shared_ptr<SchemaType> &pType = pNodeSchemaValue->getType();
-        resp.updateValue().updateType().setName(pType->getName().c_str());
+        resp.updateValue().updateType().setBaseType(pType->getBaseType().c_str());
+        resp.updateValue().updateType().setSubType(pType->getSubType().c_str());
+        resp.updateValue().setRequired(pNodeSchemaValue->isRequired());
+        resp.updateValue().setReadOnly(pNodeSchemaValue->isReadOnly());
+        resp.updateValue().setHidden(pNodeSchemaValue->isHidden());
 
         if (pType->getLimits()->isMaxSet())
         {
@@ -724,27 +728,6 @@ void Cws_config2Ex::getNodeResponse(const std::shared_ptr<EnvironmentNode> &pNod
         {
             const std::shared_ptr<EnvironmentValue> &pLocalValue = pNode->getLocalEnvValue();
             resp.updateValue().setCurrentValue(pLocalValue->getValue().c_str());
-
-            //
-            // Type information
-            const std::shared_ptr<SchemaValue> pLocalSchemaValue = pLocalValue->getSchemaValue();
-            const std::shared_ptr<SchemaType> &pLocalType = pLocalSchemaValue->getType();
-            std::shared_ptr<SchemaTypeLimits> &pLimits = pLocalType->getLimits();
-            resp.updateValue().updateType().setName(pLocalType->getName().c_str());
-            if (pLocalType->getLimits()->isMaxSet())
-            {
-                resp.updateValue().updateType().updateLimits().setMaxValid(true);
-                resp.updateValue().updateType().updateLimits().setMax(pLocalType->getLimits()->getMax());
-            }
-            if (pLocalType->getLimits()->isMinSet())
-            {
-                resp.updateValue().updateType().updateLimits().setMinValid(true);
-                resp.updateValue().updateType().updateLimits().setMin(pLocalType->getLimits()->getMin());
-            }
-
-            resp.updateValue().setRequired(pLocalSchemaValue->isRequired());
-            resp.updateValue().setReadOnly(pLocalSchemaValue->isReadOnly());
-            resp.updateValue().setHidden(pLocalSchemaValue->isHidden());
         }
     }
 }
@@ -758,8 +741,8 @@ void Cws_config2Ex::getNodeInfo(const std::shared_ptr<EnvironmentNode> &pNode, I
     // Fill in base node info struct
     getNodeInfo(pNodeSchemaItem, nodeInfo);      // fill it in based on schema
     getNodeDisplayName(pNode, nodeDisplayName);  // possibly override the displayname
-    nodeInfo.setName(nodeDisplayName.c_str());
-    nodeInfo.setNodeName(pNode->getName().c_str());
+    nodeInfo.setDisplayName(nodeDisplayName.c_str());
+    nodeInfo.setName(pNode->getName().c_str());
 }
 
 
@@ -767,12 +750,15 @@ void Cws_config2Ex::getNodeInfo(const std::shared_ptr<SchemaItem> &pNodeSchemaIt
 {
     //
     // Fill in base node info struct
-    nodeInfo.setName(pNodeSchemaItem->getProperty("displayName").c_str());
+    std::string displayName = pNodeSchemaItem->getProperty("displayName");
+    nodeInfo.setDisplayName(displayName.c_str());
     nodeInfo.setNodeType(pNodeSchemaItem->getItemType().c_str());
     nodeInfo.setClass(pNodeSchemaItem->getProperty("className").c_str());
-    nodeInfo.setCategory(pNodeSchemaItem->getProperty("category").c_str());
     nodeInfo.setTooltip(pNodeSchemaItem->getProperty("tooltip").c_str());
     nodeInfo.setHidden(pNodeSchemaItem->isHidden());
+
+    std::string category = pNodeSchemaItem->getProperty("category");
+    nodeInfo.setCategory((!category.empty()) ? category.c_str() : displayName.c_str());
 }
 
 
@@ -791,7 +777,8 @@ void Cws_config2Ex::getAttributes(const std::vector<std::shared_ptr<EnvironmentV
 
         const std::shared_ptr<SchemaType> &pType = pSchemaValue->getType();
         std::shared_ptr<SchemaTypeLimits> &pLimits = pType->getLimits();
-        pAttribute->updateType().setName(pType->getName().c_str());
+        pAttribute->updateType().setBaseType(pType->getBaseType().c_str());
+        pAttribute->updateType().setSubType(pType->getSubType().c_str());
         if (pType->getLimits()->isMaxSet())
         {
             pAttribute->updateType().updateLimits().setMaxValid(true);

+ 1 - 1
esp/services/ws_config2/ws_config2Service.hpp

@@ -59,7 +59,7 @@ public:
 
 private:
 
-    void addStatusToResponse(const Status &status, ConfigMgrSession *pSession, IEspStatusResponse &resp) const;
+    void buildStatusResponse(const Status &status, ConfigMgrSession *pSession, IEspStatusType &respStatus) const;
     ConfigMgrSession *getConfigSession(const std::string &sessionId, bool environmentRequired = false);
     ConfigMgrSession *getConfigSessionForUpdate(const std::string &sessionId, const std::string &lockKey);
     bool deleteConfigSession(const std::string &sessionId);