[Mobies-commit] [commit] r4294 - UDM/trunk/src/UdmUtil
endre at redhat3.isis.vanderbilt.edu
endre at redhat3.isis.vanderbilt.edu
Tue Apr 22 14:27:39 CDT 2014
Author: endre
Date: Tue Apr 22 14:27:39 2014
New Revision: 4294
Log:
Json schema generator
Modified:
UDM/trunk/src/UdmUtil/UdmUtil.cpp
Modified: UDM/trunk/src/UdmUtil/UdmUtil.cpp
==============================================================================
--- UDM/trunk/src/UdmUtil/UdmUtil.cpp Tue Apr 22 14:27:35 2014 (r4293)
+++ UDM/trunk/src/UdmUtil/UdmUtil.cpp Tue Apr 22 14:27:39 2014 (r4294)
@@ -1238,6 +1238,46 @@
return trace;
};
+ UDM_DLL json_spirit::Pair AttrToSchema(const Uml::Attribute& attr)
+ {
+ json_spirit::Object js_obj;
+
+ map <string, string> udm_to_json_type_conversion;
+
+ udm_to_json_type_conversion.insert(pair<string,string>("Integer","integer"));
+ udm_to_json_type_conversion.insert(pair<string,string>("Boolean","boolean"));
+ udm_to_json_type_conversion.insert(pair<string,string>("Real","number"));
+ udm_to_json_type_conversion.insert(pair<string,string>("String","string"));
+
+
+ map<string,string>::iterator i =udm_to_json_type_conversion.find((string)(attr.type()));
+
+ if ( i == udm_to_json_type_conversion.end() )
+ throw udm_exception ("UdmUtil::AttrToJSPair: Unknown attribute type");
+
+ string json_type = i->second;
+ js_obj.push_back(json_spirit::Pair("type", json_type));
+
+ if (attr.max() == 1 || attr.max() == 0)
+ {
+
+ return json_spirit::Pair(attr.name(), js_obj);
+
+ }else
+ {
+ json_spirit::Object array_obj;
+
+ array_obj.push_back(json_spirit::Pair("type", "array"));
+ if (attr.min() > 0 ) array_obj.push_back(json_spirit::Pair("minItems", (int)attr.min())); // could be 0; if so do not specify
+ if (attr.max() > 0 ) array_obj.push_back(json_spirit::Pair("maxItems", (int)attr.max())); // could be 0 or -1; if so do not specify
+ array_obj.push_back(json_spirit::Pair("items", js_obj));
+
+ return json_spirit::Pair(attr.name(), array_obj);
+ }
+
+
+
+ };
UDM_DLL json_spirit::Pair AttrToJSPair(const ::Udm::Object& obj, ::Uml::Attribute & attr)
{
const string key = attr.name();
@@ -1310,20 +1350,177 @@
}
}
+
+ struct composition_info
+ {
+ const Uml::Class child_kind;
+ const Uml::Class parent_kind;
+ composition_info( const Uml::Class &c, const Uml::Class &p) : child_kind(c), parent_kind(p) {};
+ composition_info( const composition_info& ci) : child_kind(ci.child_kind), parent_kind(ci.parent_kind) {};
+
+ };
+
+ bool operator < (const composition_info& l, const composition_info& r)
+ {
+
+ if (l.child_kind < r.child_kind) return true;
+ if (l.child_kind > r.child_kind) return false;
+ // Otherwise a are equal
+
+
+ if (l.parent_kind < r.parent_kind) return true;
+ if (l.parent_kind > r.parent_kind) return false;
+ // Otherwise both are equal
+ return false;
+ }
+ struct track_classes
+ {
+ //we need this to handle loops in containment chain. Otherwise this recursion would never end
+ //in case of diagrams containing looped containment chains
+ //a composition already written to a JSON scheme will be tracked and if it is needed once more, only the $ref to it's path will be used
+ // we need to track composition and not classes alone because the _childrole property might differ depending on the composition
+ std::map< composition_info, string> classes;
+ public:
+
+ void track( const ::Uml::Class &c, const ::Uml::Class &p, const string& ref_path)
+ {
+
+ classes.insert( std::pair< composition_info, string>(composition_info(c,p), ref_path));
+
+ };
+ bool find( const ::Uml::Class &c, const ::Uml::Class &p, string& ref_path)
+ {
+
+ std::map< composition_info, string>::iterator c_i = classes.find(composition_info(c,p));
+ if (c_i != classes.end())
+ {
+
+ ref_path = c_i->second;
+ return true;
+ }
+
+ return false;
+ };
+
+ };
+
+ UDM_DLL json_spirit::Object ClassToPtree ( const ::Uml::Class &c, const ::Uml::Class &p, track_classes& tc, string ref_path = string("#"));
+ UDM_DLL json_spirit::Object ClassToPtree ( const ::Uml::Class &c, const ::Uml::Class &p, track_classes& tc, string ref_path)
+ {
+ json_spirit::Object o;
+ string found_refpath;
+
+
+ if(!tc.find(c, p, found_refpath))
+ {
+ if (!c.isAbstract() && p)
+ {
+
+ ref_path += "/properties/";
+ ref_path += c.name();
+ tc.track(c, p, ref_path);
+ }
+
+ o.push_back(json_spirit::Pair("type","object"));
+ o.push_back(json_spirit::Pair("additionalProperties", false));
+
+
+ json_spirit::Object properties, _id, _childrole;
+
+ _id.push_back(json_spirit::Pair("type", "integer"));
+ properties.push_back(json_spirit::Pair("_id", _id));
+ if (p)
+ {
+ set< ::Uml::Composition> comps = compositionsChildToParent(c,p,NULL);
+ if (comps.size() >1 )
+ {
+ vector<string> ccr_names;
+ for (set< ::Uml::Composition>::iterator comps_i = comps.begin(); comps_i != comps.end(); comps_i++)
+ {
+ ::Uml::CompositionChildRole ccr = comps_i->childRole();
+
+ ccr_names.push_back(ccr.name());
+ }
+
+ json_spirit::Array arr = json_spirit::Array(ccr_names.begin(), ccr_names.end());
+
+ _childrole.push_back(json_spirit::Pair("enum", arr));
+ properties.push_back(json_spirit::Pair("_childrole", _childrole));
+ }
+
+ }
+ set < ::Uml::Attribute> attrs = AncestorAttributes(c);
+ for (set < ::Uml::Attribute>::iterator attrs_i = attrs.begin(); attrs_i != attrs.end(); attrs_i++)
+ properties.push_back(AttrToSchema(*attrs_i));
+
+
+
+
+ set<Class> child_kind_descs = ::Uml::AncestorContainedDescendantClasses(c);
+
+
+ for ( set< ::Uml::Class>::iterator child_kind_descs_i = child_kind_descs.begin(); child_kind_descs_i!=child_kind_descs.end(); child_kind_descs_i++)
+ {
+ if (child_kind_descs_i->isAbstract())
+ ClassToPtree(*child_kind_descs_i, c, tc, ref_path);
+ else
+
+ properties.push_back(json_spirit::Pair((string)child_kind_descs_i->name(), ClassToPtree(*child_kind_descs_i, c, tc, ref_path)));
+ }
+
+ o.push_back(json_spirit::Pair("properties", properties));
+ }
+ else
+ o.push_back(json_spirit::Pair("$ref",found_refpath));
+
+ return o;
+
+ };
+
+
+ UDM_DLL json_spirit::Object ClassDiagramToPtree( const ::Uml::Diagram& dgr )
+ {
+ json_spirit::Object o;
+ track_classes tc;
+
+ vector< ::Uml::Class> rootClasses = Uml::findNonContainedClasses(dgr);
+ /*for (vector< ::Uml::Class>::iterator rc_i = rootClasses.begin(); rc_i != rootClasses.end(); rc_i++)
+ o.push_back(json_spirit::Pair ( (string)rc_i->name(), ClassToPtree(*rc_i, &Udm::_null, tc) ));
+ */
+
+ if (rootClasses.size() > 1) throw udm_exception ("JSON SCHEMA writer: For the moment only class diagram with single possible root class are supported");
+
+ return ClassToPtree(*(rootClasses.begin()), &Udm::_null, tc);
+
+
+ };
+
UDM_DLL json_spirit::Object DiagramToPtree( const ::Udm::Object& obj, const ::Uml::CompositionChildRole& contained_via_role = &Udm::_null );
UDM_DLL json_spirit::Object DiagramToPtree( const ::Udm::Object& obj, const ::Uml::CompositionChildRole& contained_via_role)
{
json_spirit::Object pt;
const Udm::ObjectImpl * obj_impl = obj.__impl();
+ Udm::Object parent_o;
+
+ ::Uml::Class c = obj_impl->type(); //mytype
+ ::Uml::Class p; //parent's type
+ if ((parent_o = obj.GetParent()))
+ p = parent_o.type();//parent's type
+ ::Uml::Composition comp;
+ if (p)
+ comp = ::Uml::matchChildToParent(c, p); //if multiple compositions possible, this will be NULL.
+
::Udm::ObjectImpl::uniqueId_type id = obj_impl->uniqueId();
to_string< ::Udm::ObjectImpl::uniqueId_type> key = to_string< ::Udm::ObjectImpl::uniqueId_type>(id);
- pt.push_back(json_spirit::Pair ( "_id:", (__int64 ) id));
- if (contained_via_role) pt.push_back(json_spirit::Pair( "_childrole:", (string)(contained_via_role.name() )));
+ pt.push_back(json_spirit::Pair ( "_id", (__int64 ) id));
+ if (!comp && contained_via_role) //specify _chilrole only if there can be more than one possible containment
+
+ pt.push_back(json_spirit::Pair( "_childrole", (string)(contained_via_role.name() )));
set < ::Uml::Attribute> attributes = AncestorAttributes(obj.type());
@@ -1343,8 +1540,8 @@
}
-
- set< ::Uml::Class> ancestorClasses=::Uml::AncestorClasses(obj.__impl()->type());
+ //TODO: USE set<CompositionChildRole> Uml::AncestorCompositionPeerChildRoles instead !
+ set< ::Uml::Class> ancestorClasses=::Uml::AncestorClasses(c);
for(set< ::Uml::Class>::iterator p_currClass=ancestorClasses.begin(); p_currClass!=ancestorClasses.end(); p_currClass++)
{
set< ::Uml::CompositionParentRole> compParentRoles=p_currClass->parentRoles();
@@ -1370,13 +1567,18 @@
};
- UDM_DLL void write_json(const ::Udm::Object& obj, const string & FileName, bool child_attr_subtree)
+ UDM_DLL void write_json(const ::Udm::Object& obj, const string & FileName, unsigned int options)
{
- unsigned int options = json_spirit::pretty_print | json_spirit::remove_trailing_zeros | json_spirit::single_line_arrays;
-
+
ofstream os(FileName.c_str());
json_spirit::write_stream( json_spirit::Value(DiagramToPtree(obj)) , os, options);
}
-
+
+ UDM_DLL void write_json(const ::Uml::Diagram& dgr, const string & FileName, unsigned int options)
+ {
+
+ ofstream os(FileName.c_str());
+ json_spirit::write_stream( json_spirit::Value(ClassDiagramToPtree(dgr)) , os, options);
+ }
};
More information about the Mobies-commit
mailing list