esdl_transformer2.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2013 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. #pragma warning(disable : 4786)
  14. #include "esdl_transformer2.ipp"
  15. #include "xpp/xpputils.h"
  16. #include <memory>
  17. #include "rtlformat.hpp"
  18. #include "eclhelper.hpp" //IXMLWriter
  19. #include "thorxmlwrite.hpp" //JSON WRITER
  20. #include "eclrtl.hpp"
  21. #define LOGDATASETTAG "LogDatasets"
  22. using namespace std;
  23. // Uncomment this to debug ESDL issues
  24. //#define DEBUG_ESDL
  25. #ifdef _WIN32
  26. #ifdef DEBUG_ESDL
  27. #define ESDL_DBG DBGLOG
  28. #elif _MSC_VER>1200
  29. #define ESDL_DBG __noop
  30. #else
  31. #if _MSC_VER<=1300
  32. #define ESDL_DBG (void)0
  33. #else
  34. #define ESDL_DBG __noop
  35. #endif
  36. #endif
  37. #else
  38. #ifdef DEBUG_ESDL
  39. #define ESDL_DBG(format,...) DBGLOG(format,##__VA_ARGS__)
  40. #else
  41. #define ESDL_DBG(format,...)
  42. #endif
  43. #endif
  44. using namespace xpp;
  45. // ======================================================================================
  46. // primitive type lookup
  47. static bool gotoStartTag(XmlPullParser &xppx, const char *name, const char *dsname)
  48. {
  49. int level = 1;
  50. int type = XmlPullParser::END_TAG;
  51. StartTag stag;
  52. while(level > 0)
  53. {
  54. type = xppx.next();
  55. switch(type)
  56. {
  57. case XmlPullParser::START_TAG:
  58. {
  59. xppx.readStartTag(stag);
  60. ++level;
  61. const char *tag = stag.getLocalName();
  62. if (name && !stricmp(name, tag))
  63. return true;
  64. else if (dsname && *dsname && !stricmp(tag, "Dataset"))
  65. {
  66. const char *nametag=stag.getValue("name");
  67. if (nametag && *nametag)
  68. {
  69. if (!stricmp(nametag, dsname))
  70. return true;
  71. else if (name)
  72. {
  73. if (!stricmp(nametag, name))
  74. return true;
  75. int len = strlen(name);
  76. if (len > 2 && !stricmp(name+len-2, "ex") && !strnicmp(nametag, name, len-2))
  77. return true;
  78. }
  79. }
  80. }
  81. break;
  82. }
  83. case XmlPullParser::END_TAG:
  84. --level;
  85. break;
  86. }
  87. }
  88. return false;
  89. }
  90. Esdl2Base* createEsdlObject(Esdl2Transformer *xformer, IEsdlDefObject *def)
  91. {
  92. EsdlDefTypeId type = def->getEsdlType();
  93. switch(type)
  94. {
  95. case EsdlTypeStruct:
  96. return new Esdl2Struct(xformer, dynamic_cast<IEsdlDefStruct*>(def));
  97. case EsdlTypeElement:
  98. return new Esdl2Element(xformer, def);
  99. case EsdlTypeArray:
  100. return new Esdl2Array(xformer, def);
  101. case EsdlTypeEnumDef:
  102. return new Esdl2EnumItem(xformer, def);
  103. case EsdlTypeEnumRef:
  104. return new Esdl2EnumRef(xformer, def);
  105. case EsdlTypeAttribute:
  106. return new Esdl2Attribute(xformer, def);
  107. case EsdlTypeRequest:
  108. return new Esdl2Request(xformer, dynamic_cast<IEsdlDefStruct*>(def));
  109. case EsdlTypeResponse:
  110. return new Esdl2Response(xformer, dynamic_cast<IEsdlDefStruct*>(def));
  111. case EsdlTypeMethod:
  112. return new Esdl2Method(xformer, dynamic_cast<IEsdlDefMethod*>(def));
  113. case EsdlTypeService:
  114. return new Esdl2Service(xformer, def);
  115. default:
  116. return NULL;
  117. }
  118. }
  119. // ======================================================================================
  120. // class Esdl2LocalContext
  121. void Esdl2LocalContext::handleDataFor(IXmlWriterExt & writer)
  122. {
  123. if (m_dataFor || m_dataOrig)
  124. {
  125. // values available in both orig and dataFor: keep the orig
  126. if (m_dataOrig && m_dataFor)
  127. {
  128. for (unsigned i=0; i<m_dataOrig->ordinality(); i++)
  129. {
  130. const char* name = m_dataOrig->item(i);
  131. if (m_dataFor->remove(name))
  132. ESDL_DBG("Data available for '%s' twice: data_for and orig; the orig wins", name);
  133. }
  134. }
  135. // only available in dataFor
  136. if (m_dataFor)
  137. {
  138. HashIterator it(*m_dataFor);
  139. for (it.first(); it.isValid(); it.next())
  140. {
  141. IMapping& et = it.query();
  142. auto val = m_dataFor->mapToValue(&et)->get();
  143. writer.outputInline(val);
  144. }
  145. }
  146. }
  147. }
  148. // ======================================================================================
  149. // class Esdl2Base
  150. Esdl2Base::Esdl2Base(Esdl2Transformer *xformer, IEsdlDefObject* def, EsdlBasicElementType t, bool might_skip_root_)
  151. : m_def(def), might_skip_root(might_skip_root_), data_for(NULL), type_id(t)
  152. {
  153. if (def->queryProp("optional"))
  154. param_group.set(def->queryProp("optional"));
  155. if (def->queryProp("counter"))
  156. count_output = true;
  157. const char *count_flag = def->queryProp("count_val");
  158. if (!stricmp(queryName(), "RecordCount") || count_flag)
  159. {
  160. if (count_flag==NULL || *count_flag!='0')
  161. count_value = true;
  162. }
  163. if (def->queryProp("xml_tag"))
  164. xml_tag.set(def->queryProp("xml_tag"));
  165. if (xml_tag.isEmpty())
  166. xml_tag.set(queryName());
  167. }
  168. Esdl2Base::~Esdl2Base()
  169. {
  170. }
  171. void Esdl2Base::serialize(StringBuffer &out, const char *type)
  172. {
  173. out.appendf("<%s", type);
  174. serialize_attributes(out);
  175. if (!hasChild())
  176. out.append("/>");
  177. else
  178. {
  179. out.append(">");
  180. serialize_children(out);
  181. out.appendf("</%s>", type);
  182. }
  183. }
  184. void Esdl2Base::serialize_attributes(StringBuffer &out)
  185. {
  186. Owned<IPropertyIterator> piter = m_def->getProps();
  187. ForEach(*piter)
  188. {
  189. const char *key = piter->getPropKey();
  190. if (key && *key)
  191. {
  192. if (stricmp(key, "base_type"))
  193. {
  194. const char *value = m_def->queryProp(key);
  195. if (value && *value)
  196. out.appendf(" %s=\"%s\"", key, value);
  197. }
  198. }
  199. }
  200. }
  201. // return true if it passed optional check and version check
  202. bool Esdl2Base::checkVersion(Esdl2TransformerContext &ctx)
  203. {
  204. if (!param_group.isEmpty())
  205. {
  206. if (param_group.get()[0] == '!')
  207. {
  208. if (ctx.param_groups && ctx.param_groups->hasProp(param_group.get()+1))
  209. return false;
  210. }
  211. else
  212. {
  213. if (!ctx.param_groups || !ctx.param_groups->hasProp(param_group.get()))
  214. return false;
  215. }
  216. }
  217. return m_def->checkVersion(ctx.client_ver);
  218. }
  219. void Esdl2Base::countContent(Esdl2TransformerContext &ctx)
  220. {
  221. StringBuffer content;
  222. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  223. {
  224. switch(type)
  225. {
  226. case XmlPullParser::START_TAG: //shouldn't have nested tags, skip
  227. {
  228. StartTag temp;
  229. ctx.xppp->readStartTag(temp);
  230. ctx.xppp->skipSubTree();
  231. break;
  232. }
  233. case XmlPullParser::CONTENT: //support multiple content items, append
  234. {
  235. content.append(ctx.xppp->readContent());
  236. break;
  237. }
  238. }
  239. }
  240. if (content.trim().length() && (queryEclNull()==NULL || strcmp(queryEclNull(), content.str())))
  241. {
  242. if (type_id==ESDLT_BOOL)
  243. {
  244. if (!stricmp(content.str(), "true")||!strcmp(content.str(), "1"))
  245. content.clear().append('1');
  246. else
  247. content.clear().append('0');
  248. }
  249. ctx.counter=atoi(content.str());
  250. }
  251. }
  252. void Esdl2Base::output_content(Esdl2TransformerContext &ctx, IPropertyTree *pt)
  253. {
  254. output_content(ctx, pt, xml_tag.str());
  255. }
  256. void Esdl2Base::output_content(Esdl2TransformerContext &ctx, const char * content, const char *tagname, unsigned leadinzeros)
  257. {
  258. if (content && *content && tagname && *tagname && (queryEclNull()==NULL || !streq(queryEclNull(), content)))
  259. {
  260. unsigned contentlen = strlen(content);
  261. if (leadinzeros > 0 )
  262. {
  263. StringBuffer padded;
  264. if (leadinzeros > contentlen)
  265. padded.appendN(leadinzeros - contentlen,'0');
  266. padded.append(content);
  267. ctx.writer->outputCString(padded.str(), tagname);
  268. }
  269. else
  270. {
  271. switch (type_id)
  272. {
  273. case ESDLT_BOOL:
  274. ctx.writer->outputBool(strToBool(content), tagname);
  275. break;
  276. case ESDLT_INT8:
  277. case ESDLT_INT16:
  278. case ESDLT_INT32:
  279. case ESDLT_INT64:
  280. ctx.writer->outputInt(atoi(content), sizeof(int), tagname);
  281. break;
  282. case ESDLT_UINT8:
  283. case ESDLT_UINT16:
  284. case ESDLT_UINT32:
  285. case ESDLT_UINT64:
  286. ctx.writer->outputUInt(atoi(content), sizeof(unsigned), tagname);
  287. break;
  288. case ESDLT_BYTE:
  289. case ESDLT_UBYTE:
  290. ctx.writer->outputData(1, content, tagname);
  291. break;
  292. case ESDLT_FLOAT:
  293. case ESDLT_DOUBLE:
  294. ctx.writer->outputNumericString(content, tagname);
  295. break;
  296. case ESDLT_STRING:
  297. default:
  298. ctx.writer->outputUtf8(rtlUtf8Length(strlen(content),content), content, tagname);
  299. break;
  300. }
  301. }
  302. if (count_output)
  303. ctx.counter++;
  304. if (count_value)
  305. ctx.counter=atoi(content);
  306. }
  307. }
  308. void Esdl2Base::output_content(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *tagname)
  309. {
  310. StringBuffer content(pt->queryProp(NULL));
  311. const char* leadingZeroStr = m_def->queryProp("leading_zero");
  312. unsigned leadingZero = (leadingZeroStr && *leadingZeroStr) ? atoi(leadingZeroStr) : 0;
  313. output_content(ctx, content.str(), tagname, leadingZero);
  314. }
  315. void Esdl2Base::output_content(Esdl2TransformerContext &ctx, const char *tagname)
  316. {
  317. StringBuffer content;
  318. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  319. {
  320. switch(type)
  321. {
  322. case XmlPullParser::START_TAG: //shouldn't have nested tags, skip
  323. {
  324. StartTag temp;
  325. ctx.xppp->readStartTag(temp);
  326. ctx.xppp->skipSubTree();
  327. break;
  328. }
  329. case XmlPullParser::CONTENT: //support multiple content items, append
  330. {
  331. content.append(ctx.xppp->readContent());
  332. break;
  333. }
  334. }
  335. }
  336. const char* lz = m_def->queryProp("leading_zero");
  337. unsigned leadingZero = (lz && *lz) ? atoi(lz) : 0;
  338. output_content(ctx, content.str(), tagname, leadingZero);
  339. }
  340. void Esdl2Base::output_content(Esdl2TransformerContext &ctx)
  341. {
  342. output_content(ctx, xml_tag.str());
  343. }
  344. void Esdl2Base::output_ecl_date(Esdl2TransformerContext &ctx, const char *tagname)
  345. {
  346. int Month=0;
  347. int Day=0;
  348. int Year=0;
  349. StartTag child;
  350. StringBuffer content;
  351. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  352. {
  353. switch(type)
  354. {
  355. case XmlPullParser::START_TAG: //shouldn't have nested tags, skip
  356. {
  357. ctx.xppp->readStartTag(child);
  358. readFullContent(*ctx.xppp, content.clear());
  359. const char *tag = child.getLocalName();
  360. if (!stricmp(tag, "Month"))
  361. Month = atoi(content.str());
  362. else if (!stricmp(tag, "Day"))
  363. Day = atoi(content.str());
  364. else if (!stricmp(tag, "Year"))
  365. Year = atoi(content.str());
  366. break;
  367. }
  368. }
  369. }
  370. StringBuffer date;
  371. if (Year>1000 && Year<9999)
  372. date.append(Year);
  373. else
  374. date.append("0000");
  375. if (Month<1 || Month>12)
  376. date.append("00");
  377. else
  378. {
  379. if (Month<10)
  380. date.append('0');
  381. date.append(Month);
  382. }
  383. if (Day<1 || Day>31)
  384. date.append("00");
  385. else
  386. {
  387. if (Day<10)
  388. date.append('0');
  389. date.append(Day);
  390. }
  391. if (date.length())
  392. {
  393. ctx.writer->outputCString(date.str(), tagname);
  394. if (count_output)
  395. ctx.counter++;
  396. }
  397. }
  398. void Esdl2Base::addChildren(Esdl2Transformer *xformer, IEsdlDefObjectIterator *it)
  399. {
  400. assert(false);
  401. }
  402. Esdl2Base* Esdl2Base::queryChild(const char* name, bool nocase)
  403. {
  404. assert(false);
  405. return NULL;
  406. }
  407. void Esdl2Base::mergeBaseType(Esdl2Transformer *xformer, const char *base_type)
  408. {
  409. if (esdlSimpleType(base_type)==ESDLT_COMPLEX)
  410. {
  411. Esdl2Base *esdlBase = xformer->queryType(base_type);
  412. if (!esdlBase)
  413. {
  414. StringBuffer msg;
  415. msg.appendf("ESDL Initialization Error: BaseType=%s, not found for item %s", base_type, queryName());
  416. throw MakeStringExceptionDirect(-1, msg.str());
  417. }
  418. IEsdlDefObject* base = esdlBase->queryEsdlDefObject();
  419. // recursive
  420. if (base->queryProp("base_type"))
  421. mergeBaseType(xformer, base->queryProp("base_type"));
  422. //merge base children
  423. IEsdlDefStruct* st = dynamic_cast<IEsdlDefStruct*>(base);
  424. if (st)
  425. {
  426. Owned<IEsdlDefObjectIterator> it = st->getChildren();
  427. addChildren(xformer, it.get());
  428. }
  429. }
  430. }
  431. // ======================================================================================
  432. // class Esdl2Element
  433. Esdl2Element::Esdl2Element(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def), esdl_type(NULL)
  434. {
  435. complex_type.set(def->queryProp("complex_type"));
  436. simple_type.set(def->queryProp("type"));
  437. if (!simple_type.isEmpty())
  438. {
  439. type_id = esdlSimpleType(simple_type.get());
  440. if (type_id==ESDLT_COMPLEX)
  441. {
  442. DBGLOG("ESDL simple type not defined: %s", simple_type.get());
  443. assert(!"Error");
  444. }
  445. }
  446. else
  447. {
  448. type_id=ESDLT_COMPLEX;
  449. assert(complex_type.get());
  450. }
  451. }
  452. void Esdl2Element::buildDefaults(Esdl2Transformer *xformer, StringBuffer &path, IProperties *defvals)
  453. {
  454. if (type_id==ESDLT_COMPLEX)
  455. {
  456. int curlen = path.length();
  457. if (path.length())
  458. path.append("/");
  459. path.append(queryName());
  460. if (!esdl_type)
  461. {
  462. assert(complex_type.get());
  463. Esdl2Base *type_entry = xformer->queryType(complex_type.get());
  464. if (type_entry)
  465. esdl_type = type_entry;
  466. else
  467. DBGLOG("ESDL Type not defined \"%s\" in \"%s\"", complex_type.get(), queryName());
  468. }
  469. if (esdl_type)
  470. esdl_type->buildDefaults(xformer, path, defvals);
  471. path.setLength(curlen);
  472. }
  473. else if (!queryDefaultValue())
  474. {
  475. int curlen = path.length();
  476. if (path.length())
  477. path.append("/");
  478. path.append(queryName());
  479. defvals->setProp(path.str(), queryDefaultValueS());
  480. path.setLength(curlen);
  481. }
  482. }
  483. void Esdl2Element::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count)
  484. {
  485. ESDL_DBG("EsdlElement::process(pt): %s", queryName());
  486. if (data_for && data_for->checkVersion(ctx))
  487. {
  488. throw MakeStringException(-1, "EsdlElement::process(pt):%s: IPTree version of data_for not implemented", queryName());
  489. }
  490. else if (!checkVersion(ctx))
  491. {
  492. if (count_value)
  493. countContent(ctx);
  494. }
  495. else if (complex_type.isEmpty())
  496. {
  497. output_content(ctx, pt);
  498. }
  499. else
  500. {
  501. if (!esdl_type)
  502. {
  503. Esdl2Base *type_entry = ctx.queryType(complex_type.get());
  504. if (type_entry)
  505. esdl_type = type_entry;
  506. else
  507. DBGLOG("%s: ESDL Type not defined \"%s\" in \"%s\"", ctx.root_type.get(), complex_type.get(), queryName());
  508. }
  509. if (esdl_type)
  510. {
  511. const char* tag = NULL;
  512. if(ctx.skip_root && might_skip_root)
  513. tag = NULL;
  514. else
  515. tag = queryOutputName(ctx);
  516. esdl_type->process(ctx, pt, tag, NULL, count_output);
  517. }
  518. }
  519. }
  520. void Esdl2Element::process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local,bool count)
  521. {
  522. ESDL_DBG("EsdlElement::process: %s", queryName());
  523. if (data_for && data_for->checkVersion(ctx))
  524. {
  525. ESDL_DBG("DataFor %s processed", data_for->queryName());
  526. if (local)
  527. local->dataForProcessed = true;
  528. data_for->process(ctx,out_name,NULL,count);
  529. }
  530. else if (!checkVersion(ctx))
  531. {
  532. if (count_value)
  533. countContent(ctx);
  534. else
  535. ctx.xppp->skipSubTree();
  536. }
  537. else if (complex_type.isEmpty())
  538. {
  539. output_content(ctx);
  540. }
  541. else
  542. {
  543. if (!esdl_type)
  544. {
  545. Esdl2Base *type_entry = ctx.queryType(complex_type.get());
  546. if (type_entry)
  547. esdl_type = type_entry;
  548. else
  549. DBGLOG("%s: ESDL Type not defined \"%s\" in \"%s\"", ctx.root_type.get(), complex_type.get(), queryName());
  550. }
  551. if (esdl_type)
  552. {
  553. const char* tag = NULL;
  554. if(ctx.skip_root && might_skip_root)
  555. tag = NULL;
  556. else if(ctx.mode==EsdlRequestMode)
  557. tag = queryName();
  558. else
  559. tag = xml_tag.get();
  560. esdl_type->process(ctx,tag,local,count_output);
  561. }
  562. else
  563. ctx.xppp->skipSubTree();
  564. }
  565. }
  566. // ======================================================================================
  567. // class Esdl2Array
  568. Esdl2Array::Esdl2Array(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def), esdl_type(NULL)
  569. {
  570. type_unknown=false;
  571. inited=false;
  572. IEsdlDefArray* defArray = dynamic_cast<IEsdlDefArray*>(def);
  573. isEsdlList = defArray->checkIsEsdlList();
  574. const char *atype = def->queryProp("type");
  575. if (atype)
  576. {
  577. type.set(atype);
  578. type_id = esdlSimpleType(atype);
  579. }
  580. const char* itag = def->queryProp("item_tag");
  581. if (itag)
  582. item_tag.set(itag);
  583. else if (!atype || !stricmp(atype, "string")) // defuault for simple type
  584. item_tag.set("Item");
  585. else // defuault for complex type
  586. item_tag.set(atype);
  587. // flat_array
  588. //if (def->queryProp("@flat_array"))
  589. // name.set(item_tag.get());
  590. }
  591. void Esdl2Array::init(Esdl2TransformerContext &ctx)
  592. {
  593. if (!inited)
  594. {
  595. if (type_id==ESDLT_COMPLEX && !esdl_type)
  596. {
  597. Esdl2Base *type_entry = ctx.queryType(type.get());
  598. if (type_entry)
  599. esdl_type = type_entry;
  600. else
  601. DBGLOG("%s: ESDL Type not defined \"%s\" in \"%s\"", ctx.root_type.get(), type.get(), queryName());
  602. }
  603. if (type_id==ESDLT_COMPLEX && !esdl_type)
  604. type_unknown=true;
  605. inited=true;
  606. }
  607. }
  608. void Esdl2Array::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count)
  609. {
  610. ESDL_DBG("EsdlArray::process(pt): %s", queryName());
  611. if (!inited)
  612. init(ctx);
  613. bool flat_array = m_def->hasProp("flat_array");
  614. if (data_for && data_for->checkVersion(ctx))
  615. {
  616. throw MakeStringException(-1, "EsdlElement::process(pt):%s: IPTree version of data_for not implemented", queryName());
  617. }
  618. else if (type_unknown)
  619. {
  620. DBGLOG("EsdlArray type (%s) unknown", type.get());
  621. }
  622. else if (!checkVersion(ctx))
  623. {
  624. ctx.xppp->skipSubTree();
  625. }
  626. else if (flat_array)
  627. {
  628. int curlen = ctx.writer->length();
  629. if (esdl_type)
  630. esdl_type->process(ctx, item_tag.get(), local, count_output);
  631. else
  632. output_content(ctx, item_tag.get());
  633. if (ctx.writer->length() != curlen && count)
  634. ctx.counter++;
  635. }
  636. else if (isEsdlList)
  637. {
  638. int curlen = ctx.writer->length();
  639. const char *tagname = queryOutputName(ctx);
  640. if (esdl_type)
  641. esdl_type->process(ctx, pt, tagname, NULL, count_output);
  642. else
  643. output_content(ctx, pt, tagname);
  644. if (ctx.writer->length() != curlen && count)
  645. ctx.counter++;
  646. }
  647. else
  648. {
  649. const char *tagname = queryOutputName(ctx);
  650. if (pt->hasChildren())
  651. {
  652. Owned<IInterface> prevLocation = ctx.writer->saveLocation();
  653. ctx.writer->outputBeginNested(tagname, true);
  654. ctx.writer->outputBeginArray(item_tag.get());
  655. Owned<IPropertyTreeIterator> it = pt->getElements(item_tag.get());
  656. int curlen = ctx.writer->length();
  657. ForEach(*it)
  658. {
  659. if (esdl_type)
  660. {
  661. esdl_type->process(ctx, &it->query(), item_tag.get(), NULL, count_output);
  662. }
  663. else
  664. output_content(ctx, &it->query(), item_tag.get());
  665. }
  666. if (ctx.writer->length() == curlen) //nothing was added... empty content remove opening tag
  667. {
  668. ctx.writer->outputEndArray(item_tag.get());
  669. ctx.writer->outputEndNested(tagname); //we need to close out the nested area first
  670. ctx.writer->rewindTo(prevLocation); //rewind
  671. }
  672. else
  673. {
  674. ctx.writer->outputEndArray(item_tag.get());
  675. ctx.writer->outputEndNested(tagname);
  676. if (count)
  677. ctx.counter++;
  678. }
  679. }
  680. }
  681. }
  682. void Esdl2Array::process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local,bool count)
  683. {
  684. ESDL_DBG("EsdlArray::process: %s", queryName());
  685. if (!inited)
  686. init(ctx);
  687. bool flat_array = m_def->hasProp("flat_array");
  688. if (data_for && data_for->checkVersion(ctx))
  689. {
  690. ESDL_DBG("DataFor %s processed", data_for->queryName());
  691. if (local)
  692. local->dataForProcessed = true;
  693. data_for->process(ctx,out_name,NULL,count);
  694. }
  695. else if (type_unknown)
  696. {
  697. ctx.xppp->skipSubTree();
  698. DBGLOG("EsdlArray type (%s) unknown", type.get());
  699. }
  700. else if (!checkVersion(ctx))
  701. ctx.xppp->skipSubTree();
  702. else if (flat_array)
  703. {
  704. int curlen = ctx.writer->length();
  705. if (esdl_type)
  706. esdl_type->process(ctx, item_tag.get(), local, count_output);
  707. else
  708. output_content(ctx, item_tag.get());
  709. if (ctx.writer->length() != curlen && count)
  710. ctx.counter++;
  711. }
  712. else if (isEsdlList)
  713. {
  714. int curlen = ctx.writer->length();
  715. const char *tagname = queryOutputName(ctx);
  716. if (esdl_type)
  717. esdl_type->process(ctx, tagname, NULL, count_output);
  718. else
  719. output_content(ctx, tagname);
  720. if (ctx.writer->length() != curlen && count)
  721. ctx.counter++;
  722. }
  723. else
  724. {
  725. Owned<IInterface> prevLocation = ctx.writer->saveLocation();
  726. ctx.writer->outputBeginNested(xml_tag.get(), true);
  727. ctx.writer->outputBeginArray(item_tag.get());
  728. int curlen = ctx.writer->length();
  729. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  730. {
  731. if (type == XmlPullParser::START_TAG)
  732. {
  733. StartTag child_start;
  734. ctx.xppp->readStartTag(child_start);
  735. if (!stricmp(child_start.getLocalName(), item_tag.get()))
  736. {
  737. if (esdl_type)
  738. esdl_type->process(ctx, item_tag.get(), NULL, count_output);
  739. else
  740. output_content(ctx, item_tag.get());
  741. }
  742. else
  743. ctx.xppp->skipSubTree();
  744. }
  745. }
  746. if (ctx.writer->length()==curlen) //nothing was added... empty content remove opening tag
  747. {
  748. ctx.writer->outputEndArray(item_tag.get());
  749. ctx.writer->outputEndNested(xml_tag.get()); // we need to close out this section first
  750. ctx.writer->rewindTo(prevLocation); //rewind
  751. }
  752. else
  753. {
  754. ctx.writer->outputEndArray(item_tag.get());
  755. ctx.writer->outputEndNested(xml_tag.get());
  756. if (count)
  757. ctx.counter++;
  758. }
  759. }
  760. }
  761. // ======================================================================================
  762. // class Esdl2Struct
  763. Esdl2Struct::Esdl2Struct(Esdl2Transformer *xformer, IEsdlDefStruct *def, EsdlBasicElementType t)
  764. : Esdl2Base(xformer, def, t, t==ESDLT_RESPONSE),isElement(false)
  765. {
  766. ESDL_DBG("Esdl2Struct: %s", def->queryName());
  767. if (def->queryProp("base_type"))
  768. {
  769. DBGLOG("mergeBaseType: %s", def->queryProp("base_type"));
  770. mergeBaseType(xformer, def->queryProp("base_type"));
  771. }
  772. if (def->hasProp("@element"))
  773. isElement = true;
  774. // add children
  775. Owned<IEsdlDefObjectIterator> chds = def->getChildren();
  776. addChildren(xformer,chds.get());
  777. }
  778. Esdl2Struct::~Esdl2Struct()
  779. {
  780. ForEachItemIn(idx, m_children)
  781. {
  782. Esdl2Base *child = &m_children.item(idx);
  783. child->Release();
  784. }
  785. HashIterator xti(xml_tags);
  786. for (xti.first(); xti.isValid(); xti.next())
  787. {
  788. IMapping& m = xti.query();
  789. EsdlBaseArrayPtr *ebap = xml_tags.mapToValue(&m);
  790. if (ebap && *ebap)
  791. delete *ebap;
  792. }
  793. }
  794. void Esdl2Struct::buildDefaults(Esdl2Transformer *xformer, StringBuffer &path, IProperties *defvals)
  795. {
  796. ForEachItemIn(idx, m_children)
  797. {
  798. Esdl2Base &child = m_children.item(idx);
  799. child.buildDefaults(xformer, path, defvals);
  800. }
  801. }
  802. Esdl2Base* Esdl2Struct::queryChild(const char* name, bool nocase)
  803. {
  804. Esdl2Base** child = NULL;
  805. if(nocase)
  806. child = m_child_nocasemap.getValue(StringBuffer(name).toLowerCase().str());
  807. else
  808. child = m_child_map.getValue(name);
  809. if(child && *child)
  810. return *child;
  811. return NULL;
  812. }
  813. void Esdl2Struct::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local_in, bool count)
  814. {
  815. ESDL_DBG("Esdl2Struct::process(pt): %s", queryName());
  816. if (checkVersion(ctx))
  817. {
  818. Owned<IInterface> prevLocation = ctx.writer->saveLocation();
  819. if (out_name && *out_name) {
  820. if (!might_skip_root || !ctx.skip_root)
  821. ctx.writer->outputBeginNested(out_name, true);
  822. }
  823. unsigned curlen = ctx.writer->length();
  824. Esdl2LocalContext local;
  825. ForEachItemIn(idx, m_children)
  826. {
  827. Esdl2Base &child = m_children.item(idx);
  828. if (child.checkVersion(ctx))
  829. {
  830. const char *tagname = child.queryInputName(ctx);
  831. if (pt->hasProp(tagname)||child.hasDefaults())
  832. {
  833. bool isEsdlList = false;
  834. IEsdlDefObject* def = child.queryEsdlDefObject();
  835. if (def->getEsdlType() == EsdlTypeArray)
  836. {
  837. IEsdlDefArray* defArray = dynamic_cast<IEsdlDefArray*>(def);
  838. isEsdlList = defArray->checkIsEsdlList();
  839. }
  840. if (!isEsdlList)
  841. child.process(ctx, pt->queryPropTree(tagname), child.queryOutputName(ctx), &local, count);
  842. else
  843. {
  844. Owned<IInterface> prevLocation = ctx.writer->saveLocation();
  845. ctx.writer->outputBeginArray(tagname);
  846. int curlen = ctx.writer->length();
  847. Owned<IPropertyTreeIterator> iter = pt->getElements(tagname);
  848. ForEach(*iter)
  849. child.process(ctx, &iter->query(), child.queryOutputName(ctx), &local, count);
  850. if (ctx.writer->length()==curlen) //nothing was added... empty content remove opening tag
  851. ctx.writer->rewindTo(prevLocation); //rewind
  852. else
  853. {
  854. ctx.writer->outputEndArray(tagname);
  855. if (count)
  856. ctx.counter++;
  857. }
  858. }
  859. }
  860. }
  861. }
  862. if (count && ctx.writer->length() > curlen)
  863. ctx.counter++;
  864. if (out_name && *out_name)
  865. {
  866. if (!ctx.skip_root || !might_skip_root)
  867. {
  868. if (ctx.writer->length() == curlen) //nothing was added, empty content, remove open tag
  869. {
  870. ctx.writer->outputEndNested(out_name); //we need to close out current section first
  871. ctx.writer->rewindTo(prevLocation); //rewind
  872. }
  873. else
  874. ctx.writer->outputEndNested(out_name);
  875. }
  876. }
  877. }
  878. }
  879. void Esdl2Struct::process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local_in, bool count)
  880. {
  881. ESDL_DBG("Esdl2Struct::process: %s", queryName());
  882. if (!checkVersion(ctx))
  883. ctx.xppp->skipSubTree();
  884. else
  885. {
  886. Owned<IInterface> prevLocation = ctx.writer->saveLocation();
  887. unsigned curlen = ctx.writer->length();
  888. if (out_name && *out_name)
  889. {
  890. if (!might_skip_root || !ctx.skip_root)
  891. {
  892. ctx.writer->outputBeginNested(out_name, true);
  893. curlen = ctx.writer->length();
  894. if (local_in && local_in->m_startTag)
  895. {
  896. int attcount = local_in->m_startTag->getLength();
  897. if (attcount)
  898. {
  899. for (int idx=0; idx<attcount; idx++)
  900. {
  901. StringBuffer attname("@");
  902. attname.append(local_in->m_startTag->getLocalName(idx));
  903. auto val = local_in->m_startTag->getValue(idx);
  904. ctx.writer->outputUtf8(rtlUtf8Length(strlen(val),val),val,attname.str());
  905. }
  906. }
  907. }
  908. }
  909. }
  910. StringBuffer esdlListName;
  911. unsigned esdlListItemCount = 0;
  912. Esdl2LocalContext local;
  913. StringBuffer completeContent;
  914. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  915. {
  916. switch(type)
  917. {
  918. case XmlPullParser::CONTENT:
  919. {
  920. if(isElement)
  921. {
  922. completeContent.append(ctx.xppp->readContent());
  923. }
  924. break;
  925. }
  926. case XmlPullParser::START_TAG:
  927. {
  928. StartTag child_start;
  929. ctx.xppp->readStartTag(child_start);
  930. if (isElement)
  931. ctx.xppp->skipSubTree();
  932. else
  933. {
  934. local.m_startTag = &child_start;
  935. Esdl2Base *child = queryChild(child_start.getLocalName());
  936. if (!child || !child->checkVersion(ctx))
  937. {
  938. if(ctx.mode==EsdlRequestMode)
  939. {
  940. EsdlBaseArrayPtr * arrayPtr = xml_tags.getValue(child_start.getLocalName());
  941. if(arrayPtr && *arrayPtr)
  942. {
  943. EsdlBaseArray& array = **arrayPtr;
  944. ForEachItemIn(idx, array)
  945. {
  946. Esdl2Base *base = &array.item(idx);
  947. if(base->checkVersion(ctx))
  948. {
  949. child = base;
  950. break;
  951. }
  952. }
  953. }
  954. }
  955. }
  956. if (!child && type_id==ESDLT_RESPONSE && strieq("Row", child_start.getLocalName()))
  957. child = queryChild("response", true);
  958. if (child)
  959. {
  960. Esdl2Base& chd = *child;
  961. unsigned len = ctx.writer->length();
  962. Owned<IInterface> location = ctx.writer->saveLocation();
  963. local.dataForProcessed = false;
  964. const char* tagName = child_start.getLocalName();
  965. if (!esdlListName.isEmpty())
  966. {
  967. if (streq(tagName, esdlListName.str()))
  968. esdlListItemCount++;
  969. else
  970. { //A different esdl tag is coming. We need to close the last EsdlList.
  971. ctx.writer->outputEndArray(esdlListName.str());
  972. esdlListName.clear();
  973. esdlListItemCount = 0;
  974. location.setown(ctx.writer->saveLocation());
  975. }
  976. }
  977. if (esdlListName.isEmpty())
  978. {
  979. IEsdlDefObject* def = child->queryEsdlDefObject();
  980. if (def->getEsdlType() == EsdlTypeArray)
  981. {
  982. IEsdlDefArray* defArray = dynamic_cast<IEsdlDefArray*>(def);
  983. if (defArray->checkIsEsdlList())
  984. {
  985. ctx.writer->outputBeginArray(tagName);
  986. esdlListName.set(tagName);
  987. esdlListItemCount++;
  988. }
  989. }
  990. }
  991. chd.process(ctx, NULL, &local);
  992. if (local.dataForProcessed)
  993. {
  994. assertex(chd.queryDataFor()!=NULL);
  995. if (ctx.writer->length() > len)
  996. {
  997. ESDL_DBG("Taking out data for DataFor '%s' from out buffer", chd.queryDataFor()->queryName());
  998. StringBuffer databuf;
  999. ctx.writer->cutFrom(location, databuf);
  1000. local.setDataFor(chd.queryDataFor()->queryName(), databuf.str());
  1001. if (esdlListItemCount == 1)
  1002. {// Not call outputEndArray()
  1003. esdlListName.clear();
  1004. esdlListItemCount = 0;
  1005. }
  1006. }
  1007. }
  1008. if (chd.hasDataFrom())
  1009. {
  1010. if (ctx.writer->length() > len)
  1011. {
  1012. ESDL_DBG("Orig data '%s' is not empty", chd.queryName());
  1013. local.setDataOrig(chd.queryName());
  1014. }
  1015. }
  1016. }
  1017. else
  1018. ctx.xppp->skipSubTree();
  1019. }
  1020. break;
  1021. }
  1022. }
  1023. }
  1024. if (!esdlListName.isEmpty())
  1025. ctx.writer->outputEndArray(esdlListName.str());
  1026. if (completeContent.length()>0)
  1027. ctx.writer->outputUtf8(rtlUtf8Length(completeContent.length(),completeContent.str()),completeContent.str(),NULL);
  1028. local.handleDataFor(*(ctx.writer));
  1029. if (count && ctx.writer->length() > curlen)
  1030. ctx.counter++;
  1031. if (out_name && *out_name)
  1032. {
  1033. if (!ctx.skip_root || !might_skip_root)
  1034. {
  1035. if (ctx.writer->length() == curlen) //nothing was added, empty content, remove open tag
  1036. {
  1037. ctx.writer->outputEndNested(out_name); //we need to close out current section first
  1038. ctx.writer->rewindTo(prevLocation); //rewind
  1039. }
  1040. else
  1041. {
  1042. ctx.writer->outputEndNested(out_name);
  1043. }
  1044. }
  1045. }
  1046. }
  1047. }
  1048. void Esdl2Struct::processElement(Esdl2TransformerContext &ctx)
  1049. {
  1050. ESDL_DBG("Esdl2Struct::processElement: %s", queryName());
  1051. for (int type=ctx.xppp->next(); type!=XmlPullParser::END_TAG; type=ctx.xppp->next())
  1052. {
  1053. if (type==XmlPullParser::START_TAG)
  1054. {
  1055. StartTag child_start;
  1056. ctx.xppp->readStartTag(child_start);
  1057. Esdl2Base* child = queryChild(child_start.getLocalName());
  1058. if (child)
  1059. child->process(ctx, NULL);
  1060. else
  1061. ctx.xppp->skipSubTree();
  1062. break;
  1063. }
  1064. }
  1065. }
  1066. void Esdl2Struct::addChildren(Esdl2Transformer *xformer, IEsdlDefObjectIterator *it)
  1067. {
  1068. ForEach(*it)
  1069. {
  1070. IEsdlDefObject* item = &it->query();
  1071. const char *name = item->queryName();
  1072. Esdl2Base *obj = createEsdlObject(xformer, item);
  1073. if (obj)
  1074. {
  1075. m_children.append(*obj);
  1076. m_child_map.setValue(obj->queryName(), obj);
  1077. m_child_nocasemap.setValue(StringBuffer(obj->queryName()).toLowerCase().str(), obj);
  1078. if (might_skip_root && !stricmp(obj->queryName(), "response"))
  1079. obj->setMightSkipRoot(true);
  1080. }
  1081. }
  1082. // resolve get_data_from
  1083. ForEach(*it)
  1084. {
  1085. const char* dataFrom = it->query().queryProp("get_data_from");
  1086. if (dataFrom)
  1087. {
  1088. const char* name = it->query().queryProp("name");
  1089. Esdl2Base* self = queryChild(name);
  1090. Esdl2Base* dataSrc = queryChild(dataFrom);
  1091. if (dataSrc && self) {
  1092. self->setHasDataFrom();
  1093. dataSrc->setDataFor(self);
  1094. }
  1095. else
  1096. {
  1097. VStringBuffer msg("Can not find element: %s for %s as data_for target", dataFrom, self ? self->queryName() : "UNKNOWN");
  1098. ERRLOG("%s", msg.str());
  1099. throw MakeStringException(-1, "Internal Error: %s", msg.str());
  1100. }
  1101. }
  1102. }
  1103. // resolve xml_tag
  1104. ForEach(*it)
  1105. {
  1106. const char* xmlTag = it->query().queryProp("xml_tag");
  1107. if (xmlTag)
  1108. {
  1109. const char* name = it->query().queryProp("name");
  1110. Esdl2Base* self = queryChild(name);
  1111. EsdlBaseArrayPtr * arrayPtr= xml_tags.getValue(xmlTag);
  1112. if (arrayPtr)
  1113. (*arrayPtr)->append(*self);
  1114. else
  1115. {
  1116. EsdlBaseArray* array = new EsdlBaseArray;
  1117. array->append(*self);
  1118. xml_tags.setValue(xmlTag, array);
  1119. }
  1120. }
  1121. }
  1122. }
  1123. // ======================================================================================
  1124. // class Esdl2Request
  1125. void Esdl2Request::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count)
  1126. {
  1127. ESDL_DBG("Esdl2Request::process(pt): %s", queryName());
  1128. if (checkVersion(ctx))
  1129. {
  1130. if (out_name && *out_name)
  1131. {
  1132. if (!ctx.skip_root)
  1133. ctx.writer->outputBeginNested(out_name, true);
  1134. if (ctx.flags & ESDL_TRANS_ROW_OUT)
  1135. ctx.writer->outputBeginNested("Row", true);
  1136. }
  1137. Esdl2Struct::process(ctx, pt, NULL, local, count);
  1138. if (out_name && *out_name)
  1139. {
  1140. if (ctx.flags & ESDL_TRANS_ROW_OUT)
  1141. ctx.writer->outputEndNested("Row");
  1142. if (!ctx.skip_root)
  1143. ctx.writer->outputEndNested(out_name);
  1144. }
  1145. }
  1146. }
  1147. void Esdl2Request::buildDefaults(Esdl2Transformer *xformer)
  1148. {
  1149. defvals.setown(createProperties(false));
  1150. ForEachItemIn(idx, m_children)
  1151. {
  1152. Esdl2Base &child = m_children.item(idx);
  1153. StringBuffer path;
  1154. child.buildDefaults(xformer, path, defvals.get());
  1155. }
  1156. }
  1157. void Esdl2Request::addDefaults(IPropertyTree *req)
  1158. {
  1159. Owned<IPropertyIterator> iter = defvals->getIterator();
  1160. ForEach(*iter)
  1161. {
  1162. const char *path = iter->getPropKey();
  1163. if (!req->hasProp(path))
  1164. {
  1165. const char *value = defvals->queryProp(path);
  1166. ensurePTree(req, path);
  1167. req->setProp(path, value);
  1168. }
  1169. }
  1170. }
  1171. void Esdl2Response::process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local, bool count)
  1172. {
  1173. ESDL_DBG("EsdlResponse::processRespChild: %s", queryName());
  1174. if (!checkVersion(ctx))
  1175. ctx.xppp->skipSubTree();
  1176. else
  1177. {
  1178. if (out_name && *out_name) {
  1179. if (!might_skip_root || !ctx.skip_root)
  1180. {
  1181. if (ctx.do_output_ns)
  1182. {
  1183. ctx.writer->outputBeginNested(out_name, true);
  1184. ctx.writer->outputXmlns("xmlns", ctx.ns.str());
  1185. if (ctx.schemaLocation.length() > 0 )
  1186. {
  1187. ctx.writer->outputXmlns("xsi", "http://www.w3.org/2001/XMLSchema-instance");
  1188. ctx.writer->outputUtf8(rtlUtf8Length(ctx.schemaLocation.length(),ctx.schemaLocation.str()),ctx.schemaLocation.str(),"@xsi:schemaLocation");
  1189. }
  1190. ctx.do_output_ns=false;
  1191. }
  1192. else
  1193. {
  1194. ctx.writer->outputBeginNested(out_name, true);
  1195. }
  1196. }
  1197. }
  1198. if (ctx.flags & ESDL_TRANS_ROW_IN)
  1199. {
  1200. StartTag stag;
  1201. if (xppGotoTag(*ctx.xppp, "Row",stag))
  1202. Esdl2Struct::process(ctx, NULL, local, count);
  1203. }
  1204. else
  1205. Esdl2Struct::process(ctx, NULL, local, count);
  1206. if (out_name && *out_name)
  1207. {
  1208. if (!ctx.skip_root || !might_skip_root)
  1209. {
  1210. ctx.writer->outputEndNested(out_name);
  1211. }
  1212. }
  1213. }
  1214. }
  1215. void Esdl2Response::processChildNamedResponse(Esdl2TransformerContext &ctx, const char *out_name)
  1216. {
  1217. ESDL_DBG("Esdl2Struct::processRespChild: %s", queryName());
  1218. Esdl2Base *child = queryChild("response", true);
  1219. if (!child || !checkVersion(ctx))
  1220. ctx.xppp->skipSubTree();
  1221. else
  1222. {
  1223. if (out_name && *out_name) {
  1224. if (!might_skip_root || !ctx.skip_root)
  1225. {
  1226. if (ctx.do_output_ns)
  1227. {
  1228. ctx.writer->outputBeginNested(out_name, true);
  1229. ctx.writer->outputXmlns(out_name, ctx.ns.str());
  1230. ctx.do_output_ns=false;
  1231. }
  1232. else
  1233. {
  1234. ctx.writer->outputBeginNested(out_name, true);
  1235. }
  1236. }
  1237. }
  1238. if (ctx.flags & ESDL_TRANS_ROW_IN)
  1239. {
  1240. StartTag stag;
  1241. if (xppGotoTag(*ctx.xppp, "Row",stag))
  1242. child->process(ctx, NULL);
  1243. }
  1244. else
  1245. child->process(ctx, NULL);
  1246. if (out_name && *out_name)
  1247. if (!ctx.skip_root || !might_skip_root)
  1248. {
  1249. ctx.writer->outputEndNested(out_name);
  1250. }
  1251. }
  1252. }
  1253. // ======================================================================================
  1254. // class Esdl2EnumRef
  1255. void Esdl2Attribute::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count)
  1256. {
  1257. //need to make sure these are output inside the parent brackets
  1258. //if (checkVersion(ctx))
  1259. // output_content(ctx, pt);
  1260. }
  1261. // ======================================================================================
  1262. // class Esdl2EnumRef
  1263. void Esdl2EnumRef::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count)
  1264. {
  1265. if (checkVersion(ctx))
  1266. output_content(ctx, pt);
  1267. }
  1268. void Esdl2EnumRef::process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local,bool count)
  1269. {
  1270. if (!checkVersion(ctx))
  1271. ctx.xppp->skipSubTree();
  1272. else
  1273. output_content(ctx);
  1274. }
  1275. // ======================================================================================
  1276. // class Esdl2Transformer
  1277. Esdl2Transformer::Esdl2Transformer(IEsdlDefinition* def)
  1278. {
  1279. m_def.setown(LINK(def));
  1280. initEsdlTypeList();
  1281. }
  1282. void Esdl2Transformer::serialize(StringBuffer &out)
  1283. {
  1284. out.append("<esxdl>");
  1285. ForEachItemIn(idx, types)
  1286. {
  1287. Esdl2Base &type = types.item(idx);
  1288. type.serialize(out);
  1289. }
  1290. out.append("</esxdl>");
  1291. }
  1292. void Esdl2Transformer::addMethod(Esdl2Base *item)
  1293. {
  1294. if (item)
  1295. {
  1296. Esdl2Method *method=dynamic_cast<Esdl2Method *>(item);
  1297. if (method)
  1298. {
  1299. methods.append(*method);
  1300. meth_map.setValue(method->queryName(), method);
  1301. }
  1302. }
  1303. }
  1304. void Esdl2Transformer::setMethodInfo(const char *name, Esdl2Method *method)
  1305. {
  1306. if (name && *name && method)
  1307. {
  1308. WriteLockBlock block(rwMethodLock);
  1309. meth_map.setValue(name, method);
  1310. }
  1311. }
  1312. Esdl2Method **Esdl2Transformer::readMethodInfo(const char *method)
  1313. {
  1314. ReadLockBlock block(rwMethodLock);
  1315. return meth_map.getValue(method);
  1316. }
  1317. IEsdlMethodInfo* Esdl2Transformer::queryMethodInfo(const char* service,const char *method)
  1318. {
  1319. Esdl2Method **mt = readMethodInfo(method);
  1320. if (mt && *mt)
  1321. return dynamic_cast<IEsdlMethodInfo *>(*mt);
  1322. IEsdlDefService* svc = m_def->queryService(service);
  1323. if (!svc)
  1324. return NULL;
  1325. IEsdlDefMethod* mth = svc->queryMethodByName(method);
  1326. Esdl2Method* m = new Esdl2Method(this,mth);
  1327. setMethodInfo(method, m);
  1328. return m;
  1329. }
  1330. void Esdl2Transformer::addType(Esdl2Base* type)
  1331. {
  1332. WriteLockBlock block(rwTypeLock);
  1333. types.append(*type);
  1334. type_map.setValue(type->queryName(), type);
  1335. }
  1336. Esdl2Base **Esdl2Transformer::readType(const char *name)
  1337. {
  1338. ReadLockBlock block(rwTypeLock);
  1339. return type_map.getValue(name);
  1340. }
  1341. Esdl2Base* Esdl2Transformer::queryType(const char* name)
  1342. {
  1343. ESDL_DBG("queryType(%s)", name);
  1344. Esdl2Base** typ = readType(name);
  1345. if (typ && *typ)
  1346. return *typ;
  1347. IEsdlDefObject* obj = m_def->queryObj(name);
  1348. if (obj)
  1349. {
  1350. Esdl2Base* type = createEsdlObject(this,obj);
  1351. ESDL_DBG("addType(%s)", name);
  1352. addType(type);
  1353. return type;
  1354. }
  1355. return NULL;
  1356. }
  1357. Esdl2Transformer::~Esdl2Transformer()
  1358. {
  1359. ForEachItemIn(idx, types)
  1360. {
  1361. Esdl2Base *type = &types.item(idx);
  1362. type->Release();
  1363. }
  1364. ForEachItemIn(mdx, methods)
  1365. {
  1366. Esdl2Method *meth = &methods.item(mdx);
  1367. meth->Release();
  1368. }
  1369. HashIterator mmit(meth_map);
  1370. for (mmit.first(); mmit.isValid(); mmit.next())
  1371. {
  1372. IMapping& et = mmit.query();
  1373. Esdl2Method *em = (*meth_map.mapToValue(&et));
  1374. if (em)
  1375. em->Release();
  1376. }
  1377. }
  1378. int Esdl2Transformer::process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, StringBuffer &out, const char *in, unsigned int flags, const char *ns, const char *schema_location)
  1379. {
  1380. int rc = 0;
  1381. IEsdlMethodInfo *mi = queryMethodInfo(service,method);
  1382. if (!mi)
  1383. throw MakeStringException(-1, "Error processing ESDL - method '%s'not found", method);
  1384. const char *root_type=NULL;
  1385. const char *root_name=NULL;
  1386. if (mode==EsdlRequestMode)
  1387. {
  1388. root_name = "row";
  1389. root_type = mi->queryRequestType();
  1390. }
  1391. else if (mode==EsdlResponseMode)
  1392. {
  1393. root_type = mi->queryResponseType();
  1394. }
  1395. if (!root_type)
  1396. throw MakeStringException(-1, "Error processing ESDL - starting type not defined");
  1397. Esdl2Base* root = queryType(root_type);
  1398. if (!root)
  1399. throw MakeStringException(-1, "Error processing ESDL - root type '%s' not found", root_type);
  1400. IProperties *param_groups = ctx.queryRequestParameters();
  1401. try
  1402. {
  1403. XmlPullParser xppx(in, strlen(in)+1);
  1404. if (gotoStartTag(xppx, root->queryName(), "Results"))
  1405. {
  1406. Owned<IXmlWriterExt> respWriter = createIXmlWriterExt(0, 0, NULL, WTStandard);
  1407. Esdl2TransformerContext tctx(*this, respWriter, xppx, ctx.getClientVersion(), param_groups, mode, 0, ns,schema_location);
  1408. tctx.flags = flags;
  1409. tctx.skip_root = !(flags & ESDL_TRANS_OUTPUT_ROOT);
  1410. tctx.root_type.set(root->queryName());
  1411. root->process(tctx, (root_name) ? root_name : root_type);
  1412. rc = tctx.counter;
  1413. if (mode==EsdlRequestMode)
  1414. {
  1415. Esdl2Request *rootreq = dynamic_cast<Esdl2Request *>(root);
  1416. if (rootreq)
  1417. {
  1418. DBGLOG("XML: %s", respWriter->str());
  1419. OwnedPTree req = createPTreeFromXMLString(respWriter->str(), false);
  1420. if (!req.get())
  1421. req.setown(createPTree(root_type,false));
  1422. rootreq->addDefaults(req);
  1423. toXML(req.get(), out.clear());
  1424. }
  1425. }
  1426. }
  1427. else
  1428. {
  1429. const char* errorMsg = "Internal Server Error: Results dataset not available.";
  1430. DBGLOG("%s", errorMsg);
  1431. throw MakeStringExceptionDirect(5001, errorMsg);
  1432. }
  1433. }
  1434. catch (XmlPullParserException &xpexp)
  1435. {
  1436. StringBuffer text;
  1437. text.appendf("EsdlTransformer XPP exception: %s", xpexp.what());
  1438. DBGLOG("%s", text.str());
  1439. throw MakeStringExceptionDirect(5001, text.str());
  1440. }
  1441. catch (IException* e)
  1442. {
  1443. throw e;
  1444. }
  1445. catch (...)
  1446. {
  1447. throw MakeStringException(5001, "EsdlTransformer error parsing xml");
  1448. }
  1449. return rc;
  1450. };
  1451. int Esdl2Transformer::process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, IPropertyTree &in, IXmlWriterExt* writer, unsigned int flags, const char *ns)
  1452. {
  1453. IEsdlMethodInfo *mi = queryMethodInfo(service,method);
  1454. if (!mi)
  1455. throw MakeStringException(-1, "ESDL - method '%s::%s'not found", service, method);
  1456. const char *root_type=NULL;
  1457. if (mode==EsdlRequestMode)
  1458. root_type=mi->queryRequestType();
  1459. else if (mode==EsdlResponseMode)
  1460. root_type=mi->queryResponseType();
  1461. if (!root_type)
  1462. throw MakeStringException(-1, "ESDL - starting type not defined for method '%s::%s'", service, method);
  1463. Esdl2Base* root = queryType(root_type);
  1464. if (!root)
  1465. throw MakeStringException(-1, "Error processing ESDL - root type '%s' not found", root_type);
  1466. IPropertyTree *finger = &in;
  1467. if (!(flags & ESDL_TRANS_START_AT_ROOT))
  1468. {
  1469. if (flags & ESDL_TRANS_SOAP_IN)
  1470. {
  1471. if (finger->hasProp("Envelope"))
  1472. finger=finger->queryPropTree("Envelope");
  1473. if (finger->hasProp("Body"))
  1474. finger=finger->queryPropTree("Body");
  1475. }
  1476. if (!strieq(finger->queryName(), root_type))
  1477. {
  1478. if (!finger->hasProp(root_type))
  1479. throw MakeStringException(-1, "root element not found: %s", root_type);
  1480. finger = finger->queryPropTree(root_type);
  1481. }
  1482. }
  1483. IProperties *param_groups = ctx.queryRequestParameters();
  1484. int rc = 0;
  1485. try
  1486. {
  1487. Esdl2TransformerContext tctx(*this, writer, ctx.getClientVersion(), param_groups, mode, flags, ns);
  1488. tctx.skip_root = false;
  1489. tctx.root_type.set(root->queryName());
  1490. root->process(tctx, &in, root_type);
  1491. rc = tctx.counter;
  1492. }
  1493. catch (...)
  1494. {
  1495. throw MakeStringException(5001, "Esdl2Transformer error property tree xml");
  1496. }
  1497. return rc;
  1498. }
  1499. int Esdl2Transformer::processElement(IEspContext &ctx, const char* service, const char *parentStructName, IXmlWriterExt* writer, const char *in)
  1500. {
  1501. if (!in || !*in)
  1502. return 0;
  1503. Esdl2Base* type = queryType(parentStructName);
  1504. if (!type)
  1505. throw MakeStringException(-1, "Error processing ESDL - type '%s' not found", parentStructName);
  1506. try
  1507. {
  1508. XmlPullParser xppx(in, strlen(in));
  1509. IProperties *param_groups = ctx.queryRequestParameters();
  1510. Esdl2TransformerContext tctx(*this, writer, xppx, ctx.getClientVersion(), param_groups, EsdlResponseMode);
  1511. tctx.skip_root = true;
  1512. type->processElement(tctx);
  1513. return tctx.counter;
  1514. }
  1515. catch (XmlPullParserException &xpexp)
  1516. {
  1517. StringBuffer text;
  1518. text.appendf("Esdl2Transformer XPP exception: %s", xpexp.what());
  1519. DBGLOG("%s", text.str());
  1520. throw MakeStringExceptionDirect(5001, text.str());
  1521. }
  1522. catch (...)
  1523. {
  1524. throw MakeStringException(5001, "Esdl2Transformer error parsing xml");
  1525. }
  1526. return 0;
  1527. }
  1528. static const char * gotoNextHPCCDataset(XmlPullParser &xppx, StartTag &stag)
  1529. {
  1530. int depth = 1;
  1531. int level = 0;
  1532. int type = XmlPullParser::END_TAG;
  1533. bool looking = true;
  1534. while (looking)
  1535. {
  1536. type = xppx.next();
  1537. switch(type)
  1538. {
  1539. case XmlPullParser::START_TAG:
  1540. case XmlPullParser::END_DOCUMENT:
  1541. looking=false;
  1542. break;
  1543. }
  1544. }
  1545. do
  1546. {
  1547. switch(type)
  1548. {
  1549. case XmlPullParser::START_TAG:
  1550. {
  1551. xppx.readStartTag(stag);
  1552. ++level;
  1553. const char *tag = stag.getLocalName();
  1554. if (!stricmp(tag, "Dataset"))
  1555. return stag.getValue("name");
  1556. else if (!stricmp(tag, "Exception"))
  1557. {
  1558. throw xppMakeException(xppx);
  1559. }
  1560. break;
  1561. }
  1562. case XmlPullParser::END_TAG:
  1563. --level;
  1564. break;
  1565. case XmlPullParser::END_DOCUMENT:
  1566. level=0;
  1567. break;
  1568. }
  1569. type = xppx.next();
  1570. }
  1571. while (level > 0);
  1572. return NULL;
  1573. }
  1574. void Esdl2Transformer::processHPCCResult(IEspContext &ctx, IEsdlDefMethod &mthdef, const char *xml, IXmlWriterExt* writer, StringBuffer &logdata, unsigned int flags, const char *ns, const char *schema_location)
  1575. {
  1576. std::unique_ptr<XmlPullParser> xpp(new XmlPullParser());
  1577. xpp->setSupportNamespaces(true);
  1578. xpp->setInput(xml, strlen(xml));
  1579. StartTag stag;
  1580. int depth=1;
  1581. IEsdlDefinition *esdl = m_def.get();
  1582. if (!esdl)
  1583. throw MakeStringExceptionDirect(-1, "ESDL transformer error: could not access ESDL definition object");
  1584. const char *restype = mthdef.queryResponseType();
  1585. if (!restype)
  1586. throw MakeStringException(-1, "ESDL method %s, response type not declared", mthdef.queryName());
  1587. IEsdlDefStruct *resdef = esdl->queryStruct(restype);
  1588. if (!resdef)
  1589. throw MakeStringException(-1, "ESDL method %s, response type %s not defined", mthdef.queryName(), restype);
  1590. const char *resdsname = restype;
  1591. const char *subresdsname = NULL;
  1592. if (resdef->queryChild("response", true)) //indicates we're at the ResponseEx level
  1593. {
  1594. IEsdlDefObject *respobj = resdef->queryChild("response", true);
  1595. EsdlDefTypeId tid = respobj->getEsdlType();
  1596. if (tid==EsdlTypeElement)
  1597. {
  1598. IEsdlDefElement *subrespel = dynamic_cast<IEsdlDefElement*>(respobj);
  1599. if (subrespel)
  1600. {
  1601. const char *eltype=subrespel->queryProp("complex_type");
  1602. if (eltype)
  1603. subresdsname=eltype;
  1604. }
  1605. }
  1606. }
  1607. logdata.appendf("<%s>", LOGDATASETTAG);
  1608. const char * dataset;
  1609. try
  1610. {
  1611. while((dataset = gotoNextHPCCDataset(*xpp, stag)) != NULL)
  1612. {
  1613. if ( strieq(dataset, resdsname)
  1614. ||(subresdsname && strieq(dataset, subresdsname)) //Only allow correctly named dataset?
  1615. || stricmp(dataset, "FinalResults")==0
  1616. || stricmp(dataset, "Results")==0
  1617. )
  1618. {
  1619. Esdl2TransformerContext tctx(*this, writer, *xpp, ctx.getClientVersion(), ctx.queryRequestParameters(), EsdlResponseMode, 0, ns,schema_location);
  1620. tctx.flags = flags | ESDL_TRANS_ROW_IN;
  1621. tctx.skip_root = !(flags & ESDL_TRANS_OUTPUT_ROOT);
  1622. tctx.root_type.set(restype);
  1623. Esdl2Base* root = queryType(restype);
  1624. if (root)
  1625. {
  1626. Esdl2Response *resp = dynamic_cast<Esdl2Response *>(root);
  1627. if (resp)
  1628. {
  1629. if (subresdsname)
  1630. resp->processChildNamedResponse(tctx, restype);
  1631. else
  1632. resp->process(tctx, restype);
  1633. }
  1634. }
  1635. }
  1636. else if (strnicmp(dataset, "VendorGatewayRecords", 20)==0)
  1637. xppToXmlString(*xpp, stag, logdata);
  1638. else if (strnicmp(dataset, "LOG_", 4)==0)
  1639. xppToXmlString(*xpp, stag, logdata);
  1640. else if (strieq(dataset, "royaltyset"))
  1641. xppToXmlString(*xpp, stag, logdata);
  1642. else if (strieq(dataset, "desdlsoaprequestecho"))
  1643. xppToXmlString(*xpp, stag, logdata);
  1644. else
  1645. {
  1646. WARNLOG("ESDL processing HPCC Result: Dataset ignored: %s", dataset);
  1647. xpp->skipSubTree();
  1648. }
  1649. }
  1650. logdata.appendf("</%s>",LOGDATASETTAG);
  1651. }
  1652. catch (...)
  1653. {
  1654. logdata.appendf("</%s>",LOGDATASETTAG);
  1655. throw;
  1656. }
  1657. }
  1658. Esdl2Base* Esdl2TransformerContext::queryType(const char* name)
  1659. {
  1660. return xformer.queryType(name);
  1661. }
  1662. // ======================================================================================
  1663. // factory
  1664. esdl_decl IEsdlTransformer *createEsdlXFormerFromXMLFilesV2(StringArray &files)
  1665. {
  1666. Owned<IEsdlDefinition> esdl = createEsdlDefinition();
  1667. ForEachItemIn(idx, files)
  1668. {
  1669. const char* file = files.item(idx);
  1670. esdl->addDefinitionsFromFile(file);
  1671. }
  1672. return new Esdl2Transformer(esdl.get());
  1673. }
  1674. esdl_decl IEsdlTransformer *createEsdlXFormer(IEsdlDefinition *def)
  1675. {
  1676. return new Esdl2Transformer(def);
  1677. }
  1678. // end
  1679. // ======================================================================================