SchemaElement.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2016 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include <cassert>
  14. #include "jptree.hpp"
  15. #include "jstring.hpp"
  16. #include "jarray.hpp"
  17. #include "jhash.hpp"
  18. #include "XMLTags.h"
  19. #include "SchemaAnnotation.hpp"
  20. #include "SchemaCommon.hpp"
  21. #include "SchemaElement.hpp"
  22. #include "SchemaComplexType.hpp"
  23. #include "SchemaElement.hpp"
  24. #include "SchemaAttributes.hpp"
  25. #include "SchemaAppInfo.hpp"
  26. #include "SchemaDocumentation.hpp"
  27. #include "DocumentationMarkup.hpp"
  28. #include "ConfigSchemaHelper.hpp"
  29. #include "ConfigSchemaHelper.hpp"
  30. #include "SchemaMapManager.hpp"
  31. #include "ConfiguratorMain.hpp"
  32. #include "JSONMarkUp.hpp"
  33. using namespace CONFIGURATOR;
  34. const CXSDNodeBase* CElement::getNodeByTypeAndNameAscending(NODE_TYPES eNodeType, const char *pName) const
  35. {
  36. const CXSDNodeBase* pMatchingNode = nullptr;
  37. if (eNodeType == this->getNodeType() && (pName != nullptr ? !strcmp(pName, this->getNodeTypeStr()) : true))
  38. return this;
  39. if (eNodeType == XSD_ELEMENT)
  40. pMatchingNode = (dynamic_cast<CElement*>(this->getParentNode()))->getNodeByTypeAndNameAscending(XSD_ELEMENT, pName);
  41. if (pMatchingNode == nullptr)
  42. pMatchingNode = (dynamic_cast<CElementArray*>(this->getParentNode()))->getNodeByTypeAndNameAscending(eNodeType, pName);
  43. return pMatchingNode;
  44. }
  45. const CXSDNodeBase* CElement::getNodeByTypeAndNameDescending(NODE_TYPES eNodeType, const char *pName) const
  46. {
  47. const CXSDNodeBase* pMatchingNode = nullptr;
  48. if (eNodeType == this->getNodeType() && (pName != nullptr ? !strcmp(pName, this->getNodeTypeStr()) : true))
  49. return this;
  50. if (m_pComplexTypeArray != nullptr)
  51. pMatchingNode = m_pComplexTypeArray->getNodeByTypeAndNameDescending(eNodeType, pName);
  52. return pMatchingNode;
  53. }
  54. CElement* CElement::load(CXSDNodeBase* pParentNode, const ::IPropertyTree *pSchemaRoot, const char* xpath, bool bIsInXSD)
  55. {
  56. assert(pSchemaRoot != nullptr);
  57. assert(pParentNode != nullptr);
  58. if (pSchemaRoot == nullptr || pParentNode == nullptr)
  59. return nullptr;
  60. CElement *pElement = new CElement(pParentNode);
  61. pElement->setIsInXSD(bIsInXSD);
  62. pElement->setXSDXPath(xpath);
  63. ::IPropertyTree *pTree = pSchemaRoot->queryPropTree(xpath);
  64. if (pTree != nullptr)
  65. pElement->setName(pTree->queryProp(XML_ATTR_NAME));
  66. Owned<IAttributeIterator> iterAttrib = pTree->getAttributes(true);
  67. ForEach(*iterAttrib)
  68. {
  69. if (strcmp(iterAttrib->queryName(), XML_ATTR_NAME) == 0)
  70. {
  71. const char *pName = iterAttrib->queryValue();
  72. if (pName != nullptr && *pName != 0)
  73. pElement->setName(pName);
  74. }
  75. else if (strcmp(iterAttrib->queryName(), XML_ATTR_MAXOCCURS) == 0)
  76. pElement->setMaxOccurs(iterAttrib->queryValue());
  77. else if (strcmp(iterAttrib->queryName(), XML_ATTR_MINOCCURS) == 0)
  78. pElement->setMinOccurs(iterAttrib->queryValue());
  79. else if (strcmp(iterAttrib->queryName(), XML_ATTR_TYPE) == 0)
  80. {
  81. const char *pType = iterAttrib->queryValue();
  82. assert(pType != nullptr && *pType != 0);
  83. if (pType != nullptr && *pType != 0)
  84. {
  85. pElement->setType(pType);
  86. CConfigSchemaHelper::getInstance()->addNodeForTypeProcessing(pElement);
  87. }
  88. }
  89. else if (strcmp(iterAttrib->queryName(), XML_ATTR_REF) == 0)
  90. {
  91. const char *pRef = iterAttrib->queryValue();
  92. assert (pRef != nullptr && *pRef != 0 && pElement->getConstAncestorNode(3)->getNodeType() != XSD_SCHEMA);
  93. if (pRef != nullptr && *pRef != 0 && pElement->getConstAncestorNode(3)->getNodeType() != XSD_SCHEMA)
  94. {
  95. pElement->setRef(pRef);
  96. CConfigSchemaHelper::getInstance()->addElementForRefProcessing(pElement);
  97. }
  98. else
  99. {
  100. // TODO: throw exception
  101. }
  102. }
  103. else if (strcmp(iterAttrib->queryName(), XML_ATTR_DEFAULT) == 0)
  104. {
  105. const char *pDefault = iterAttrib->queryValue();
  106. assert(pDefault != nullptr);
  107. assert(strlen(pElement->getDefault()) == 0);
  108. pElement->setDefault(pDefault);
  109. }
  110. assert(iterAttrib->queryValue() != nullptr);
  111. }
  112. assert(strlen(pElement->getName()) > 0);
  113. if (strlen(pElement->getRef()) != 0)
  114. {
  115. assert(pElement->getComplexTypeArray()->length() == 0);
  116. assert(pElement->getSimpleType() == nullptr);
  117. assert(strlen(pElement->getDefault()) == 0);
  118. assert(strlen(pElement->getType()) == 0);
  119. /*assert(pElement->getKey() == nullptr);
  120. assert(pElement->getKeyRef() == nullptr);
  121. assert(pElement->getUnique() == nullptr);*/
  122. }
  123. ::VStringBuffer strXPathExt("%s/%s", xpath, XSD_TAG_ANNOTATION);
  124. pElement->m_pAnnotation = CAnnotation::load(pElement, pSchemaRoot, strXPathExt.str());
  125. strXPathExt.setf("%s/%s", xpath, XSD_TAG_COMPLEX_TYPE);
  126. pElement->m_pComplexTypeArray = CComplexTypeArray::load(pElement, pSchemaRoot, strXPathExt.str());
  127. if (pElement->m_pAnnotation != nullptr && pElement->m_pAnnotation->getAppInfo() != nullptr && strlen(pElement->m_pAnnotation->getAppInfo()->getTitle()) > 0)
  128. {
  129. /**** MUST FIX TO HAVE CORRECT UI TAB LABELS (but getName is expected to return the XPATH name *****/
  130. //pElement->setName(pElement->m_pAnnotation->getAppInfo()->getTitle());
  131. pElement->setTitle(pElement->m_pAnnotation->getAppInfo()->getTitle());
  132. }
  133. else
  134. pElement->setTitle(pElement->getName());
  135. /* strXPathExt.setf("%s/%s", xpath, XSD_TAG_KEY);
  136. pElement->m_pKeyArray = CKeyArray::load(pElement, pSchemaRoot, strXPathExt.str());
  137. strXPathExt.setf("%s/%s", xpath, XSD_TAG_KEYREF);
  138. pElement->m_pKeyRefArray = CKeyRefArray::load(pElement, pSchemaRoot, strXPathExt.str());
  139. */
  140. strXPathExt.setf("%s/%s", xpath, XSD_TAG_SIMPLE_TYPE);
  141. pElement->m_pSimpleType = CSimpleType::load(pElement, pSchemaRoot, strXPathExt.str());
  142. SETPARENTNODE(pElement, pParentNode);
  143. return pElement;
  144. }
  145. const CElement* CElement::getTopMostElement(const CXSDNodeBase *pNode)
  146. {
  147. if (pNode == nullptr)
  148. return nullptr;
  149. else if (pNode->getNodeType() == XSD_ELEMENT && pNode->getParentNodeByType(XSD_ELEMENT) == nullptr)
  150. {
  151. assert(dynamic_cast<const CElement*>(pNode) != nullptr);
  152. return dynamic_cast<const CElement*>(pNode);
  153. }
  154. return getTopMostElement(pNode->getParentNodeByType(XSD_ELEMENT));
  155. }
  156. const CSchema* CElement::getConstSchemaNode() const
  157. {
  158. const CSchema *pSchema = dynamic_cast<const CSchema*>(CElement::getTopMostElement(this)->getParentNodeByType(XSD_SCHEMA));
  159. return pSchema;
  160. }
  161. const char* CElement::getXML(const char* /*pComponent*/)
  162. {
  163. if (m_strXML.length () == 0)
  164. {
  165. m_strXML.append("\n<").append(getName()).append(" ");
  166. if (m_pAnnotation != nullptr)
  167. m_strXML.append(m_pAnnotation->getXML(nullptr));
  168. if (m_pComplexTypeArray != nullptr)
  169. m_strXML.append(m_pComplexTypeArray->getXML(nullptr));
  170. if (m_pKeyArray != nullptr)
  171. m_strXML.append(m_pKeyArray->getXML(nullptr));
  172. if (m_pKeyRefArray != nullptr)
  173. m_strXML.append(m_pKeyRefArray->getXML(nullptr));
  174. }
  175. return m_strXML.str();
  176. }
  177. void CElement::dump(::std::ostream &cout, unsigned int offset) const
  178. {
  179. offset += STANDARD_OFFSET_1;
  180. quickOutHeader(cout, XSD_ELEMENT_STR, offset);
  181. QUICK_OUT(cout, Name, offset);
  182. QUICK_OUT(cout, Type, offset);
  183. QUICK_OUT(cout, MinOccurs, offset);
  184. QUICK_OUT(cout, MaxOccurs, offset);
  185. QUICK_OUT(cout, Title, offset);
  186. QUICK_OUT(cout, XSDXPath, offset);
  187. QUICK_OUT(cout, EnvXPath, offset);
  188. QUICK_OUT(cout, EnvValueFromXML, offset);
  189. QUICK_OUT(cout, Ref, offset);
  190. if (this->getTypeNode() != nullptr)
  191. this->getTypeNode()->dump(cout, offset);
  192. if (m_pAnnotation != nullptr)
  193. m_pAnnotation->dump(cout, offset);
  194. if (m_pComplexTypeArray != nullptr)
  195. m_pComplexTypeArray->dump(cout, offset);
  196. if (m_pKeyArray != nullptr)
  197. m_pKeyArray->dump(cout, offset);
  198. if (m_pKeyRefArray != nullptr)
  199. m_pKeyRefArray->dump(cout, offset);
  200. if (m_pSimpleType != nullptr)
  201. m_pSimpleType->dump(cout, offset);
  202. if (this->getRef() != nullptr)
  203. {
  204. CElement *pElement = CConfigSchemaHelper::getInstance()->getSchemaMapManager()->getElementWithName(this->getRef());
  205. assert(pElement != nullptr);
  206. if (pElement != nullptr)
  207. pElement->dump(cout, offset);
  208. }
  209. quickOutFooter(cout, XSD_ELEMENT_STR, offset);
  210. }
  211. void CElement::getDocumentation(::StringBuffer &strDoc) const
  212. {
  213. const CXSDNodeBase *pGrandParentNode = this->getConstParentNode()->getConstParentNode();
  214. assert(pGrandParentNode != nullptr);
  215. if (pGrandParentNode == nullptr)
  216. return;
  217. if (m_pAnnotation != nullptr && m_pAnnotation->getAppInfo() != nullptr && m_pAnnotation->getAppInfo()->getViewType() != nullptr && stricmp(m_pAnnotation->getAppInfo()->getViewType(), "none") == 0)
  218. return;
  219. if (this->getName() != nullptr && (stricmp(this->getName(), "Instance") == 0 || stricmp(this->getName(), "Note") == 0 || stricmp(this->getName(), "Notes") == 0 || stricmp(this->getName(), "Topology") == 0 ))
  220. return; // don't document instance
  221. assert(strlen(this->getName()) > 0);
  222. if (strDoc.length() == 0)
  223. {
  224. ::StringBuffer strName(this->getName());
  225. strName.replace(' ', '_');
  226. strDoc.append(DM_HEADING);
  227. // component name would be here
  228. strDoc.appendf("<%s %s=\"%s%s\">\n", DM_SECT2, DM_ID, strName.str(),"_mod");
  229. strDoc.appendf("<%s>%s</%s>\n", DM_TITLE_LITERAL, this->getName(), DM_TITLE_LITERAL);
  230. if (m_pAnnotation!= nullptr)
  231. {
  232. m_pAnnotation->getDocumentation(strDoc);
  233. DEBUG_MARK_STRDOC;
  234. }
  235. strDoc.append(DM_SECT3_BEGIN);
  236. DEBUG_MARK_STRDOC;
  237. strDoc.append(DM_TITLE_BEGIN).append(DM_TITLE_END);
  238. if (m_pComplexTypeArray != nullptr)
  239. m_pComplexTypeArray->getDocumentation(strDoc);
  240. strDoc.append(DM_SECT3_END);
  241. return;
  242. }
  243. else if (m_pComplexTypeArray != nullptr)
  244. {
  245. if (m_pAnnotation!= nullptr)
  246. {
  247. m_pAnnotation->getDocumentation(strDoc);
  248. DEBUG_MARK_STRDOC;
  249. }
  250. if (pGrandParentNode->getNodeType() == XSD_CHOICE)
  251. strDoc.appendf("%s%s%s", DM_PARA_BEGIN, this->getTitle(), DM_PARA_END);
  252. else
  253. strDoc.appendf("%s%s%s", DM_TITLE_BEGIN, this->getTitle(), DM_TITLE_END);
  254. DEBUG_MARK_STRDOC;
  255. m_pComplexTypeArray->getDocumentation(strDoc);
  256. }
  257. else if (m_pComplexTypeArray == nullptr)
  258. {
  259. if (m_pAnnotation!= nullptr)
  260. {
  261. m_pAnnotation->getDocumentation(strDoc);
  262. DEBUG_MARK_STRDOC;
  263. }
  264. strDoc.appendf("%s%s%s", DM_PARA_BEGIN, this->getName(), DM_PARA_END);
  265. DEBUG_MARK_STRDOC;
  266. if (m_pAnnotation != nullptr && m_pAnnotation->getDocumentation() != nullptr)
  267. {
  268. m_pAnnotation->getDocumentation(strDoc);
  269. DEBUG_MARK_STRDOC;
  270. }
  271. }
  272. }
  273. void CElement::getJSON(::StringBuffer &strJSON, unsigned int offset, int idx) const
  274. {
  275. assert(strlen(this->getName()) > 0);
  276. StringBuffer strXPath(this->getEnvXPath());
  277. stripTrailingIndex(strXPath);
  278. if (m_pComplexTypeArray != nullptr && m_pComplexTypeArray->length() > 0)
  279. {
  280. CJSONMarkUpHelper::createUIContent(strJSON, offset, JSON_TYPE_TAB, this->getTitle(), strXPath.str());
  281. m_pComplexTypeArray->getJSON(strJSON, offset);
  282. }
  283. else
  284. CJSONMarkUpHelper::createUIContent(strJSON, offset, JSON_TYPE_TABLE, this->getTitle(), strXPath.str());
  285. }
  286. bool CElement::isATab() const
  287. {
  288. const CComplexTypeArray *pComplexTypArray = this->getComplexTypeArray();
  289. const CAttributeGroupArray *pAttributeGroupArray = (pComplexTypArray != nullptr && pComplexTypArray->length() > 0) ? pComplexTypArray->item(0).getAttributeGroupArray() : nullptr;
  290. const CAttributeArray *pAttributeArray = (pComplexTypArray != nullptr && pComplexTypArray->length() > 0) ? pComplexTypArray->item(0).getAttributeArray() : nullptr;
  291. if (this->getConstAncestorNode(3)->getNodeType() != XSD_SCHEMA && \
  292. (this->hasChildElements() == true || \
  293. (this->hasChildElements() == false && (static_cast<const CElementArray*>(this->getConstParentNode()))->anyElementsHaveMaxOccursGreaterThanOne() == false)/* || \
  294. (this->isTopLevelElement() == true && (pAttributeGroupArray != nullptr || pAttributeArray != nullptr))*/))
  295. {
  296. return true;
  297. }
  298. else
  299. {
  300. return false;
  301. }
  302. // Any element that is in sequence of complex type will be a tab
  303. if (this->getConstAncestorNode(3)->getNodeType() == XSD_SEQUENCE && this->getConstAncestorNode(3)->getNodeType() == XSD_COMPLEX_TYPE)
  304. {
  305. return true;
  306. }
  307. else if (this->getConstAncestorNode(3)->getNodeType() == XSD_ELEMENT)
  308. {
  309. const CElement *pElement = dynamic_cast<const CElement*>(this->getConstAncestorNode(3));
  310. assert(pElement != nullptr);
  311. if (pElement != nullptr)
  312. return pElement->isATab();
  313. }
  314. return false;
  315. }
  316. bool CElement::isLastTab(const int idx) const
  317. {
  318. assert(this->isATab() == true);
  319. const CElementArray *pElementArray = dynamic_cast<const CElementArray*>(this->getConstParentNode());
  320. if (pElementArray == nullptr)
  321. {
  322. assert(!"Corrupt XSD??");
  323. return false;
  324. }
  325. if (pElementArray->length()-1 == idx)
  326. return true;
  327. return false;
  328. }
  329. void CElement::populateEnvXPath(::StringBuffer strXPath, unsigned int index)
  330. {
  331. assert(strXPath.length() > 0);
  332. strXPath.append("[").append(index).append("]");
  333. this->setEnvXPath(strXPath);
  334. CConfigSchemaHelper::getInstance()->getSchemaMapManager()->addMapOfXPathToElement(this->getEnvXPath(), this);
  335. if (m_pComplexTypeArray != nullptr)
  336. m_pComplexTypeArray->populateEnvXPath(strXPath, index);
  337. if (m_pSimpleType != nullptr)
  338. m_pSimpleType->populateEnvXPath(strXPath, index);
  339. if (m_pKeyArray != nullptr)
  340. m_pKeyArray->populateEnvXPath(strXPath, index);
  341. }
  342. void CElement::loadXMLFromEnvXml(const ::IPropertyTree *pEnvTree)
  343. {
  344. //PROGLOG("Mapping element with XPATH of %s to %p", this->getEnvXPath(), this);
  345. //CConfigSchemaHelper::getInstance()->getSchemaMapManager()->addMapOfXPathToElement(this->getEnvXPath(), this);
  346. if (m_pComplexTypeArray != nullptr)
  347. {
  348. try
  349. {
  350. m_pComplexTypeArray->loadXMLFromEnvXml(pEnvTree);
  351. }
  352. catch (...)
  353. {
  354. // node described in XSD doesn't exist in XML
  355. // time to do validation?
  356. }
  357. }
  358. if (m_pSimpleType != nullptr)
  359. {
  360. try
  361. {
  362. m_pSimpleType->loadXMLFromEnvXml(pEnvTree);
  363. }
  364. catch(...)
  365. {
  366. }
  367. }
  368. if (m_pComplexTypeArray == nullptr)
  369. {
  370. const char* pValue = pEnvTree->queryPropTree(this->getEnvXPath())->queryProp("");
  371. if (pValue != nullptr)
  372. {
  373. this->setEnvValueFromXML(pValue);
  374. CConfigSchemaHelper::getInstance()->appendElementXPath(this->getEnvXPath());
  375. }
  376. }
  377. const char* pInstanceName = pEnvTree->queryPropTree(this->getEnvXPath())->queryProp(XML_ATTR_NAME);
  378. if (pInstanceName != nullptr && *pInstanceName != 0)
  379. this->setInstanceName(pInstanceName);
  380. }
  381. bool CElement::isTopLevelElement() const
  382. {
  383. return m_bTopLevelElement;
  384. }
  385. const char * CElement::getViewType() const
  386. {
  387. if(m_pAnnotation != nullptr && m_pAnnotation->getAppInfo() != nullptr)
  388. return m_pAnnotation->getAppInfo()->getViewType();
  389. return nullptr;
  390. }
  391. void CElementArray::dump(::std::ostream &cout, unsigned int offset) const
  392. {
  393. offset+= STANDARD_OFFSET_1;
  394. quickOutHeader(cout, XSD_ELEMENT_ARRAY_STR, offset);
  395. QUICK_OUT(cout, XSDXPath, offset);
  396. QUICK_OUT(cout, EnvXPath, offset);
  397. QUICK_OUT_ARRAY(cout, offset);
  398. quickOutFooter(cout, XSD_ELEMENT_ARRAY_STR, offset);
  399. }
  400. void CElementArray::getDocumentation(::StringBuffer &strDoc) const
  401. {
  402. QUICK_DOC_ARRAY(strDoc);
  403. }
  404. void CElementArray::getJSON(::StringBuffer &strJSON, unsigned int offset, int idx) const
  405. {
  406. offset += STANDARD_OFFSET_2;
  407. quickOutPad(strJSON, offset);
  408. int lidx = (idx == -1 ? 0 : idx);
  409. strJSON.append("{");
  410. (this->item(lidx)).getJSON(strJSON, offset+STANDARD_OFFSET_2, lidx);
  411. offset += STANDARD_OFFSET_2;
  412. quickOutPad(strJSON, offset);
  413. strJSON.append("}");
  414. }
  415. void CElementArray::populateEnvXPath(::StringBuffer strXPath, unsigned int index)
  416. {
  417. strXPath.appendf("/%s", this->item(0).getName());
  418. this->setEnvXPath(strXPath);
  419. int len = this->length();
  420. for (int idx=0; idx < len; idx++)
  421. {
  422. this->item(idx).populateEnvXPath(strXPath.str(), idx+1);
  423. CConfigSchemaHelper::stripXPathIndex(strXPath);
  424. }
  425. }
  426. const char* CElementArray::getXML(const char* /*pComponent*/)
  427. {
  428. if (m_strXML.length() == 0)
  429. {
  430. int length = this->length();
  431. for (int idx = 0; idx < length; idx++)
  432. {
  433. CElement &Element = this->item(idx);
  434. m_strXML.append(Element.getXML(nullptr));
  435. if (idx+1 < length)
  436. m_strXML.append("\n");
  437. }
  438. }
  439. return m_strXML.str();
  440. }
  441. void CElementArray::loadXMLFromEnvXml(const ::IPropertyTree *pEnvTree)
  442. {
  443. ::StringBuffer strEnvXPath(this->getEnvXPath());
  444. int subIndex = 1;
  445. do
  446. {
  447. CElement *pElement = nullptr;
  448. strEnvXPath.appendf("[%d]", subIndex);
  449. if (pEnvTree->hasProp(strEnvXPath.str()) == false)
  450. return;
  451. if (subIndex == 1)
  452. pElement = CConfigSchemaHelper::getInstance()->getSchemaMapManager()->getElementFromXPath(strEnvXPath.str());
  453. else
  454. {
  455. pElement = CElement::load(this, this->getSchemaRoot(), this->getXSDXPath(), false);
  456. this->append(*pElement);
  457. }
  458. if (subIndex > 1)
  459. pElement->populateEnvXPath(this->getEnvXPath(), subIndex);
  460. pElement->setTopLevelElement(false);
  461. pElement->loadXMLFromEnvXml(pEnvTree);
  462. CConfigSchemaHelper::stripXPathIndex(strEnvXPath);
  463. subIndex++;
  464. } while (true);
  465. }
  466. CElementArray* CElementArray::load(const char* pSchemaFile)
  467. {
  468. assert(pSchemaFile != nullptr);
  469. if (pSchemaFile == nullptr)
  470. return nullptr;
  471. typedef ::IPropertyTree jlibIPropertyTree;
  472. ::Linked<jlibIPropertyTree> pSchemaRoot;
  473. ::StringBuffer schemaPath;
  474. schemaPath.appendf("%s%s", DEFAULT_SCHEMA_DIRECTORY, pSchemaFile);
  475. pSchemaRoot.setown(createPTreeFromXMLFile(schemaPath.str()));
  476. CElementArray *pElemArray = CElementArray::load(nullptr, pSchemaRoot, XSD_TAG_ELEMENT);
  477. return pElemArray;
  478. }
  479. CElementArray* CElementArray::load(CXSDNodeBase* pParentNode, const ::IPropertyTree *pSchemaRoot, const char* xpath)
  480. {
  481. assert(pSchemaRoot != nullptr);
  482. if (pSchemaRoot == nullptr)
  483. return nullptr;
  484. CElementArray *pElemArray = new CElementArray(pParentNode);
  485. pSchemaRoot->Link();
  486. pElemArray->setSchemaRoot(pSchemaRoot);
  487. ::StringBuffer strXPathExt(xpath);
  488. pElemArray->setXSDXPath(xpath);
  489. CElement *pElem = CElement::load(pElemArray, pSchemaRoot, strXPathExt.str());
  490. assert(pElem);
  491. pElemArray->append(*pElem);
  492. SETPARENTNODE(pElemArray, pParentNode);
  493. return pElemArray;
  494. }
  495. int CElementArray::getCountOfSiblingElements(const char *pXPath) const
  496. {
  497. assert(pXPath != nullptr && *pXPath != 0);
  498. int count = 0;
  499. for (int idx=0; idx < this->length(); idx++)
  500. {
  501. if (strcmp(this->item(idx).getXSDXPath(), pXPath) == 0)
  502. count++;
  503. }
  504. return count;
  505. }
  506. const CXSDNodeBase* CElementArray::getNodeByTypeAndNameAscending(NODE_TYPES eNodeType, const char *pName) const
  507. {
  508. assert(pName != nullptr);
  509. if (!pName || !*pName)
  510. return nullptr;
  511. int len = this->length();
  512. for (int idx = 1; idx < len && eNodeType == XSD_ELEMENT; idx++)
  513. {
  514. if (strcmp ((static_cast<CElement>(this->item(idx))).getName(), pName) == 0)
  515. return &(this->item(idx));
  516. }
  517. return (this->getParentNode()->getNodeByTypeAndNameAscending(eNodeType, pName));
  518. }
  519. const CXSDNodeBase* CElementArray::getNodeByTypeAndNameDescending(NODE_TYPES eNodeType, const char *pName) const
  520. {
  521. assert(pName != nullptr);
  522. if (eNodeType == this->getNodeType())
  523. return this;
  524. return (this->getParentNode()->getNodeByTypeAndNameDescending(eNodeType, pName));
  525. }
  526. const CElement* CElementArray::getElementByNameAscending(const char *pName) const
  527. {
  528. int len = this->length();
  529. for (int idx = 1; idx < len; idx++)
  530. {
  531. if (strcmp ((static_cast<CElement>(this->item(idx))).getName(), pName) == 0)
  532. return &(this->item(idx));
  533. }
  534. assert(!("Control should not reach here, unknown pName?"));
  535. return nullptr;
  536. }
  537. int CElementArray::getSiblingIndex(const char* pXSDXPath, const CElement* pElement)
  538. {
  539. assert(pXSDXPath != nullptr && *pXSDXPath != 0 && pElement != nullptr);
  540. int nSiblingIndex = 0;
  541. int len =this->length();
  542. for (int idx=0; idx < len; idx++)
  543. {
  544. if (strcmp(this->item(idx).getXSDXPath(), pXSDXPath) == 0)
  545. {
  546. if (&(this->item(idx)) == pElement)
  547. break;
  548. nSiblingIndex++;
  549. }
  550. }
  551. return nSiblingIndex;
  552. }
  553. bool CElementArray::anyElementsHaveMaxOccursGreaterThanOne() const
  554. {
  555. int len = this->length();
  556. for (int i = 0; i < len; i++)
  557. {
  558. if ((this->item(i)).getMaxOccursInt() > 1 || this->item(i).getMaxOccursInt() == -1)
  559. return true;
  560. }
  561. return false;
  562. }
  563. void CElement::setIsInXSD(bool b)
  564. {
  565. m_bIsInXSD = b;
  566. if (m_bIsInXSD == true)
  567. {
  568. CElementArray *pElemArray = dynamic_cast<CElementArray*>(this->getParentNode());
  569. assert(pElemArray != nullptr);
  570. if (pElemArray != nullptr)
  571. pElemArray->incCountOfElementsInXSD();
  572. }
  573. }
  574. bool CElement::hasChildElements() const
  575. {
  576. const CComplexTypeArray* pComplexTypeArray = this->getComplexTypeArray();
  577. if (pComplexTypeArray != nullptr && pComplexTypeArray->length() != 0)
  578. {
  579. int nLen = pComplexTypeArray->length();
  580. for (int i = 0; i < nLen; i++)
  581. {
  582. if (pComplexTypeArray->item(i).hasChildElements() == true)
  583. return true;
  584. }
  585. }
  586. return false;
  587. }
  588. CArrayOfElementArrays* CArrayOfElementArrays::load(CXSDNodeBase* pParentNode, const ::IPropertyTree *pSchemaRoot, const char* xpath)
  589. {
  590. assert(pSchemaRoot != nullptr);
  591. if (pSchemaRoot == nullptr)
  592. return nullptr;
  593. CArrayOfElementArrays *pArrayOfElementArrays = new CArrayOfElementArrays(pParentNode);
  594. ::StringBuffer strXPathExt(xpath);
  595. pArrayOfElementArrays->setXSDXPath(xpath);
  596. typedef ::IPropertyTreeIterator jlibIPropertyTreeIterator;
  597. Owned<jlibIPropertyTreeIterator> elemIter = pSchemaRoot->getElements(xpath);
  598. int count = 1;
  599. ForEach(*elemIter)
  600. {
  601. strXPathExt.set(xpath);
  602. strXPathExt.appendf("[%d]", count);
  603. CElementArray *pElemArray = CElementArray::load(pArrayOfElementArrays, pSchemaRoot, strXPathExt.str());
  604. pArrayOfElementArrays->append(*pElemArray);
  605. count++;
  606. }
  607. return pArrayOfElementArrays;
  608. }
  609. void CArrayOfElementArrays::getDocumentation(::StringBuffer &strDoc) const
  610. {
  611. int len = this->length();
  612. for (int i = 0; i < len; i++)
  613. {
  614. this->item(i).getDocumentation(strDoc);
  615. }
  616. }
  617. void CArrayOfElementArrays::populateEnvXPath(::StringBuffer strXPath, unsigned int index)
  618. {
  619. ::StringBuffer strCopy(strXPath);
  620. CConfigSchemaHelper::stripXPathIndex(strCopy);
  621. this->setEnvXPath(strCopy);
  622. int len = this->length();
  623. for (int i = 0; i < len; i++)
  624. {
  625. this->item(i).populateEnvXPath(strXPath.str());
  626. CConfigSchemaHelper::getInstance()->getSchemaMapManager()->addMapOfXSDXPathToElementArray(this->item(i).getXSDXPath(), &(this->item(i)));
  627. }
  628. }
  629. void CArrayOfElementArrays::loadXMLFromEnvXml(const ::IPropertyTree *pEnvTree)
  630. {
  631. int len = this->ordinality();
  632. for (int i = 0; i < len; i++)
  633. {
  634. this->item(i).loadXMLFromEnvXml(pEnvTree);
  635. }
  636. }
  637. void CArrayOfElementArrays::getJSON(::StringBuffer &strJSON, unsigned int offset, int idx) const
  638. {
  639. int len = this->ordinality();
  640. for (int i = 0; i < len; i++)
  641. {
  642. if (i != 0)
  643. strJSON.append(",\n");
  644. this->item(i).getJSON(strJSON, offset);
  645. }
  646. }