From 8286ac511144e4f17d34eac9affb97e50646344a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 23 Jul 2014 15:25:44 +0200 Subject: Imported Upstream version 4.0.0 --- .../xsd-frontend/transformations/anonymous.cxx | 377 ++++++++++++++++++--- 1 file changed, 327 insertions(+), 50 deletions(-) (limited to 'libxsd-frontend/xsd-frontend/transformations/anonymous.cxx') diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx index 118fd5d..1c42d98 100644 --- a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx +++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx @@ -1,6 +1,5 @@ // file : xsd-frontend/transformations/anonymous.cxx -// author : Boris Kolpackov -// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include @@ -10,27 +9,281 @@ #include #include +#include using std::wcerr; using std::endl; namespace XSDFrontend { - using namespace Cult; - - typedef WideString String; - namespace { using Transformations::AnonymousNameTranslator; + // + // + struct CompareMembers: Traversal::Element, + Traversal::Attribute, + Traversal::Any, + Traversal::AnyAttribute + { + CompareMembers (SemanticGraph::Nameable& m, bool& r) + : member_ (m), result_ (r) + { + } + + virtual void + traverse (SemanticGraph::Element& x) + { + using SemanticGraph::Element; + + Element& y (dynamic_cast (member_)); + + // Check cardinalities. + // + if (x.min () != y.min () || x.max () != y.max ()) + return; + + traverse_member (x); + } + + virtual void + traverse (SemanticGraph::Attribute& x) + { + using SemanticGraph::Attribute; + + Attribute& y (dynamic_cast (member_)); + + // Check cardinalities. + // + if (x.optional_p () != y.optional_p ()) + return; + + traverse_member (x); + } + + virtual void + traverse_member (SemanticGraph::Member& x) + { + using SemanticGraph::Member; + + Member& y (dynamic_cast (member_)); + + // Check name. + // + if (x.name () != y.name ()) + return; + + // Check namespace. + // + if (x.qualified_p () || y.qualified_p ()) + { + if (!x.qualified_p () || !y.qualified_p ()) + return; + + if (x.namespace_ ().name () != y.namespace_ ().name ()) + return; + } + + // Check type. + // + // @@ What if types are anonymous and structurally equal? + // + if (&x.type () != &y.type ()) + return; + + // Check default/fixed values. + // + if (x.default_p () != y.default_p () || x.fixed_p () != y.fixed_p ()) + return; + + if (x.default_p () && x.value () != y.value ()) + return; + + result_ = true; + } + + virtual void + traverse (SemanticGraph::Any&) + { + //@@ TODO + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + //@@ TODO + } + + private: + SemanticGraph::Nameable& member_; + bool& result_; + }; + + // Compare two types for structural equality. + // + struct CompareTypes: Traversal::List, + Traversal::Union, + Traversal::Enumeration, + Traversal::Complex + { + CompareTypes (SemanticGraph::Type& t, bool& r) + : type_ (t), result_ (r) + { + } + + + virtual void + traverse (SemanticGraph::List&) + { + using SemanticGraph::List; + + //List& y (dynamic_cast (type_)); + } + + virtual void + traverse (SemanticGraph::Union& x) + { + using SemanticGraph::Union; + + Union& y (dynamic_cast (type_)); + + Union::ArgumentedIterator ix (x.argumented_begin ()), + iy (y.argumented_begin ()); + + for (; ix != x.argumented_end () && iy != y.argumented_end (); + ++ix, ++iy) + { + // @@ Anon structurally equivalent. + // + if (&iy->type () != &ix->type ()) + return; + } + + result_ = true; + } + + virtual void + traverse (SemanticGraph::Enumeration& x) + { + using SemanticGraph::Enumeration; + + Enumeration& y (dynamic_cast (type_)); + + // Bases should be the same. + // + if (&x.inherits ().base () != &y.inherits ().base ()) + return; + + // Make sure facets match. + // + using SemanticGraph::Restricts; + + Restricts& rx (dynamic_cast (x.inherits ())); + Restricts& ry (dynamic_cast (y.inherits ())); + + if (rx.facets () != ry.facets ()) + return; + + // Compare enumerators. + // + using SemanticGraph::Scope; + + Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); + for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) + { + if (ix->name () != iy->name ()) + return; + } + + if (ix != x.names_end () || iy != y.names_end ()) + return; + + result_ = true; + } + + virtual void + traverse (SemanticGraph::Complex& x) + { + using SemanticGraph::Complex; + + Complex& y (dynamic_cast (type_)); + + // Check inheritance. + // + if (x.inherits_p () || y.inherits_p ()) + { + // They both must inherits. + // + if (!x.inherits_p () || !y.inherits_p ()) + return; + + // With the same kind of inheritance (restriction or extension). + // + if (typeid (x.inherits ()) != typeid (y.inherits ())) + return; + + // Bases should be the same. + // + // @@ What if bases are anonymous? + // + if (&x.inherits ().base () != &y.inherits ().base ()) + return; + + // If it is a restriction, make sure facets match. + // + using SemanticGraph::Restricts; + + if (x.inherits ().is_a ()) + { + Restricts& rx (dynamic_cast (x.inherits ())); + Restricts& ry (dynamic_cast (y.inherits ())); + + if (rx.facets () != ry.facets ()) + return; + } + } + + // Check the member list. + // + // @@ Ignoring compositors at the moment. + // + using SemanticGraph::Scope; + + Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); + for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) + { + if (typeid (ix->named ()) != typeid (iy->named ())) + return; + + bool equal (false); + CompareMembers t (iy->named (), equal); + t.dispatch (ix->named ()); + + if (!equal) + return; + } + + if (ix != x.names_end () || iy != y.names_end ()) + return; + + result_ = true; + } + + private: + SemanticGraph::Type& type_; + bool& result_; + }; + + // + // class Context { public: Context (SemanticGraph::Schema& schema_, SemanticGraph::Path const& file, AnonymousNameTranslator& trans_, - Boolean du) + bool du) : schema_path_ (file), ns_ (0), failed_ (false), @@ -56,6 +309,19 @@ namespace XSDFrontend } public: + + bool + structurally_equal (SemanticGraph::Type& x, SemanticGraph::Type& y) + { + if (typeid (x) != typeid (y)) + return false; + + bool r (false); + CompareTypes t (y, r); + t.dispatch (x); + return r; + } + struct UnstableConflict { UnstableConflict (SemanticGraph::Type& type) @@ -73,7 +339,7 @@ namespace XSDFrontend SemanticGraph::Type& type_; }; - Boolean + SemanticGraph::Type* conflict (String const& name) { using SemanticGraph::Type; @@ -96,10 +362,10 @@ namespace XSDFrontend throw UnstableConflict (*t1); } - return true; + return t1; } - return false; + return 0; } SemanticGraph::Type* @@ -179,17 +445,17 @@ namespace XSDFrontend private: SemanticGraph::Path const schema_path_; SemanticGraph::Namespace* ns_; - Boolean failed_; + bool failed_; public: AnonymousNameTranslator& trans; - Boolean detect_unstable; + bool detect_unstable; public: SemanticGraph::Schema& schema; SemanticGraph::Path const& schema_path; SemanticGraph::Namespace*& ns; - Boolean& failed; + bool& failed; }; @@ -198,7 +464,7 @@ namespace XSDFrontend // struct Uses: Traversal::Uses { - virtual Void + virtual void traverse (Type& u) { SemanticGraph::Schema& s (u.schema ()); @@ -220,13 +486,13 @@ namespace XSDFrontend { } - Void + void pre (SemanticGraph::Namespace& ns) { ns_ = &ns; } - Void + void post (SemanticGraph::Namespace&) { ns_ = 0; @@ -248,7 +514,7 @@ namespace XSDFrontend { } - virtual Void + virtual void traverse (SemanticGraph::List& l) { SemanticGraph::Type& t (l.argumented ().type ()); @@ -264,6 +530,7 @@ namespace XSDFrontend // Run the name through the translation service. // SemanticGraph::Path file (path (l)); + file.normalize (); String file_str; // Try to use the portable representation of the path. If that @@ -271,15 +538,11 @@ namespace XSDFrontend // try { - file_str = file.string (); + file_str = file.posix_string (); } catch (SemanticGraph::InvalidPath const&) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - file_str = file.native_file_string (); -#else file_str = file.string (); -#endif } String name ( @@ -288,7 +551,7 @@ namespace XSDFrontend // Make sure the name is unique. // - UnsignedLong n (1); + unsigned long n (1); String escaped (name); while (conflict (escaped)) @@ -330,7 +593,7 @@ namespace XSDFrontend } } - virtual Void + virtual void traverse (SemanticGraph::Union& u) { String file_str; @@ -352,21 +615,18 @@ namespace XSDFrontend if (!file_str) { SemanticGraph::Path file (path (u)); + file.normalize (); // Try to use the portable representation of the path. If // that fails, fall back to the native representation. // try { - file_str = file.string (); + file_str = file.posix_string (); } catch (SemanticGraph::InvalidPath const&) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - file_str = file.native_file_string (); -#else file_str = file.string (); -#endif } } @@ -376,7 +636,7 @@ namespace XSDFrontend // Make sure the name is unique. // - UnsignedLong n (1); + unsigned long n (1); String escaped (name); while (conflict (escaped)) @@ -419,7 +679,7 @@ namespace XSDFrontend } } - virtual Void + virtual void traverse (SemanticGraph::Complex& c) { if (!c.inherits_p ()) @@ -438,6 +698,7 @@ namespace XSDFrontend // Run the name through the translation service. // SemanticGraph::Path file (path (c)); + file.normalize (); String file_str; // Try to use the portable representation of the path. If that @@ -445,15 +706,11 @@ namespace XSDFrontend // try { - file_str = file.string (); + file_str = file.posix_string (); } catch (SemanticGraph::InvalidPath const&) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - file_str = file.native_file_string (); -#else file_str = file.string (); -#endif } String name ( @@ -462,7 +719,7 @@ namespace XSDFrontend // Make sure the name is unique. // - UnsignedLong n (1); + unsigned long n (1); String escaped (name); while (conflict (escaped)) @@ -517,7 +774,7 @@ namespace XSDFrontend { } - virtual Void + virtual void traverse (SemanticGraph::Element& e) { SemanticGraph::Type& t (e.type ()); @@ -560,7 +817,7 @@ namespace XSDFrontend } } - virtual Void + virtual void traverse (SemanticGraph::Attribute& a) { SemanticGraph::Type& t (a.type ()); @@ -603,7 +860,7 @@ namespace XSDFrontend } } - Void + void traverse_ (SemanticGraph::Member& m) { using SemanticGraph::Type; @@ -640,6 +897,7 @@ namespace XSDFrontend // Run the name through the translation service. // SemanticGraph::Path file (path (m)); + file.normalize (); String file_str; // Try to use the portable representation of the path. If that @@ -647,27 +905,46 @@ namespace XSDFrontend // try { - file_str = file.string (); + file_str = file.posix_string (); } catch (SemanticGraph::InvalidPath const&) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - file_str = file.native_file_string (); -#else file_str = file.string (); -#endif } String name ( trans.translate (file_str, ns->name (), m.name (), xpath (m))); - // Make sure the name is unique. + // Check if this name conflicts. // - UnsignedLong n (1); + unsigned long n (1); String escaped (name); - while (conflict (escaped)) + while (SemanticGraph::Type* other = conflict (escaped)) { + // First see if we should just use the other type. It should + // also have been anonymous and structurally equal to our type. + // + if (other->context ().count ("anonymous")) + { + if (structurally_equal (t, *other)) + { + // Reset the elements that are classified by this type to point + // to the other type. + // + for (Type::ClassifiesIterator i (t.classifies_begin ()); + i != t.classifies_end (); ++i) + { + schema.reset_right_node (*i, *other); + } + + //wcerr << "equal " << name << endl; + return; + } + //else + //wcerr << "unequal " << name << endl; + } + std::wostringstream os; os << n++; escaped = name + os.str (); @@ -687,10 +964,10 @@ namespace XSDFrontend { } - Void Anonymous:: + void Anonymous:: transform (SemanticGraph::Schema& s, SemanticGraph::Path const& f, - Boolean duc) + bool duc) { Context ctx (s, f, trans_, duc); -- cgit v1.2.3