summaryrefslogtreecommitdiff
path: root/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libxsd-frontend/xsd-frontend/transformations/anonymous.cxx')
-rw-r--r--libxsd-frontend/xsd-frontend/transformations/anonymous.cxx377
1 files changed, 327 insertions, 50 deletions
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 <boris@codesynthesis.com>
-// 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 <xsd-frontend/transformations/anonymous.hxx>
@@ -10,27 +9,281 @@
#include <iostream>
#include <sstream>
+#include <typeinfo>
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<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_,
- 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);