[Mobies-commit] [commit] r4293 - in UDM/trunk: . include src/UdmBase src/UdmJson

endre at redhat3.isis.vanderbilt.edu endre at redhat3.isis.vanderbilt.edu
Tue Apr 22 14:27:35 CDT 2014


Author: endre
Date: Tue Apr 22 14:27:35 2014
New Revision: 4293

Log:
JSON schema generator that validates JSON data serialisation

Modified:
   UDM/trunk/MACOS_build.txt
   UDM/trunk/include/UdmUtil.h
   UDM/trunk/include/UmlExt.h
   UDM/trunk/src/UdmBase/DTDGen.cpp
   UDM/trunk/src/UdmBase/UmlExt.cpp
   UDM/trunk/src/UdmJson/UdmJson.cpp

Modified: UDM/trunk/MACOS_build.txt
==============================================================================
--- UDM/trunk/MACOS_build.txt	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/MACOS_build.txt	Tue Apr 22 14:27:35 2014	(r4293)
@@ -76,7 +76,7 @@
 		./build.sh cc
 	3.2 build boost (will be needed for UdmPython). If the Python wrapper for UDM will not be used, you can skip this section
 		cd boost_1_55_0/
-		/tools/build/v2/engine/bin.macosxx86/bjam -sBUILD=release cxxflags="-g -O2 -arch i386" cflags="-g -O2 -arch i386" linkflags="-arch i386"
+		tools/build/v2/engine/bin.macosxx86/bjam -sBUILD=release cxxflags="-g -O2 -arch i386" cflags="-g -O2 -arch i386" linkflags="-arch i386"
 
 
 4. If build.sh will report 'operation not permitted', than the file was quarantined by Mac OS because it was downloaded from the internet. You can solve this by issuing xattr -dr com.apple.quarantine . in that directory.

Modified: UDM/trunk/include/UdmUtil.h
==============================================================================
--- UDM/trunk/include/UdmUtil.h	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/include/UdmUtil.h	Tue Apr 22 14:27:35 2014	(r4293)
@@ -91,8 +91,8 @@
 	UDM_DLL string stacktrace();
     
     //json stuff
-    UDM_DLL void write_json(const ::Udm::Object& obj, const string & FileName, bool child_attr_subtree = false);
-    
+    UDM_DLL void write_json(const ::Udm::Object& obj, const string & FileName, unsigned int options = 0);
+    UDM_DLL void write_json(const ::Uml::Diagram& dgr, const string & FileName, unsigned int options = 0);
     
 };
 

Modified: UDM/trunk/include/UmlExt.h
==============================================================================
--- UDM/trunk/include/UmlExt.h	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/include/UmlExt.h	Tue Apr 22 14:27:35 2014	(r4293)
@@ -190,6 +190,9 @@
     // addtionally, names of the child and parent roles can be provided to constraint the possible compositions.
 	UDM_DLL Composition matchChildToParent(Class c, Class p, const char * crole, const char * prole = NULL);
     
+    // addtionally, return all the possible Compositions names of the child and parent roles can be provided to constraint the possible compositions.
+	UDM_DLL set<Composition> compositionsChildToParent(Class c, Class p, const char * crole, const char * prole = NULL);
+    
     //finds the only suitable AssociationRole to reach 'target_class' or 'assoc_cls' from c for the association with which has the name 'rolename' on C's side
     //if target_aclass is provided than peer_type is ignored, and only those assoc. roles are considered which are in an assoc. cls. based assoc.
     //rolename can be NULL. if not null, the results will be filtered against the rolename as well
@@ -217,6 +220,16 @@
 
 	// get the corresponding class from the cross diagram
 	UDM_DLL Class GetClassFromCrossDgr(const Diagram &cross_dgr, const Class &cl);
+    //determines whether a class is the child end of a composition with the parent end in other namespace
+    UDM_DLL bool IsCrossNSCompositionChildEnd(const ::Uml::Class &c);
+    //return the classes that are
+    //not contained
+    //or it's only container is itself or an abstract superclass
+    // or it's the child end of a composition with the parent end in other namespace
+
+    UDM_DLL vector< ::Uml::Class> findNonContainedClasses(const ::Uml::Diagram & dgr);
+    
+
 
 	UDM_DLL Diagram GetDiagram(const Class &c);
 	UDM_DLL Diagram GetDiagram(const Association &assoc);

Modified: UDM/trunk/src/UdmBase/DTDGen.cpp
==============================================================================
--- UDM/trunk/src/UdmBase/DTDGen.cpp	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/src/UdmBase/DTDGen.cpp	Tue Apr 22 14:27:35 2014	(r4293)
@@ -1128,6 +1128,7 @@
 	return ret;
 }
 
+    /*
 static bool IsCrossNSCompositionChildEnd(const ::Uml::Class &c)
 {
 	::Uml::Namespace ns = c.parent_ns();
@@ -1150,7 +1151,7 @@
 
 	return false;
 }
-
+*/
 static void GenerateXMLSchemaForClasses(const ::Uml::Diagram &dgr,
 			      ostream &output,
 			      const set< ::Uml::Class> &classes,
@@ -1191,13 +1192,15 @@
 	set< ::Uml::Class>::const_iterator i = classes.begin();
 	while( i != classes.end() )
 	{
-		if(uxsdi || !(bool)i->isAbstract() )
-		{
+        // in these two ifs the behaviour is not affected by the value of uxsdi and of the ifs can be eliminated
+		//if(uxsdi || !(bool)i->isAbstract() )
+        // TODO: Use Uml::findNonContainedClasses instead of this.
+		//{
 			bool is_not_contained = false;
 
 			// XSD elements can't be of abstract types,
 			// don't make them globals
-			if (!uxsdi || !(bool)i->isAbstract()) {
+			if (/*!uxsdi || */!(bool)i->isAbstract()) {
 				set< ::Uml::Class> p_c = Uml::AncestorContainerClasses(*i);		//all possible containers
 				
 				//the condition: It's not contained
@@ -1210,13 +1213,13 @@
 						(anc == *i || (::Uml::IsDerivedFrom(*i, anc) && anc.isAbstract()))))
 					is_not_contained = true;
 
-				if (is_not_contained || IsCrossNSCompositionChildEnd(*i))
+				if (is_not_contained || ::Uml::IsCrossNSCompositionChildEnd(*i))
 					globalElements.push_back(*i);
 			}
 
 			GenerateXMLSchemaElement(*i,  output, ns_ignore_set, uxsdi, xsd_el_ta, is_not_contained);
 
-		}
+		//}
 		++i;
 	}
 

Modified: UDM/trunk/src/UdmBase/UmlExt.cpp
==============================================================================
--- UDM/trunk/src/UdmBase/UmlExt.cpp	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/src/UdmBase/UmlExt.cpp	Tue Apr 22 14:27:35 2014	(r4293)
@@ -572,6 +572,7 @@
 
 	UDM_DLL Composition matchChildToParent(Class c, Class p, const char * crole, const char * prole)
 	{
+        /*
 		Composition comp;
 		set<Class> pancs = AncestorClasses(p);
 		set<Class> cancs = AncestorClasses(c);
@@ -597,8 +598,35 @@
             }
 		}
 		return comp;
+         */
+        set<Composition> comps =compositionsChildToParent(c,p,crole, prole);
+        if (comps.size() != 1) return NULL;
+        else return *(comps.begin());
 	}
 
+    UDM_DLL set<Composition> compositionsChildToParent(Class c, Class p, const char * crole, const char * prole)
+	{
+		set<Composition> comp;
+		set<Class> pancs = AncestorClasses(p);
+		set<Class> cancs = AncestorClasses(c);
+		for(set<Class>::iterator j = cancs.begin(); j != cancs.end(); j++)
+        {
+			set<CompositionChildRole> cr = (*j).childRoles();
+            for(set<CompositionChildRole>::iterator i = cr.begin(); i != cr.end(); i++)
+            {
+                if (crole == NULL  || i->name() == string(crole))
+                {
+                    if (prole == NULL || theOther((*i)).name() == string(prole))
+                    {
+                        if(pancs.find(theOther(*i).target()) != pancs.end()) comp.insert((*i).parent());
+                    }
+                }
+            }
+		}
+		return comp;
+	}
+    
+
     
     UDM_DLL AssociationRole matchPeerToPeer(Class c, Class target_class, Class target_aclass, const char * rolename)
     {
@@ -877,11 +905,68 @@
 	};
 
 	// get the corresponding class from the cross diagram
-	UDM_DLL Class GetClassFromCrossDgr(const Diagram &cross_dgr, const Class &cl) {
+	UDM_DLL Class GetClassFromCrossDgr(const Diagram &cross_dgr, const Class &cl)
+    {
 		//The classname in cross diagram is: classname + cross_delimiter + diagramname ( + cross_delimiter + namespacename )*
 		string cross_cl_name = string(cl.name()) + string(Udm::cross_delimiter) + cl.GetParent().getPath2(Udm::cross_delimiter);
 		return classByName(cross_dgr, cross_cl_name);
 	}
+    
+    bool IsCrossNSCompositionChildEnd(const ::Uml::Class &c)
+    {
+        ::Uml::Namespace ns = c.parent_ns();
+        
+        set< ::Uml::CompositionParentRole> comps_c = ::Uml::AncestorCompositionPeerParentRoles(c);
+        for (set< ::Uml::CompositionParentRole>::iterator j = comps_c.begin(); j != comps_c.end(); j++)
+        {
+            ::Uml::Class theother = j->target();
+            
+            set< ::Uml::Class> desc = ::Uml::DescendantClasses(theother);
+            for (set< ::Uml::Class>::iterator jd = desc.begin(); jd != desc.end(); jd++)
+            {
+                ::Uml::Class cc = *jd;
+                
+                ::Uml::Namespace theother_ns = (::Uml::Namespace) cc.parent_ns();
+                if (ns != theother_ns)
+                    return true;
+            }
+        }
+        
+        return false;
+    };
+
+
+    UDM_DLL vector< ::Uml::Class> findNonContainedClasses(const ::Uml::Diagram & dgr)
+    {
+        vector< ::Uml::Class> globalElements;
+        set< ::Uml::Class> classes = dgr.classes();
+        set< ::Uml::Class>::const_iterator i = classes.begin();
+        while( i != classes.end() )
+        {
+            if (!(bool)i->isAbstract())
+            {
+                bool is_not_contained = false;
+                
+                // XSD elements can't be of abstract types,
+                // don't make them globals
+                set< ::Uml::Class> p_c = Uml::AncestorContainerClasses(*i);		//all possible containers
+                
+                //the condition: It's not contained
+                //				 or it's only container is itself or an abstract superclass
+                //				 or it's the child end of a composition with the parent end in other namespace
+                ::Uml::Class anc;
+                if ((p_c.size() == 0) || (p_c.size() == 1 && (anc = *(p_c.begin())) && (anc == *i || (::Uml::IsDerivedFrom(*i, anc) && anc.isAbstract()))))
+                    is_not_contained = true;
+                
+                if (is_not_contained || ::Uml::IsCrossNSCompositionChildEnd(*i))
+                    globalElements.push_back(*i);
+                
+                
+            }
+            ++i;
+        }
+        return globalElements;
+    };
 
 	// find a class by name
 	UDM_DLL Class classByName(const Diagram &d, const string &ns_path, const string &name, const string &delim)

Modified: UDM/trunk/src/UdmJson/UdmJson.cpp
==============================================================================
--- UDM/trunk/src/UdmJson/UdmJson.cpp	Mon Apr 14 15:29:40 2014	(r4292)
+++ UDM/trunk/src/UdmJson/UdmJson.cpp	Tue Apr 22 14:27:35 2014	(r4293)
@@ -2,6 +2,8 @@
 #include <Uml.h>
 #include <UdmUtil.h>
 #include <UmlExt.h>
+#include <json_spirit_writer_template.h>
+
 
 UDM_USE_DOM
 #ifdef _WIN32
@@ -12,50 +14,167 @@
 void dummy(void) {; }
 
 
-int main(int argc, char **argv) 
+/*
+ json writer options are:
+ 
+ pretty_print = 0x01,   // Add whitespace to format the output nicely.
+ 
+ raw_utf8 = 0x02,       // This prevents non-printable characters from being escapted using "\uNNNN" notation.
+                        // Note, this is an extension to the JSON standard. It disables the escaping of
+                        // non-printable characters allowing UTF-8 sequences held in 8 bit char strings
+                        // to pass through unaltered.
+ 
+ remove_trailing_zeros = 0x04,
+                        // outputs e.g. "1.200000000000000" as "1.2"
+ single_line_arrays = 0x08,
+                        // pretty printing except that arrays printed on single lines unless they contain
+                        // composite elements, i.e. objects or arrays
+ always_escape_nonascii = 0x10,
+                        // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they are
+                        // printable under the current locale, ascii printable chars are not escaped
+ */
+
+#define CMD_SW_PREFIX "--"
+struct cmd_line_option
 {
+    string desc;
+    unsigned int value;
+    cmd_line_option(string d, unsigned int v) : desc(d), value(v) {};
     
-    bool child_attr_subtree = false;
-	if (argc > 2 && strcmp(argv[1], "-s") == 0)
-	{
-		child_attr_subtree = true;
-		argc--;
-		argv++;
-	}
+};
 
-	if (argc != 4 )
-	{
-		cout << "Usage: UdmJson [-s] <inputdatafile> <outputjsonfile> <diagramname> " << endl;
-		cout << "  where: <diagramname>: Udm .xml file" << endl;
-        cout << " -s : generate children and attributes in _children and _attributes subtrees" << endl;
-		cout << "Available backends: " + Udm::DataNetwork::DumpBackendNames() << endl;
-                return(-1);
+struct cmd_line_options
+{
+    unsigned int options;
+    map <string, cmd_line_option> options_map;
+    set <string> parsed_options;
+    vector <string> positional_options;
+    void add(string sw, string desc, unsigned int value)
+    {
+        if (!sw.empty())
+        {
+            string options_sw = string(CMD_SW_PREFIX) + sw;
+            options_map.insert(pair<string, cmd_line_option> (sw, cmd_line_option(desc, value)));
+        }
+    }
+    bool parse(int argc, char **argv)
+    {
+        while (argc > 1)
+        {
+            
+            
+            if (strlen(argv[1]) > strlen(CMD_SW_PREFIX) &&  !strncmp(argv[1], CMD_SW_PREFIX, strlen(CMD_SW_PREFIX)))
+            {
+                //it is a switch
+                map <string, cmd_line_option>::iterator i = options_map.find(argv[1]+strlen(CMD_SW_PREFIX));
+                if (i != options_map.end())
+                {
+                    options = options | i->second.value;
+                    parsed_options.insert(argv[1]+strlen(CMD_SW_PREFIX));
+                } else return false;
+                
+            }
+            else positional_options.push_back(argv[1]);
+            argc--;
+            argv++;
+        }
+        return true;
+        
+    }
+    
+    bool option_provided(const string& o)
+    
+    {
+        return (parsed_options.find(o) != parsed_options.end());
+    }
 
+};
 
-	}
+std::ostream& operator<<(std::ostream& os, const cmd_line_options& clo)
+{
+    os << "Usage: UdmJson [options] <InputDataNetwork> <UmlMetaDiagram> <OutputJson> [<OutputSchema>]" << endl;
+    os << "Valid options are : " << endl;
+    
+    map <string, cmd_line_option>::const_iterator i = clo.options_map.begin();
+    for (; i!= clo.options_map.end(); i++)
+    {
+        os << string(CMD_SW_PREFIX) << i->first << string(":") << i->second.desc << endl;
+    }
+
+    return os;
+};
+
+
+int main(int argc, char **argv)
+{
+    
+    cmd_line_options clo;
+    
+    clo.add ("help", "                  Produce help message",0);
+    clo.add ("pretty_print", "          Add whitespace to format the output nicely", json_spirit::pretty_print);
+    clo.add ("remove_trailing_zeros", " Outputs e.g. \"1.200000000000000\" as \"1.2\"", json_spirit::remove_trailing_zeros);
+    clo.add ("single_line_arrays", "    Pretty printing arrays on single lines unless they contain composite elements, i.e. objects or arrays",json_spirit::single_line_arrays );
+    clo.add ("always_escape_nonascii", "All unicode wide characters are escaped, i.e. outputed as \"\\uXXXX\", even if they are printable under the current locale, ascii printable chars are not escaped", json_spirit::always_escape_nonascii);
+
+    
+    
+    if (!clo.parse(argc, argv))
+    {
+        cout << "Error: Invalid options. Use --help for usage "<< endl;
+        return -1;
+    }
+    
+    if (clo.option_provided("help"))
+    {
+        cout << clo << endl;
+        return 0;
+    }
+    
+    if (clo.positional_options.size() < 3 || clo.positional_options.size() > 4)
+    {
+        cout << "Error in providing input/meta/output/schema files. Use --help for usage "<< endl;
+        return -1;
+    }
+    
+   
+    string input_file = clo.positional_options[0];
+    string uml_diagram_file = clo.positional_options[1];
+    string json_output_file = clo.positional_options[2];
+    
+    string schema_output_file;
+    if( clo.positional_options.size() ==4 )
+         schema_output_file = clo.positional_options[3];
+    
+    
+    
 	// Loading the meta
-        Udm::SmartDataNetwork  ddnMeta(::Uml::diagram);
-        ::Uml::Diagram theUmlDiagram;
-        try {
-
-                // Opening the XML meta of the host graph
-                Udm::SmartDataNetwork ddnMeta_in(::Uml::diagram);
-                ddnMeta_in.OpenExisting(argv[3],"uml.dtd", Udm::CHANGES_LOST_DEFAULT);
+    Udm::SmartDataNetwork  ddnMeta(::Uml::diagram);
+    ::Uml::Diagram theUmlDiagram;
+    try {
+
+            // Opening the XML meta of the host graph
+            Udm::SmartDataNetwork ddnMeta_in(::Uml::diagram);
+            ddnMeta_in.OpenExisting(uml_diagram_file,"uml.dtd", Udm::CHANGES_LOST_DEFAULT);
 		
-		// Casting the DataNetwork to diagram
-                theUmlDiagram = ::Uml::Diagram::Cast(ddnMeta_in.GetRootObject());
+            // Casting the DataNetwork to diagram
+            theUmlDiagram = ::Uml::Diagram::Cast(ddnMeta_in.GetRootObject());
 
-                // Creating the UDM diagram
-                Udm::UdmDiagram udmDataDiagram;
-                udmDataDiagram.dgr = &theUmlDiagram;
-                udmDataDiagram.init = dummy;
-
-		Udm::SmartDataNetwork DN(udmDataDiagram);
-		DN.OpenExisting(argv[1],"",Udm::CHANGES_LOST_DEFAULT);
-		::UdmUtil::write_json(DN.GetRootObject(), argv[2],child_attr_subtree);
-		DN.CloseNoUpdate();		
+            // Creating the UDM diagram
+            Udm::UdmDiagram udmDataDiagram;
+            udmDataDiagram.dgr = &theUmlDiagram;
+            udmDataDiagram.init = dummy;
+
+            Udm::SmartDataNetwork DN(udmDataDiagram);
+            DN.OpenExisting(input_file,"",Udm::CHANGES_LOST_DEFAULT);
+            ::UdmUtil::write_json(DN.GetRootObject(), json_output_file, clo.options);
+            DN.CloseNoUpdate();
+        
+            if (!schema_output_file.empty())
+            {
+                ::UdmUtil::write_json(theUmlDiagram, schema_output_file, clo.options );
+            }
 	}
-	catch(udm_exception u) 
+	catch(udm_exception u)
 	{
                 cerr << u.what() << endl;
                 exit(-1);


More information about the Mobies-commit mailing list