summaryrefslogtreecommitdiff
path: root/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2025-03-19 15:41:36 +0100
committerJörg Frings-Fürst <debian@jff.email>2025-03-19 15:41:36 +0100
commit018e1ba581ec6f01f069a45ec4cf89f152b44d5f (patch)
tree0e7dda4bb693a6714066fbe5efcd2f24ff7c1a65 /libxsd-frontend/xsd-frontend/transformations/anonymous.cxx
parent1c188393cd2e271ed2581471b601fb5960777fd8 (diff)
remerge
Diffstat (limited to 'libxsd-frontend/xsd-frontend/transformations/anonymous.cxx')
-rw-r--r--libxsd-frontend/xsd-frontend/transformations/anonymous.cxx1016
1 files changed, 1016 insertions, 0 deletions
diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx
new file mode 100644
index 0000000..1c42d98
--- /dev/null
+++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx
@@ -0,0 +1,1016 @@
+// 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 ()
+ {
+ }
+ }
+}