SchemaElement.cpp 27 KB

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