def writestackedlistenertypedobjectlistimplementation(istate, schema): naming = istate.naming() subtypenaming = CppParserSubTypeNaming(schema, naming) outfile = istate.outputfile() outfile.write( string.Template(""" ${subtype_cppstackedlistlistenerclassname}::${subtype_cppstackedlistlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent) : ${cppsuperstackedlistenerclassname}(mainListener, parent) { fTarget = new List<${subtype_cppmodelclassname}*, true>(); } ${subtype_cppstackedlistlistenerclassname}::~${subtype_cppstackedlistlistenerclassname}() { } List<${subtype_cppmodelclassname}*, true>* ${subtype_cppstackedlistlistenerclassname}::Target() { return fTarget; } bool ${subtype_cppstackedlistlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { case B_JSON_ARRAY_END: Pop(); delete this; break; case B_JSON_OBJECT_START: { ${subtype_cppstackedlistenerclassname}* nextListener = new ${subtype_cppstackedlistenerclassname}(fMainListener, this); fTarget->Add(nextListener->Target()); Push(nextListener); break; } default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of ${subtype_cppmodelclassname}"); break; } return ErrorStatus() == B_OK; } """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict())))
def writebulkcontainerstackedlistenerinterface(istate, schema): naming = istate.naming() subtypenaming = CppParserSubTypeNaming(schema, naming) outfile = istate.outputfile() # This is a sub-class of the main model object listener. It will ping out to an item listener # when parsing is complete. outfile.write( string.Template(""" class ${cppitemlistenerstackedlistenerclassname} : public ${subtype_cppstackedlistenerclassname} { public: ${cppitemlistenerstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener); ~${cppitemlistenerstackedlistenerclassname}(); void WillPop(); private: ${cppitemlistenerclassname}* fItemListener; }; class ${cppbulkcontainerstackedlistenerclassname} : public ${cppsuperstackedlistenerclassname} { public: ${cppbulkcontainerstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener); ~${cppbulkcontainerstackedlistenerclassname}(); bool Handle(const BJsonEvent& event); private: BString fNextItemName; ${cppitemlistenerclassname}* fItemListener; }; class ${cppbulkcontaineritemliststackedlistenerclassname} : public ${cppsuperstackedlistenerclassname} { public: ${cppbulkcontaineritemliststackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener); ~${cppbulkcontaineritemliststackedlistenerclassname}(); bool Handle(const BJsonEvent& event); void WillPop(); private: ${cppitemlistenerclassname}* fItemListener; }; """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict())))
def writeageneralstackedlistenerinterface(istate, alistenerclassname): istate.outputfile().write( string.Template(""" class ${alistenerclassname} : public ${cppsuperstackedlistenerclassname} { public: ${alistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent); ~${alistenerclassname}(); bool Handle(const BJsonEvent& event); }; """).substitute( hdscommon.uniondicts(istate.naming().todict(), {'alistenerclassname': alistenerclassname})))
def writestackedlistenerinterface(istate, subschema): naming = istate.naming() subtypenaming = CppParserSubTypeNaming(subschema, naming) if not istate.isinterfacehandledcppname(subtypenaming.cppmodelclassname()): istate.addinterfacehandledcppname(subtypenaming.cppmodelclassname()) istate.outputfile().write( string.Template(""" class ${subtype_cppstackedlistenerclassname} : public ${cppsuperstackedlistenerclassname} { public: ${subtype_cppstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent); ~${subtype_cppstackedlistenerclassname}(); bool Handle(const BJsonEvent& event); ${subtype_cppmodelclassname}* Target(); protected: ${subtype_cppmodelclassname}* fTarget; BString fNextItemName; }; class ${subtype_cppstackedlistlistenerclassname} : public ${cppsuperstackedlistenerclassname} { public: ${subtype_cppstackedlistlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent); ~${subtype_cppstackedlistlistenerclassname}(); bool Handle(const BJsonEvent& event); List<${subtype_cppmodelclassname}*, true>* Target(); // list of %s pointers private: List<${subtype_cppmodelclassname}*, true>* fTarget; }; """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict()))) for propname, propmetadata in subschema['properties'].items(): if propmetadata['type'] == 'array': writestackedlistenerinterface(istate, propmetadata['items']) elif propmetadata['type'] == 'object': writestackedlistenerinterface(istate, propmetadata)
def writegeneralnoopstackedlistenerconstructordestructor(istate, aclassname): istate.outputfile().write( string.Template(""" ${aclassname}::${aclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent) : ${cppsuperstackedlistenerclassname}(mainListener, parent) { } ${aclassname}::~${aclassname}() { } """).substitute( hdscommon.uniondicts(istate.naming().todict(), {'aclassname': aclassname})))
def writemainlistenerimplementation(istate, schema, supportbulkcontainer): outfile = istate.outputfile() naming = istate.naming() subtypenaming = CppParserSubTypeNaming(schema, istate.naming()) # super (abstract) listener outfile.write( string.Template(""" ${cppsupermainlistenerclassname}::${cppsupermainlistenerclassname}() { fStackedListener = NULL; fErrorStatus = B_OK; } ${cppsupermainlistenerclassname}::~${cppsupermainlistenerclassname}() { } void ${cppsupermainlistenerclassname}::HandleError(status_t status, int32 line, const char* message) { fprintf(stderr, "an error has arisen processing json for '${cpprootmodelclassname}'; %s\\n", message); fErrorStatus = status; } void ${cppsupermainlistenerclassname}::Complete() { } status_t ${cppsupermainlistenerclassname}::ErrorStatus() { return fErrorStatus; } void ${cppsupermainlistenerclassname}::SetStackedListener( ${cppsuperstackedlistenerclassname}* stackedListener) { fStackedListener = stackedListener; } """).substitute(naming.todict())) # single parser outfile.write( string.Template(""" ${cppsinglemainlistenerclassname}::${cppsinglemainlistenerclassname}() : ${cppsupermainlistenerclassname}() { fTarget = NULL; } ${cppsinglemainlistenerclassname}::~${cppsinglemainlistenerclassname}() { } bool ${cppsinglemainlistenerclassname}::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; if (fStackedListener != NULL) return fStackedListener->Handle(event); switch (event.EventType()) { case B_JSON_OBJECT_START: { ${subtype_cppstackedlistenerclassname}* nextListener = new ${subtype_cppstackedlistenerclassname}( this, NULL); fTarget = nextListener->Target(); SetStackedListener(nextListener); break; } default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for ${cpprootmodelclassname}"); break; } return ErrorStatus() == B_OK; } ${cpprootmodelclassname}* ${cppsinglemainlistenerclassname}::Target() { return fTarget; } """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict()))) if supportbulkcontainer: # create a main listener that can work through the list of top level model objects and ping the listener outfile.write( string.Template(""" ${cppbulkcontainermainlistenerclassname}::${cppbulkcontainermainlistenerclassname}( ${cppitemlistenerclassname}* itemListener) : ${cppsupermainlistenerclassname}() { fItemListener = itemListener; } ${cppbulkcontainermainlistenerclassname}::~${cppbulkcontainermainlistenerclassname}() { } bool ${cppbulkcontainermainlistenerclassname}::Handle(const BJsonEvent& event) { if (fErrorStatus != B_OK) return false; if (fStackedListener != NULL) return fStackedListener->Handle(event); switch (event.EventType()) { case B_JSON_OBJECT_START: { ${cppbulkcontainerstackedlistenerclassname}* nextListener = new ${cppbulkcontainerstackedlistenerclassname}( this, NULL, fItemListener); SetStackedListener(nextListener); return true; break; } default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for ${cppbulkcontainermainlistenerclassname}"); break; } return ErrorStatus() == B_OK; } """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict())))
def writebulkcontainerstackedlistenerimplementation(istate, schema): naming = istate.naming() subtypenaming = CppParserSubTypeNaming(schema, naming) outfile = istate.outputfile() outfile.write( string.Template(""" ${cppitemlistenerstackedlistenerclassname}::${cppitemlistenerstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener) : ${subtype_cppstackedlistenerclassname}(mainListener, parent) { fItemListener = itemListener; } ${cppitemlistenerstackedlistenerclassname}::~${cppitemlistenerstackedlistenerclassname}() { } void ${cppitemlistenerstackedlistenerclassname}::WillPop() { fItemListener->Handle(fTarget); delete fTarget; } ${cppbulkcontainerstackedlistenerclassname}::${cppbulkcontainerstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener) : ${cppsuperstackedlistenerclassname}(mainListener, parent) { fItemListener = itemListener; } ${cppbulkcontainerstackedlistenerclassname}::~${cppbulkcontainerstackedlistenerclassname}() { } bool ${cppbulkcontainerstackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; case B_JSON_OBJECT_START: Push(new ${cppgeneralobjectstackedlistenerclassname}(fMainListener, this)); break; case B_JSON_ARRAY_START: if (fNextItemName == "items") Push(new ${cppbulkcontaineritemliststackedlistenerclassname}(fMainListener, this, fItemListener)); else Push(new ${cppgeneralarraystackedlistenerclassname}(fMainListener, this)); break; case B_JSON_OBJECT_END: Pop(); delete this; break; default: // ignore break; } return ErrorStatus() == B_OK; } ${cppbulkcontaineritemliststackedlistenerclassname}::${cppbulkcontaineritemliststackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent, ${cppitemlistenerclassname}* itemListener) : ${cppsuperstackedlistenerclassname}(mainListener, parent) { fItemListener = itemListener; } ${cppbulkcontaineritemliststackedlistenerclassname}::~${cppbulkcontaineritemliststackedlistenerclassname}() { } bool ${cppbulkcontaineritemliststackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { case B_JSON_OBJECT_START: Push(new ${cppitemlistenerstackedlistenerclassname}(fMainListener, this, fItemListener)); break; case B_JSON_ARRAY_END: Pop(); delete this; break; default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event"); break; } return ErrorStatus() == B_OK; } void ${cppbulkcontaineritemliststackedlistenerclassname}::WillPop() { fItemListener->Complete(); } """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict())))
def writestackedlistenertypedobjectimplementation(istate, schema): outfile = istate.outputfile() naming = istate.naming() subtypenaming = CppParserSubTypeNaming(schema, naming) outfile.write( string.Template(""" ${subtype_cppstackedlistenerclassname}::${subtype_cppstackedlistenerclassname}( ${cppsupermainlistenerclassname}* mainListener, ${cppsuperstackedlistenerclassname}* parent) : ${cppsuperstackedlistenerclassname}(mainListener, parent) { fTarget = new ${subtype_cppmodelclassname}(); } ${subtype_cppstackedlistenerclassname}::~${subtype_cppstackedlistenerclassname}() { } ${subtype_cppmodelclassname}* ${subtype_cppstackedlistenerclassname}::Target() { return fTarget; } bool ${subtype_cppstackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; case B_JSON_OBJECT_END: Pop(); delete this; break; """).substitute(hdscommon.uniondicts(naming.todict(), subtypenaming.todict()))) # now extract the fields from the schema that need to be fed in. writestackedlistenerfieldsimplementation(istate, schema, jscom.CPP_TYPE_STRING, 'B_JSON_STRING', 'new BString(event.Content())') writestackedlistenerfieldsimplementation(istate, schema, jscom.CPP_TYPE_BOOLEAN, 'B_JSON_TRUE', 'true') writestackedlistenerfieldsimplementation(istate, schema, jscom.CPP_TYPE_BOOLEAN, 'B_JSON_FALSE', 'false') outfile.write(' case B_JSON_NULL:\n') outfile.write(' {\n') for propname, propmetadata in schema['properties'].items(): # TODO; deal with array case somehow. if 'array' != propmetadata['type']: writestackedlistenerfieldimplementation(istate, propname, 'NULL') outfile.write(' fNextItemName.SetTo("");\n') outfile.write(' break;\n') outfile.write(' }\n') # number type is a bit complex because it can either be a double or it can be an # integral value. outfile.write(' case B_JSON_NUMBER:\n') outfile.write(' {\n') for propname, propmetadata in schema['properties'].items(): propcpptypename = jscom.propmetadatatocpptypename(propmetadata) if propcpptypename == jscom.CPP_TYPE_INTEGER: writestackedlistenerfieldimplementation(istate, propname, 'event.ContentInteger()') elif propcpptypename == jscom.CPP_TYPE_NUMBER: writestackedlistenerfieldimplementation(istate, propname, 'event.ContentDouble()') outfile.write(' fNextItemName.SetTo("");\n') outfile.write(' break;\n') outfile.write(' }\n') # object type; could be a sub-type or otherwise just drop into a placebo consumer to keep the parse # structure working. This would most likely be additional sub-objects that are additional to the # expected schema. outfile.write(' case B_JSON_OBJECT_START:\n') outfile.write(' {\n') objectifclausekeyword = 'if' for propname, propmetadata in schema['properties'].items(): if propmetadata['type'] == jscom.JSON_TYPE_OBJECT: subtypenaming = CppParserSubTypeNaming(propmetadata, naming) outfile.write(' %s (fNextItemName == "%s") {\n' % (objectifclausekeyword, propname)) outfile.write( ' %s* nextListener = new %s(fMainListener, this);\n' % (subtypenaming.cppstackedlistenerclassname(), subtypenaming.cppstackedlistenerclassname())) outfile.write( ' fTarget->Set%s(nextListener->Target());\n' % (subtypenaming.cppmodelclassname())) outfile.write(' Push(nextListener);\n') outfile.write(' }\n') objectifclausekeyword = 'else if' outfile.write(' %s (1 == 1) {\n' % objectifclausekeyword) outfile.write( ' %s* nextListener = new %s(fMainListener, this);\n' % (naming.cppgeneralobjectstackedlistenerclassname(), naming.cppgeneralobjectstackedlistenerclassname())) outfile.write(' Push(nextListener);\n') outfile.write(' }\n') outfile.write(' fNextItemName.SetTo("");\n') outfile.write(' break;\n') outfile.write(' }\n') # array type; could be an array of objects or otherwise just drop into a placebo consumer to keep # the parse structure working. outfile.write(' case B_JSON_ARRAY_START:\n') outfile.write(' {\n') objectifclausekeyword = 'if' for propname, propmetadata in schema['properties'].items(): if propmetadata['type'] == jscom.JSON_TYPE_ARRAY: subtypenaming = CppParserSubTypeNaming(propmetadata['items'], naming) outfile.write(' %s (fNextItemName == "%s") {\n' % (objectifclausekeyword, propname)) outfile.write( ' %s* nextListener = new %s(fMainListener, this);\n' % (subtypenaming.cppstackedlistlistenerclassname(), subtypenaming.cppstackedlistlistenerclassname())) outfile.write( ' fTarget->Set%s(nextListener->Target());\n' % (jscom.propnametocppname(propname))) outfile.write(' Push(nextListener);\n') outfile.write(' }\n') objectifclausekeyword = 'else if' outfile.write(' %s (1 == 1) {\n' % objectifclausekeyword) outfile.write( ' %s* nextListener = new %s(fMainListener, this);\n' % (naming.cppsuperstackedlistenerclassname(), naming.cppgeneralarraystackedlistenerclassname())) outfile.write(' Push(nextListener);\n') outfile.write(' }\n') outfile.write(' fNextItemName.SetTo("");\n') outfile.write(' break;\n') outfile.write(' }\n') outfile.write(""" } return ErrorStatus() == B_OK; } """)