diff options
Diffstat (limited to 'libxsd-frontend/xsd-frontend/transformations/anonymous.cxx')
-rw-r--r-- | libxsd-frontend/xsd-frontend/transformations/anonymous.cxx | 1016 |
1 files changed, 0 insertions, 1016 deletions
diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx deleted file mode 100644 index 1c42d98..0000000 --- a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx +++ /dev/null @@ -1,1016 +0,0 @@ -// file : xsd-frontend/transformations/anonymous.cxx -// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC -// license : GNU GPL v2 + exceptions; see accompanying LICENSE file - -#include <xsd-frontend/transformations/anonymous.hxx> - -#include <xsd-frontend/semantic-graph.hxx> -#include <xsd-frontend/traversal.hxx> - -#include <iostream> -#include <sstream> -#include <typeinfo> - -using std::wcerr; -using std::endl; - -namespace XSDFrontend -{ - 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<Element&> (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<Attribute&> (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&> (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<List&> (type_)); - } - - virtual void - traverse (SemanticGraph::Union& x) - { - using SemanticGraph::Union; - - Union& y (dynamic_cast<Union&> (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<Enumeration&> (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<Restricts&> (x.inherits ())); - Restricts& ry (dynamic_cast<Restricts&> (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<Complex&> (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> ()) - { - Restricts& rx (dynamic_cast<Restricts&> (x.inherits ())); - Restricts& ry (dynamic_cast<Restricts&> (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_, - bool du) - : schema_path_ (file), - ns_ (0), - failed_ (false), - trans (trans_), - detect_unstable (du), - schema (schema_), - schema_path (schema_path_), - ns (ns_), - failed (failed_) - { - - } - - protected: - Context (Context& c) - : trans (c.trans), - detect_unstable (c.detect_unstable), - schema (c.schema), - schema_path (c.schema_path), - ns (c.ns), - failed (c.failed) - { - } - - 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) - : type_ (type) - { - } - - SemanticGraph::Type& - type () const - { - return type_; - } - - private: - SemanticGraph::Type& type_; - }; - - SemanticGraph::Type* - conflict (String const& name) - { - using SemanticGraph::Type; - using SemanticGraph::Schema; - - if (Type* t1 = find (schema, name)) - { - // Check if this is a stable conflict. A conflict is unstable - // if a conflicting type is visible from the root schema but - // is not visible from the schema where the conflicting - // element is defined. - // - if (detect_unstable) - { - Schema& s (dynamic_cast<Schema&> (ns->scope ())); - - Type* t2 (find (s, name)); - - if (t1 != t2) - throw UnstableConflict (*t1); - } - - return t1; - } - - return 0; - } - - SemanticGraph::Type* - find (SemanticGraph::Schema& schema, String const& name) - { - using SemanticGraph::Type; - using SemanticGraph::Scope; - using SemanticGraph::Namespace; - - String ns_name (ns->name ()); - - // Get all namespaces across include/import hierarchy with - // our namespace name. - // - Scope::NamesIteratorPair nip (schema.find (ns_name)); - - for (; nip.first != nip.second; ++nip.first) - { - Namespace& ns (dynamic_cast<Namespace&> (nip.first->named ())); - - Scope::NamesIteratorPair types (ns.find (name)); - - for (; types.first != types.second; ++types.first) - { - if (Type* t = dynamic_cast<Type*> (&types.first->named ())) - { - return t; - } - } - } - - return 0; - } - - public: - SemanticGraph::Path - path (SemanticGraph::Nameable& n) - { - using SemanticGraph::Scope; - using SemanticGraph::Schema; - using SemanticGraph::Uses; - - Schema* schema (0); - - for (Scope* s (dynamic_cast<Scope*> (&n) - ? dynamic_cast<Scope*> (&n) : &n.scope ());; - s = &s->scope ()) - { - if ((schema = dynamic_cast<Schema*> (s))) - break; - } - - if (!schema->used_p ()) - return schema_path; - - Uses& u (*schema->used_begin ()); - return u.path (); - } - - public: - String - xpath (SemanticGraph::Nameable& n) - { - if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0) - return L"<namespace-level>"; // There is a bug if you see this. - - assert (n.named_p ()); - - SemanticGraph::Scope& scope (n.scope ()); - - if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0) - return n.name (); - - return xpath (scope) + L"/" + n.name (); - } - - private: - SemanticGraph::Path const schema_path_; - SemanticGraph::Namespace* ns_; - bool failed_; - - public: - AnonymousNameTranslator& trans; - bool detect_unstable; - - public: - SemanticGraph::Schema& schema; - SemanticGraph::Path const& schema_path; - SemanticGraph::Namespace*& ns; - bool& failed; - }; - - - // Go into implied/included/imported schemas while making sure - // we don't process the same stuff more than once. - // - struct Uses: Traversal::Uses - { - virtual void - traverse (Type& u) - { - SemanticGraph::Schema& s (u.schema ()); - - if (!s.context ().count ("xsd-frontend-anonymous-seen")) - { - s.context ().set ("xsd-frontend-anonymous-seen", true); - Traversal::Uses::traverse (u); - } - } - }; - - // Keep track which namespace we are in. - // - struct Namespace: Traversal::Namespace - { - Namespace (SemanticGraph::Namespace*& ns) - : ns_ (ns) - { - } - - void - pre (SemanticGraph::Namespace& ns) - { - ns_ = &ns; - } - - void - post (SemanticGraph::Namespace&) - { - ns_ = 0; - } - - private: - SemanticGraph::Namespace*& ns_; - }; - - // - // - struct Type: Traversal::List, - Traversal::Union, - Traversal::Complex, - protected virtual Context - { - Type (Context& c) - : Context (c) - { - } - - virtual void - traverse (SemanticGraph::List& l) - { - SemanticGraph::Type& t (l.argumented ().type ()); - - //@@ This IDREF stuff is really ugly! - // - if (!t.named_p () && - !t.is_a<SemanticGraph::Fundamental::IdRef> () && - !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) - { - try - { - // 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 - // fails, fall back to the native representation. - // - try - { - file_str = file.posix_string (); - } - catch (SemanticGraph::InvalidPath const&) - { - file_str = file.string (); - } - - String name ( - trans.translate ( - file_str, ns->name (), l.name () + L"_item", xpath (l))); - - // Make sure the name is unique. - // - unsigned long n (1); - String escaped (name); - - while (conflict (escaped)) - { - std::wostringstream os; - os << n++; - escaped = name + os.str (); - } - - t.context ().set ("anonymous", true); - schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); - } - catch (UnstableConflict const& ex) - { - SemanticGraph::Type& t (ex.type ()); - - wcerr << l.file () << ":" << l.line () << ":" << l.column () - << ": error: list type name '" << xpath (l) << "' " - << "creates an unstable conflict when used as a base " - << "for the item type name" - << endl; - - wcerr << t.file () << ":" << t.line () << ":" << t.column () - << ": info: conflicting type is defined here" << endl; - - wcerr << l.file () << ":" << l.line () << ":" << l.column () - << ": info: " - << "use --anonymous-regex to resolve this conflict" - << endl; - - wcerr << l.file () << ":" << l.line () << ":" << l.column () - << ": info: " - << "and don't forget to pass the same option when " - << "translating '" << l.file ().leaf () << "' and all " - << "the schemas that refer to it" << endl; - - failed = true; - } - } - } - - virtual void - traverse (SemanticGraph::Union& u) - { - String file_str; - - for (SemanticGraph::Union::ArgumentedIterator i ( - u.argumented_begin ()); i != u.argumented_end (); ++i) - { - SemanticGraph::Type& t (i->type ()); - - if (!t.named_p () && - !t.is_a<SemanticGraph::Fundamental::IdRef> () && - !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) - { - try - { - // Run the name through the translation service. - // - - 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.posix_string (); - } - catch (SemanticGraph::InvalidPath const&) - { - file_str = file.string (); - } - } - - String name ( - trans.translate ( - file_str, ns->name (), u.name () + L"_member", xpath (u))); - - // Make sure the name is unique. - // - unsigned long n (1); - String escaped (name); - - while (conflict (escaped)) - { - std::wostringstream os; - os << n++; - escaped = name + os.str (); - } - - t.context ().set ("anonymous", true); - schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); - } - catch (UnstableConflict const& ex) - { - SemanticGraph::Type& t (ex.type ()); - - wcerr << u.file () << ":" << u.line () << ":" << u.column () - << ": error: union type name '" << xpath (u) << "' " - << "creates an unstable conflict when used as a base " - << "for the member type name" - << endl; - - wcerr << t.file () << ":" << t.line () << ":" << t.column () - << ": info: conflicting type is defined here" << endl; - - wcerr << u.file () << ":" << u.line () << ":" << u.column () - << ": info: " - << "use --anonymous-regex to resolve this conflict" - << endl; - - wcerr << u.file () << ":" << u.line () << ":" << u.column () - << ": info: " - << "and don't forget to pass the same option when " - << "translating '" << u.file ().leaf () << "' and all " - << "the schemas that refer to it" << endl; - - failed = true; - } - } - } - } - - virtual void - traverse (SemanticGraph::Complex& c) - { - if (!c.inherits_p ()) - return; - - SemanticGraph::Type& t (c.inherits ().base ()); - - //@@ This IDREF stuff is really ugly! - // - if (!t.named_p () && - !t.is_a<SemanticGraph::Fundamental::IdRef> () && - !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) - { - try - { - // 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 - // fails, fall back to the native representation. - // - try - { - file_str = file.posix_string (); - } - catch (SemanticGraph::InvalidPath const&) - { - file_str = file.string (); - } - - String name ( - trans.translate ( - file_str, ns->name (), c.name () + L"_base", xpath (c))); - - // Make sure the name is unique. - // - unsigned long n (1); - String escaped (name); - - while (conflict (escaped)) - { - std::wostringstream os; - os << n++; - escaped = name + os.str (); - } - - t.context ().set ("anonymous", true); - schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); - } - catch (UnstableConflict const& ex) - { - SemanticGraph::Type& t (ex.type ()); - - wcerr << c.file () << ":" << c.line () << ":" << c.column () - << ": error: simple type name '" << xpath (c) << "' " - << "creates an unstable conflict when used as a base " - << "for the base type name" - << endl; - - wcerr << t.file () << ":" << t.line () << ":" << t.column () - << ": info: conflicting type is defined here" << endl; - - wcerr << c.file () << ":" << c.line () << ":" << c.column () - << ": info: " - << "use --anonymous-regex to resolve this conflict" - << endl; - - wcerr << c.file () << ":" << c.line () << ":" << c.column () - << ": info: " - << "and don't forget to pass the same option when " - << "translating '" << c.file ().leaf () << "' and all " - << "the schemas that refer to it" << endl; - - failed = true; - } - } - } - }; - - - // - // - struct Member: Traversal::Element, - Traversal::Attribute, - protected virtual Context - { - Member (Context& c) - : Context (c) - { - } - - virtual void - traverse (SemanticGraph::Element& e) - { - SemanticGraph::Type& t (e.type ()); - - //@@ This IDREF stuff is really ugly! - // - if (!t.named_p () && - !t.is_a<SemanticGraph::Fundamental::IdRef> () && - !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) - { - try - { - traverse_ (e); - } - catch (UnstableConflict const& ex) - { - SemanticGraph::Type& t (ex.type ()); - - wcerr << e.file () << ":" << e.line () << ":" << e.column () - << ": error: element name '" << xpath (e) << "' " - << "creates an unstable conflict when used as a type name" - << endl; - - wcerr << t.file () << ":" << t.line () << ":" << t.column () - << ": info: conflicting type is defined here" << endl; - - wcerr << e.file () << ":" << e.line () << ":" << e.column () - << ": info: " - << "use --anonymous-regex to resolve this conflict" - << endl; - - wcerr << e.file () << ":" << e.line () << ":" << e.column () - << ": info: " - << "and don't forget to pass the same option when " - << "translating '" << e.file ().leaf () << "' and all " - << "the schemas that refer to it" << endl; - - failed = true; - } - } - } - - virtual void - traverse (SemanticGraph::Attribute& a) - { - SemanticGraph::Type& t (a.type ()); - - //@@ This IDREF stuff us really ugly! - // - if (!t.named_p () && - !t.is_a<SemanticGraph::Fundamental::IdRef> () && - !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) - { - try - { - traverse_ (a); - } - catch (UnstableConflict const& ex) - { - SemanticGraph::Type& t (ex.type ()); - - wcerr << a.file () << ":" << a.line () << ":" << a.column () - << ": error: attribute name '" << xpath (a) << "' " - << "creates an unstable conflict when used as a type name" - << endl; - - wcerr << t.file () << ":" << t.line () << ":" << t.column () - << ": info: conflicting type is defined here" << endl; - - wcerr << a.file () << ":" << a.line () << ":" << a.column () - << ": info: " - << "use --anonymous-regex to resolve this conflict" - << endl; - - wcerr << a.file () << ":" << a.line () << ":" << a.column () - << ": info: " - << "and don't forget to pass the same option when " - << "translating '" << a.file ().leaf () << "' and all " - << "the schemas that refer to it" << endl; - - failed = true; - } - } - } - - void - traverse_ (SemanticGraph::Member& m) - { - using SemanticGraph::Type; - - Type& t (m.type ()); - - // Normally this will be the member which also "defined" the type. - // However, in some cases of cyclic schema inclusion, this does - // not happen. As a result we need an extra check that will make - // sure we create the Names edge in the same Schema node as the - // one which contains the member which initially defined this - // type. See the cyclic-inclusion test for an example. - // - - // Find the first member that this type classifies. - // - for (Type::ClassifiesIterator i (t.classifies_begin ()); - i != t.classifies_end (); ++i) - { - SemanticGraph::Instance& inst (i->instance ()); - - if (inst.is_a<SemanticGraph::Member> ()) - { - // If it is the same member as the one we are traversing, - // then continue. - // - if (&inst == &m) - break; - else - return; - } - } - - // 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 - // fails, fall back to the native representation. - // - try - { - file_str = file.posix_string (); - } - catch (SemanticGraph::InvalidPath const&) - { - file_str = file.string (); - } - - String name ( - trans.translate (file_str, ns->name (), m.name (), xpath (m))); - - // Check if this name conflicts. - // - unsigned long n (1); - String escaped (name); - - 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 (); - } - - t.context ().set ("anonymous", true); - schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); - } - }; - } - - namespace Transformations - { - Anonymous:: - Anonymous (AnonymousNameTranslator& trans) - : trans_ (trans) - { - } - - void Anonymous:: - transform (SemanticGraph::Schema& s, - SemanticGraph::Path const& f, - bool duc) - { - Context ctx (s, f, trans_, duc); - - Traversal::Schema schema; - Uses uses; - - schema >> uses >> schema; - - Traversal::Names schema_names; - Namespace ns (ctx.ns); - Traversal::Names ns_names_member; - Traversal::Names ns_names_type; - - schema >> schema_names >> ns; - ns >> ns_names_member; - ns >> ns_names_type; - - Type type (ctx); - ns_names_type >> type; - - Traversal::Scope scope; // Goes to both types and groups. - Member member (ctx); - - ns_names_member >> scope; - ns_names_member >> member; - - Traversal::Names names; - - scope >> names >> member; - - // Some twisted schemas do recusive inclusions. - // - s.context ().set ("xsd-frontend-anonymous-seen", true); - - schema.dispatch (s); - - if (ctx.failed) - throw Failed (); - } - - AnonymousNameTranslator:: - ~AnonymousNameTranslator () - { - } - } -} |