1# -*- coding: utf-8 -*-
2# Copyright 2009-2013, Peter A. Bigot
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain a
6# copy of the License at:
7#
8#            http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Classes corresponding to W3C XML Schema components.
17
18Class names and behavior should conform to the schema components described in
19U{XML Schema Part 1: Structures<http://www.w3.org/TR/xmlschema-1/>}.
20References to sections in the documentation of this module generally refers to
21that document.
22
23Each class has a C{CreateFromDOM} class method that creates an instance and
24initializes it from a DOM node.  Only the L{Wildcard}, L{Particle}, and
25L{ModelGroup} components are created from non-DOM sources.  However, the
26requirements on DOM interface are restricted to attributes, child nodes, and
27basic fields, though all these must support namespaces.
28
29@group Mixins: *_mixin
30@group Ur Type Specializations: *UrType*
31@group Utilities: _ImportElementInformationItem
32
33"""
34
35import re
36import logging
37from xml.dom import Node
38import copy
39from pyxb.utils.six.moves.urllib import parse as urlparse
40import os.path
41
42import pyxb
43import pyxb.xmlschema
44import pyxb.namespace.archive
45import pyxb.namespace.resolution
46
47from pyxb.binding import basis, datatypes, facets
48from pyxb.utils import domutils, six
49import pyxb.utils.utility
50
51_log = logging.getLogger(__name__)
52
53# Flag indicating that the built in types have been registered
54_PastAddBuiltInTypes = False
55
56# Make it easier to check node names in the XMLSchema namespace
57from pyxb.namespace import XMLSchema as xsd
58
59class _SchemaComponent_mixin (pyxb.namespace._ComponentDependency_mixin,
60                              pyxb.namespace.archive._ArchivableObject_mixin,
61                              pyxb.utils.utility.PrivateTransient_mixin,
62                              pyxb.utils.utility.Locatable_mixin):
63    """A mix-in that marks the class as representing a schema component.
64
65    This exists so that we can determine the owning schema for any
66    component we encounter.  This is normally done at construction
67    time by passing a C{schema=val} parameter to the constructor.
68    """
69
70    # This class suppports transient instance variables.  These variables are
71    # added to the set of transients at the point of declaration in the class.
72    __PrivateTransient = set()
73
74    def _namespaceContext (self):
75        """The namespace context for this schema.
76
77        This defines where it looks things up, where it puts things it
78        creates, the in-scope namespace declarations, etc.  Must be defined
79        for anything that does any sort of QName interpretation.  The value is
80        generally a reference to a namespace context associated with the DOM
81        element node corresponding to this component."""
82        if self.__namespaceContext is None:
83            raise pyxb.LogicError('Attempt to access missing namespace context for %s' % (self,))
84        return self.__namespaceContext
85    def _clearNamespaceContext (self):
86        # Calculate the binding sort key for any archive before we discard the
87        # namespace context, which we might need.
88        self.schemaOrderSortKey()
89        self.__namespaceContext = None
90        return self
91    __namespaceContext = None
92    __PrivateTransient.add('namespaceContext')
93
94    # The name by which this component is known within the binding module.
95    # This is in component rather than _NamedComponent_mixin because some
96    # unnamed components (like ModelGroup and Wildcard) have Python objects to
97    # represent them, so need a binding-level name.
98    __nameInBinding = None
99
100    # The public unique name by which this component is referenced within the
101    # binding class (as opposed to the binding module).
102    __uniqueNameInBinding = None
103
104    # The schema component that owns this.  If C{None}, the component is owned
105    # directly by the schema.
106    __owner = None
107    __PrivateTransient.add('owner')
108
109    # The schema components owned by this component.
110    __ownedComponents = None
111    __PrivateTransient.add('ownedComponent')
112
113    def _scope (self):
114        """The context into which declarations in or subordinate to this node are placed."""
115        return self.__scope
116    __scope = None
117
118    def _scopeIsIndeterminate (self):
119        """Return True iff nobody has defined a scope for this node."""
120        return _ScopedDeclaration_mixin.ScopeIsIndeterminate(self._scope())
121
122    def _scopeIsGlobal (self):
123        """Return True iff this component has global scope."""
124        return _ScopedDeclaration_mixin.ScopeIsGlobal(self._scope())
125
126    def _setScope (self, ctd):
127        """Set the scope of this instance after construction.
128
129        This should only be invoked on cloned declarations being incorporated
130        into a complex type definition.  Note that the source of the clone may
131        be any scope: indeterminate if from a model (attribute) group
132        definition; global if a reference to a global component; or ctd if
133        inherited from a complex base type."""
134        assert self.__cloneSource is not None
135        assert isinstance(self, _ScopedDeclaration_mixin)
136        assert isinstance(ctd, ComplexTypeDefinition)
137        self.__scope = ctd
138        return self
139
140    def __init__ (self, *args, **kw):
141        """Initialize portions of a component.
142
143        @keyword scope: The scope in which the component is defined
144
145        @keyword namespace_context: The NamespaceContext to use within this component
146
147        @keyword node: If no C{namespace_context} is provided, a DOM node must
148        be provided from which a namespace context can be identified.
149
150        @keyword owner: Reference to the component that owns this one (the
151        immediately enclosing component).  Is C{None} in the case of top-level
152        components.
153
154        @keyword schema: Reference to the L{Schema} component to which the
155        component belongs.  Required for every component except L{Schema},
156        L{Annotation}, and L{Wildcard}.
157        """
158
159        self.__ownedComponents = set()
160        self.__scope = kw.get('scope')
161        self.__namespaceContext = kw.get('namespace_context')
162        node = kw.get('node')
163        owner = kw.get('owner')
164        if self.__namespaceContext is None:
165            if node is None:
166                raise pyxb.LogicError('Schema component constructor must be given namespace_context or node')
167            self.__namespaceContext = pyxb.namespace.NamespaceContext.GetNodeContext(node)
168        if self.__namespaceContext is None:
169            raise pyxb.LogicError('No namespace_context for schema component')
170
171        super(_SchemaComponent_mixin, self).__init__(*args, **kw)
172
173        self._namespaceContext().targetNamespace()._associateComponent(self)
174
175        self._setOwner(owner)
176        if isinstance(node, pyxb.utils.utility.Locatable_mixin):
177            self._setLocation(node._location())
178        elif isinstance(owner, pyxb.utils.utility.Locatable_mixin):
179            self._setLocation(owner._location())
180
181        schema = kw.get('schema')
182        if schema is not None:
183            self._setObjectOrigin(schema.originRecord())
184        else:
185            assert isinstance(self, (Schema, Annotation, Wildcard)), 'No origin available for type %s' % (type(self),)
186
187        if isinstance(self, ComplexTypeDefinition):
188            assert 1 < len(self.__namespaceContext.inScopeNamespaces())
189
190    def _dissociateFromNamespace (self):
191        """Dissociate this component from its owning namespace.
192
193        This should only be done whwen there are no other references to the
194        component, and you want to ensure it does not appear in the model."""
195        self._namespaceContext().targetNamespace()._replaceComponent(self, None)
196        return self
197
198    def _setOwner (self, owner):
199        """Set the owner of this component.
200
201        If C{owner} is C{None}, this has no effect.  Otherwise, the
202        component's current owner must be either C{None} or the same as the
203        input C{owner}."""
204
205        if owner is not None:
206            assert (self.__owner is None) or (self.__owner == owner), 'Owner was %s set to %s' % (self.__owner, owner)
207            self.__owner = owner
208            owner.__ownedComponents.add(self)
209        return self
210
211    def owner (self):
212        return self.__owner
213
214    # A reference to the instance from which this instance was cloned.
215    __cloneSource = None
216    __PrivateTransient.add('cloneSource')
217
218    def _cloneSource (self):
219        """The source component from which this is a clone.
220
221        Returns C{None} if this is not a clone."""
222        return self.__cloneSource
223
224    # A set of references to all instances that are clones of this one.
225    __clones = None
226    __PrivateTransient.add('clones')
227
228    def _clones (self):
229        """The set of instances cloned from this component.
230
231        Returns None if no instances have been cloned from this."""
232        return self.__clones
233
234    def _resetClone_csc (self, **kw):
235        """Virtual method to clear whatever attributes should be reset in a
236        cloned component.
237
238        This instance should be an instance created by copy.copy().
239
240        The implementation in this class clears the owner and dependency
241        relations.
242
243        Returns C{self}.
244        """
245        assert self.__cloneSource is not None
246        owner = kw['owner']
247        self.__nameInBinding = None
248        self.__uniqueNameInBinding = None
249        self.__owner = owner
250        assert not (isinstance(self, ComplexTypeDefinition) and isinstance(owner, Schema))
251        self.__ownedComponents = set()
252        self.__clones = None
253        owner._namespaceContext().targetNamespace()._associateComponent(self)
254        if self.__namespaceContext is None:
255            # When cloning imported components, loan them the owner's
256            # namespace context, only so that their cloned children can be
257            # associated with the same namespace.
258            self.__namespaceContext = owner._namespaceContext()
259        self_fn = lambda *_args, **_kw: self
260        return getattr(super(_SchemaComponent_mixin, self), '_resetClone_csc', self_fn)(**kw)
261
262    def _clone (self, owner, origin):
263        """Create a copy of this instance suitable for adoption by some other
264        component.
265
266        This is used for creating a locally-scoped declaration from a
267        declaration in a named model or attribute group."""
268
269        # We only care about cloning declarations, and they should
270        # have an unassigned scope.  However, we do clone
271        # non-declarations that contain cloned declarations.
272        #assert (not isinstance(self, _ScopedDeclaration_mixin)) or self._scopeIsIndeterminate()
273        if isinstance(self, pyxb.namespace.resolution._Resolvable_mixin):
274            assert self.isResolved()
275
276        assert owner is not None
277        that = copy.copy(self)
278        that.__cloneSource = self
279        if self.__clones is None:
280            self.__clones = set()
281        self.__clones.add(that)
282        that._resetClone_csc(owner=owner, origin=origin)
283        if isinstance(that, pyxb.namespace.resolution._Resolvable_mixin):
284            assert that.isResolved()
285        return that
286
287    def isTypeDefinition (self):
288        """Return True iff this component is a simple or complex type
289        definition."""
290        return isinstance(self, (SimpleTypeDefinition, ComplexTypeDefinition))
291
292    def isUrTypeDefinition (self):
293        """Return True iff this component is a simple or complex type
294        definition."""
295        return isinstance(self, (_SimpleUrTypeDefinition, _UrTypeDefinition))
296
297    def bestNCName (self):
298        """Return the name of this component, as best it can be determined.
299
300        For example, ModelGroup instances will be named by their
301        ModelGroupDefinition, if available.  Returns None if no name can be
302        inferred."""
303        if isinstance(self, _NamedComponent_mixin):
304            return self.name()
305        if isinstance(self, ModelGroup):
306            agd = self.modelGroupDefinition()
307            if agd is not None:
308                return agd.name()
309        return None
310
311    def nameInBinding (self):
312        """Return the name by which this component is known in the binding module.
313
314        @note: To support builtin datatypes, type definitions with an
315        associated L{pythonSupport<SimpleTypeDefinition.pythonSupport>} class
316        initialize their binding name from the class name when the support
317        association is created.  As long as no built-in datatype conflicts
318        with a language keyword, this should be fine."""
319        return self.__nameInBinding
320
321    def uniqueNameInBinding (self):
322        """Return the name by which this component is known in the binding class."""
323        return self.__uniqueNameInBinding
324
325    def hasBinding (self):
326        """Return C{True} iff this is a component which has a user-visible
327        Python construct which serves as its binding.
328
329        Type definitions have classes as their bindings.  Global element
330        declarations have instances of L{pyxb.binding.basis.element} as their
331        bindings."""
332        return self.isTypeDefinition() or (isinstance(self, ElementDeclaration) and self._scopeIsGlobal())
333
334    def setNameInBinding (self, name_in_binding):
335        """Set the name by which this component shall be known in the binding module."""
336        self.__nameInBinding = name_in_binding
337        return self
338
339    def setUniqueNameInBinding (self, unique_name):
340        """Set the name by which this component shall be known in the binding class."""
341        self.__uniqueNameInBinding = unique_name
342        return self
343
344    def _updateFromOther_csc (self, other):
345        """Override fields in this instance with those from the other.
346
347        Post-extended; description in leaf implementation in
348        ComplexTypeDefinition and SimpleTypeDefinition."""
349        assert self != other
350        self_fn = lambda *_args, **_kw: self
351        getattr(super(_SchemaComponent_mixin, self), '_updateFromOther_csc', self_fn)(other)
352        # The only thing we update is the binding name, and that only if it's new.
353        if self.__nameInBinding is None:
354            self.__nameInBinding = other.__nameInBinding
355        return self
356
357    def schemaOrderSortKey (self):
358        """A key to be used when sorting components for binding generation.
359
360        This is a tuple comprising the namespace URI, schema location, and
361        line and column of the component definition within the schema.  The
362        purpose is to ensure consistent order of binding components in
363        generated code, to simplify maintenance involving the generated
364        sources.
365
366        To support Python 3 values that are C{None} are replaced with the
367        default value for whatever type belongs in the corresponding
368        position: (uri:str, locbase:str, locline:int, loccol:int) """
369        if self.__schemaOrderSortKey is None:
370            ns = None
371            if isinstance(self, _NamedComponent_mixin):
372                ns = self.bindingNamespace()
373                if ns is None:
374                    ns = self._namespaceContext().targetNamespace()
375            elif isinstance(self, _ParticleTree_mixin):
376                ns = self._namespaceContext().targetNamespace()
377            ns_uri = ''
378            if (ns is not None) and (ns.uri() is not None):
379                ns_uri = ns.uri()
380            key_elts = [ns_uri]
381            loc = self._location()
382            v = ''
383            if (loc is not None) and (loc.locationBase is not None):
384                v = loc.locationBase
385            key_elts.append(v)
386            v = 0
387            if (loc is not None) and (loc.lineNumber is not None):
388                v = loc.lineNumber
389            key_elts.append(v)
390            v = 0
391            if (loc is not None) and (loc.columnNumber is not None):
392                v = loc.columnNumber
393            key_elts.append(v)
394            self.__schemaOrderSortKey = tuple(key_elts)
395        return self.__schemaOrderSortKey
396    __schemaOrderSortKey = None
397
398    def facStateSortKey (self):
399        """A sort key matching preferred content order.
400
401        This is an ordinal (integer) used to control which candidate
402        transitions are attempted first when testing symbols against the
403        content automaton state.
404
405        @note: The value associated with a node (especially a L{ModelGroup} or
406        L{Particle} will be different for different complex types, and is
407        valid only during generation of the automata code for a given type."""
408        assert self.__facStateSortKey is not None
409        return self.__facStateSortKey
410
411    def _setFacStateSortKey (self, key):
412        """Set the automata state sort key.
413
414        @param key: the ordinal used for sorting."""
415        self.__facStateSortKey = key
416    __facStateSortKey = None
417    __PrivateTransient.add('facStateSortKey')
418
419class _ParticleTree_mixin (pyxb.cscRoot):
420    def _walkParticleTree (self, visit, arg):
421        """Mix-in supporting walks of L{Particle} trees.
422
423        This invokes a provided function on each node in a tree defining the
424        content model of a particle, both on the way down the tree and on the
425        way back up.  A standard implementation would be::
426
427          def _walkParticleTree (self, visit, arg):
428            visit(self, True, arg)
429            self.__term.walkParticleTree(visit, arg)
430            visit(self, False, arg)
431
432        @param visit: A callable with parameters C{node, entering, arg} where
433        C{node} is an instance of a class inheriting L{_ParticleTree_mixin},
434        C{entering} indicates tree transition status, and C{arg} is a
435        caller-provided state parameter.  C{entering} is C{True} if C{node}
436        has particle children and the call is before they are visited;
437        C{None} if the C{node} has no particle children; and C{False} if
438        C{node} has particle children and they have been visited.
439
440        @param arg: The caller-provided state parameter to be passed along
441        with the node and entry/exit status in the invocation of C{visit}.
442        """
443        raise NotImplementedError('%s._walkParticleTree' % (self.__class__.__name__,))
444
445class _Singleton_mixin (pyxb.cscRoot):
446    """This class is a mix-in which guarantees that only one instance
447    of the class will be created.  It is used to ensure that the
448    ur-type instances are pointer-equivalent even when unpickling.
449    See ComplexTypeDefinition.UrTypeDefinition()."""
450    def __new__ (cls, *args, **kw):
451        singleton_property = '_%s__singleton' % (cls.__name__,)
452        if not (singleton_property in cls.__dict__):
453            setattr(cls, singleton_property, super(_Singleton_mixin, cls).__new__(cls, *args, **kw))
454        return cls.__dict__[singleton_property]
455
456class _Annotated_mixin (pyxb.cscRoot):
457    """Mix-in that supports an optional single annotation that describes the component.
458
459    Most schema components have annotations.  The ones that don't are
460    L{AttributeUse}, L{Particle}, and L{Annotation}.  L{ComplexTypeDefinition}
461    and L{Schema} support multiple annotations, so do not mix-in this
462    class."""
463
464    # Optional Annotation instance
465    __annotation = None
466
467    def __init__ (self, *args, **kw):
468        super(_Annotated_mixin, self).__init__(*args, **kw)
469        self.__annotation = kw.get('annotation')
470
471    def _annotationFromDOM (self, node):
472        cn = domutils.LocateUniqueChild(node, 'annotation')
473        if cn is not None:
474            kw = { }
475            if isinstance(self, _SchemaComponent_mixin):
476                kw['owner'] = self
477            self.__annotation = Annotation.CreateFromDOM(cn, **kw)
478
479    def _updateFromOther_csc (self, other):
480        """Override fields in this instance with those from the other.
481
482        Post-extended; description in leaf implementation in
483        ComplexTypeDefinition and SimpleTypeDefinition."""
484        assert self != other
485        self_fn = lambda *_args, **_kw: self
486        getattr(super(_Annotated_mixin, self), '_updateFromOther_csc', self_fn)(other)
487        # @todo: make this a copy?
488        self.__annotation = other.__annotation
489        return self
490
491    def annotation (self):
492        return self.__annotation
493
494class _PickledAnonymousReference (object):
495    """A helper that encapsulates a reference to an anonymous type in a different namespace.
496
497    Normally references to components in other namespaces can be made using
498    the component's name.  This is not the case when a namespace derives from
499    a base type in another namespace and needs to reference the attribute or
500    element declarations held in that type.  If these declarations are local
501    to the base complex type, they cannot be identified by name.  This class
502    provides a pickleable representation for them that behaves rather like an
503    L{pyxb.namespace.ExpandedName} instance in that it can be used to
504    dereference various component types."""
505
506    __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory()
507
508    __namespace = None
509    __anonymousName = None
510    def __init__ (self, namespace, anonymous_name):
511        """Create a new anonymous reference.
512
513        @param namespace: The namespace in which the component is declared.
514        @type namespace: L{pyxb.namespace.Namespace}
515        @param anonymous_name: A generated name guaranteed to be unique within
516        the namespace.  See L{_NamedComponent_mixin._anonymousName}.
517        @type anonymous_name: C{basestring}.
518        """
519        self.__namespace = namespace
520        self.__anonymousName = anonymous_name
521        assert self.__anonymousName is not None
522
523    @classmethod
524    def FromPickled (cls, object_reference):
525        """Return the component referred to by the provided reference,
526        regardless of whether it is a normal or anonymous reference."""
527        if not isinstance(object_reference, _PickledAnonymousReference):
528            assert isinstance(object_reference, tuple)
529            object_reference = pyxb.namespace.ExpandedName(object_reference)
530        return object_reference
531
532    def namespace (self):
533        return self.__namespace
534
535    def anonymousName (self):
536        return self.__anonymousName
537
538    def validateComponentModel (self):
539        """Forward to the associated namespace."""
540        return self.__namespace.validateComponentModel()
541
542    def __lookupObject (self):
543        return self.__namespace.categoryMap(self.__AnonymousCategory).get(self.__anonymousName)
544
545    typeDefinition = __lookupObject
546    attributeGroupDefinition = __lookupObject
547    modelGroupDefinition = __lookupObject
548    attributeDeclaration = __lookupObject
549    elementDeclaration = __lookupObject
550    identityConstraintDefinition = __lookupObject
551    notationDeclaration = __lookupObject
552
553    def __str__ (self):
554        """Represent the anonymous reference in a form recognizable by a developer."""
555        return 'ANONYMOUS:%s' % (pyxb.namespace.ExpandedName(self.__namespace, self.__anonymousName),)
556
557class _NamedComponent_mixin (pyxb.utils.utility.PrivateTransient_mixin, pyxb.cscRoot):
558    """Mix-in to hold the name and targetNamespace of a component.
559
560    The name may be None, indicating an anonymous component.  The
561    targetNamespace is never None, though it could be an empty namespace.  The
562    name and targetNamespace values are immutable after creation.
563
564    This class overrides the pickling behavior: when pickling a Namespace,
565    objects that do not belong to that namespace are pickled as references,
566    not as values.  This ensures the uniqueness of objects when multiple
567    namespace definitions are pre-loaded.
568
569    This class must follow L{_SchemaComponent_mixin} in the MRO.
570    """
571
572    __PrivateTransient = set()
573
574    def name (self):
575        """Name of the component within its scope or namespace.
576
577        This is an NCName.  The value isNone if the component is
578        anonymous.  The attribute is immutable after the component is
579        created creation."""
580        return self.__name
581    __name = None
582
583    def isAnonymous (self):
584        """Return true iff this instance is locally scoped (has no name)."""
585        return self.__name is None
586
587    def _setAnonymousName (self, namespace, unique_id=None, anon_name=None):
588        # If this already has a name, keep using it.
589        if self.__anonymousName is not None:
590            return
591        assert self.__needAnonymousSupport()
592        assert namespace is not None
593        if self.bindingNamespace() is not None:
594            assert self.bindingNamespace() == namespace
595        if self.targetNamespace() is not None:
596            assert self.targetNamespace() == namespace
597        if anon_name is None:
598            anon_name = self.nameInBinding()
599            if anon_name is None:
600                anon_name = self.name()
601            if anon_name is None:
602                anon_name = 'ANON_IN_GROUP'
603            if unique_id is not None:
604                anon_name = '%s_%s' % (anon_name, unique_id)
605            anon_name = pyxb.utils.utility.MakeUnique(anon_name, set(six.iterkeys(namespace.categoryMap(self.__AnonymousCategory))))
606        self.__anonymousName = anon_name
607        namespace.addCategoryObject(self.__AnonymousCategory, anon_name, self)
608    def _anonymousName (self, namespace=None):
609        assert self.__anonymousName is not None, '%x %s %s in %s missing anonymous name' % (id(self), type(self), self.name(), self.targetNamespace())
610        return self.__anonymousName
611    __anonymousName = None
612
613    def targetNamespace (self):
614        """The targetNamespace of a component.
615
616        This is None, or a reference to a Namespace in which the
617        component is declared (either as a global or local to one of
618        the namespace's complex type definitions).  This is immutable
619        after creation.
620        """
621        return self.__targetNamespace
622    __targetNamespace = None
623
624    def bindingNamespace (self):
625        """The namespace in which this component's binding is placed."""
626        return self.__bindingNamespace
627    def _setBindingNamespace (self, namespace):
628        self.__bindingNamespace = namespace
629    __bindingNamespace = None
630
631    def _templateMap (self):
632        """A map from template keys to component-specific values.
633
634        This is used in code generation to maintain unique names for accessor
635        methods, identifiers, keys, and other characteristics associated with
636        the code generated in support of the binding for this component."""
637        return self.__templateMap
638    __templateMap = None
639
640    __AnonymousCategory = pyxb.namespace.archive.NamespaceArchive._AnonymousCategory()
641
642    def __needAnonymousSupport (self):
643        # If this component doesn't have a name, or if it's in some scope in
644        # which it cannot be located in a category map, we'll need a unique
645        # name for it.
646        return self.isAnonymous() or (self._scopeIsIndeterminate() and not isinstance(self, (AttributeGroupDefinition, ModelGroupDefinition)))
647
648    def _schema (self):
649        """Return the schema component from which this component was defined.
650
651        Needed so we can distinguish components that came from different
652        locations, since that imposes an external order dependency on them and
653        on cross-namespace inclusions.
654
655        @note: This characteristic is removed when the component is stored in
656        a namespace archive."""
657        return self.__schema
658    __schema = None
659    __PrivateTransient.add('schema')
660
661    def _prepareForArchive_csc (self, module_record):
662        if self.__needAnonymousSupport():
663            self._setAnonymousName(module_record.namespace(), unique_id=module_record.generationUID())
664        self_fn = lambda *_args, **_kw: self
665        return getattr(super(_NamedComponent_mixin, self), '_prepareForArchive_csc', self_fn)(module_record)
666
667    def _picklesInArchive (self, archive):
668        """Return C{True} if this component should be pickled by value in the
669        given namespace.
670
671        When pickling, a declaration component is considered to belong to the
672        namespace if it has a local scope which belongs to the namespace.  In
673        that case, the declaration is a clone of something that does not
674        belong to the namespace; but the clone does.
675
676        @see: L{_bindsInNamespace}
677
678        @return: C{False} if the component should be pickled by reference.
679        """
680        if isinstance(self._scope(), ComplexTypeDefinition):
681            return self._scope()._picklesInArchive(archive)
682        assert not (self.targetNamespace() is None), '%s has no tns, scope %s, location %s, schema %s' % (self, self._scope(), self._location(), self._schema().targetNamespace())
683        assert not (self._objectOrigin() is None)
684        new_flag = (self._objectOrigin().generationUID() == archive.generationUID())
685        return new_flag
686
687    def _bindsInNamespace (self, ns):
688        """Return C{True} if the binding for this component should be
689        generated in the given namespace.
690
691        This is the case when the component is in the given namespace.  It's
692        also the case when the component has no associated namespace (but not
693        an absent namespace).  Be aware that cross-namespace inheritance means
694        you will get references to elements in another namespace when
695        generating code for a subclass; that's fine, and those references
696        should not be generated locally.
697        """
698        return self.targetNamespace() in (ns, None)
699
700    def expandedName (self):
701        """Return the L{pyxb.namespace.ExpandedName} of this object."""
702        if self.name() is None:
703            return None
704        return pyxb.namespace.ExpandedName(self.targetNamespace(), self.name())
705
706    def __new__ (cls, *args, **kw):
707        """Pickling support.
708
709        Normally, we just create a new instance of this class.
710        However, if we're unpickling a reference in a loadable schema,
711        we need to return the existing component instance by looking
712        up the name in the component map of the desired namespace.  We
713        can tell the difference because no normal constructors that
714        inherit from this have positional arguments; only invocations
715        by unpickling with a value returned in __getnewargs__ do.
716
717        This does require that the dependent namespace already have
718        been validated (or that it be validated here).  That shouldn't
719        be a problem, except for the dependency loop resulting from
720        use of xml:lang in the XMLSchema namespace.  For that issue,
721        see pyxb.namespace._XMLSchema.
722        """
723
724        if 0 == len(args):
725            rv = super(_NamedComponent_mixin, cls).__new__(cls)
726            return rv
727        ( object_reference, scope, icls ) = args
728
729        object_reference = _PickledAnonymousReference.FromPickled(object_reference)
730
731        # Explicitly validate here: the lookup operations won't do so,
732        # but will abort if the namespace hasn't been validated yet.
733        object_reference.validateComponentModel()
734        rv = None
735        if isinstance(scope, (tuple, _PickledAnonymousReference)):
736            # Scope is the expanded name of the complex type in which the
737            # named value can be located.
738            scope_ref = _PickledAnonymousReference.FromPickled(scope)
739            if object_reference.namespace() != scope_ref.namespace():
740                scope_ref.validateComponentModel()
741                assert 'typeDefinition' in scope_ref.namespace().categories()
742            scope_ctd = scope_ref.typeDefinition()
743            if scope_ctd is None:
744                raise pyxb.SchemaValidationError('Unable to resolve local scope %s' % (scope_ref,))
745            if issubclass(icls, AttributeDeclaration):
746                rv = scope_ctd.lookupScopedAttributeDeclaration(object_reference)
747            elif issubclass(icls, ElementDeclaration):
748                rv = scope_ctd.lookupScopedElementDeclaration(object_reference)
749            if rv is None:
750                raise pyxb.SchemaValidationError('Unable to resolve %s as %s in scope %s' % (object_reference, icls, scope_ref))
751        elif _ScopedDeclaration_mixin.ScopeIsGlobal(scope) or _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope):
752            if (issubclass(icls, SimpleTypeDefinition) or issubclass(icls, ComplexTypeDefinition)):
753                rv = object_reference.typeDefinition()
754            elif issubclass(icls, AttributeGroupDefinition):
755                rv = object_reference.attributeGroupDefinition()
756            elif issubclass(icls, ModelGroupDefinition):
757                rv = object_reference.modelGroupDefinition()
758            elif issubclass(icls, AttributeDeclaration):
759                rv = object_reference.attributeDeclaration()
760            elif issubclass(icls, ElementDeclaration):
761                rv = object_reference.elementDeclaration()
762            elif issubclass(icls, IdentityConstraintDefinition):
763                rv = object_reference.identityConstraintDefinition()
764            if rv is None:
765                raise pyxb.SchemaValidationError('Unable to resolve %s as %s' % (object_reference, icls))
766        if rv is None:
767            raise pyxb.SchemaValidationError('Unable to resolve reference %s, scope %s ns %s type %s, class %s' % (object_reference, scope, (scope is None and "<unknown>" or scope.targetNamespace()), type(scope), icls))
768        return rv
769
770    def __init__ (self, *args, **kw):
771        assert 0 == len(args)
772        name = kw.get('name')
773        # Must be None or a valid NCName
774        assert (name is None) or (0 > name.find(':')), 'name %s' % (name,)
775        self.__name = name
776
777        # Target namespace is taken from the context, unless somebody
778        # overrides it (as is done for local declarations if the form is
779        # unqualified).
780        self.__targetNamespace = kw.get('target_namespace', self._namespaceContext().targetNamespace())
781        self.__bindingNamespace = kw.get('binding_namespace')
782
783        self.__templateMap = {}
784
785        self.__schema = kw.get('schema')
786        assert self._schema() is not None
787
788        # Do parent invocations after we've set the name: they might need it.
789        super(_NamedComponent_mixin, self).__init__(*args, **kw)
790
791    def isNameEquivalent (self, other):
792        """Return true iff this and the other component share the same name and target namespace.
793
794        Anonymous components are inherently name inequivalent, except to
795        themselves.  This relies on equivalence as defined for
796        pyxb.namespace.ExpandedName, for which None is not equivalent to any
797        non-anonymous name."""
798        # Note that unpickled objects
799        return (self == other) or ((not self.isAnonymous()) and (self.expandedName() == other.expandedName()))
800
801    def isTypeEquivalent (self, other):
802        """Return True iff this and the other component have matching types.
803
804        It appears that name equivalence is used; two complex type definitions
805        with identical structures are not considered equivalent (at least, per
806        XMLSpy).
807        """
808        return (type(self) == type(other)) and self.isNameEquivalent(other)
809
810    def isDerivationConsistent (self, other):
811        """Return True iff this type can serve as a restriction of the other
812        type for the purposes of U{element consistency<http://www.w3.org/TR/xmlschema-1/#cos-element-consistent>}.
813
814        It appears that name equivalence is normally used; two complex type
815        definitions with identical structures are not considered equivalent
816        (at least, per XMLSpy).  However, some OpenGIS standards demonstrate
817        that derivation by restriction from the other type is also acceptable.
818        That opens a whole can of worms; see
819        L{ElementDeclaration.isAdaptable}.
820        """
821        this = self
822        # can this succeed if component types are not equivalent?
823        while this is not None:
824            if this.isTypeEquivalent(other):
825                return True
826            # Assumption from ElementDeclaration.isAdaptable
827            assert this.isResolved() and other.isResolved()
828            if isinstance(self, ComplexTypeDefinition):
829                if self.DM_restriction != this.derivationMethod():
830                    return False
831            else:
832                assert isinstance(self, SimpleTypeDefinition)
833                if self._DA_restriction != this._derivationAlternative():
834                    return False
835                if not this.baseTypeDefinition().isDerivationConsistent(other):
836                    return False
837            this = this.baseTypeDefinition()
838        return False
839
840    def _picklingReference (self):
841        if self.__needAnonymousSupport():
842            assert self._anonymousName() is not None
843            return _PickledAnonymousReference(self.targetNamespace(), self._anonymousName())
844        return self.expandedName().uriTuple()
845
846    def __pickleAsReference (self):
847        if self.targetNamespace() is None:
848            return False
849        # Get the namespace we're pickling.  If the namespace is None,
850        # we're not pickling; we're probably cloning, and in that case
851        # we don't want to use the reference state encoding.
852        pickling_archive = pyxb.namespace.archive.NamespaceArchive.PicklingArchive()
853        if pickling_archive is None:
854            return False
855        # If this thing is scoped in a complex type that belongs to the
856        # namespace being pickled, then it gets pickled as an object even if
857        # its target namespace isn't this one.
858        assert self._objectOrigin() is not None
859        if self._picklesInArchive(pickling_archive):
860            return False
861        # Note that anonymous objects must use their fallback
862        return True
863
864    def __getstate__ (self):
865        if self.__pickleAsReference():
866            # NB: This instance may be a scoped declaration, but in
867            # this case (unlike getnewargs) we don't care about trying
868            # to look up a previous instance, so we don't need to
869            # encode the scope in the reference tuple.
870            return self._picklingReference()
871        if self.targetNamespace() is None:
872            # The only internal named objects that should exist are
873            # ones that have a non-global scope (including those with
874            # absent scope).
875            # @todo: this is wrong for schema that are not bound to a
876            # namespace, unless we use an unbound Namespace instance
877            #assert isinstance(self, _ScopedDeclaration_mixin)
878            #assert self.SCOPE_global != self.scope()
879            # NOTE: The name of the scope may be None.  This is not a
880            # problem unless somebody tries to extend or restrict the
881            # scope type, which at the moment I'm thinking is
882            # impossible for anonymous types.  If it isn't, we're
883            # gonna need some other sort of ID, like a UUID associated
884            # with the anonymous class at the time it's written to the
885            # preprocessed schema file.
886            pass
887        return super(_NamedComponent_mixin, self).__getstate__()
888
889    def __getnewargs__ (self):
890        """Pickling support.
891
892        If this instance is being pickled as a reference, provide the
893        arguments that are necessary so that the unpickler can locate
894        the appropriate component rather than create a duplicate
895        instance."""
896
897        if self.__pickleAsReference():
898            scope = self._scope()
899            if isinstance(self, _ScopedDeclaration_mixin):
900                # If scope is global, we can look it up in the namespace.
901                # If scope is indeterminate, this must be within a group in
902                # another namespace.  Why are we serializing it?
903                # If scope is local, provide the namespace and name of
904                # the type that holds it
905                if self.SCOPE_global == self.scope():
906                    pass
907                elif isinstance(self.scope(), ComplexTypeDefinition):
908                    scope = self.scope()._picklingReference()
909                    assert isinstance(scope, (tuple, _PickledAnonymousReference)), self
910                else:
911                    assert self._scopeIsIndeterminate()
912                    # This is actually OK: we made sure both the scope and
913                    # this instance can be looked up by a unique identifier.
914            else:
915                assert isinstance(self, _NamedComponent_mixin), 'Pickling unnamed component %s in indeterminate scope by reference' % (self,)
916                assert not isinstance(scope, ComplexTypeDefinition), '%s %s %s %s' % (self, self.name(), scope, self._objectOrigin())
917
918            rv = ( self._picklingReference(), scope, self.__class__ )
919            return rv
920        return ()
921
922    def __setstate__ (self, state):
923        if isinstance(state, tuple):
924            # We don't actually have to set any state here; we just
925            # make sure that we resolved to an already-configured
926            # instance.
927            assert self.targetNamespace() is not None
928            assert self.targetNamespace().uri() == state[0]
929            assert self.name() == state[1]
930            return
931        if isinstance(state, _PickledAnonymousReference):
932            assert self.targetNamespace() is not None
933            assert self.targetNamespace() == state.namespace()
934            assert self.__needAnonymousSupport()
935            assert self._anonymousName() == state.anonymousName()
936            return
937        self.__dict__.update(state)
938
939    def _resetClone_csc (self, **kw):
940        self.__schema = None
941        self_fn = lambda *_args, **_kw: self
942        rv = getattr(super(_NamedComponent_mixin, self), '_resetClone_csc', self_fn)(**kw)
943        self.__templateMap = { }
944        origin = kw.get('origin')
945        self.__anonymousName = None
946        self._setObjectOrigin(origin, override=True)
947        return rv
948
949class _ValueConstraint_mixin (pyxb.cscRoot):
950    """Mix-in indicating that the component contains a simple-type
951    value that may be constrained."""
952
953    VC_na = 0                   #<<< No value constraint applies
954    VC_default = 1              #<<< Provided value constraint is default value
955    VC_fixed = 2                #<<< Provided value constraint is fixed value
956
957    # None, or a tuple containing a string followed by one of the VC_*
958    # values above.
959    __valueConstraint = None
960    def valueConstraint (self):
961        """A constraint on the value of the attribute or element.
962
963        Either None, or a pair consisting of a string in the lexical
964        space of the typeDefinition and one of VC_default and
965        VC_fixed."""
966        return self.__valueConstraint
967
968    def default (self):
969        """If this instance constraints a default value, return that
970        value; otherwise return None."""
971        if not isinstance(self.__valueConstraint, tuple):
972            return None
973        if self.VC_default != self.__valueConstraint[1]:
974            return None
975        return self.__valueConstraint[0]
976
977    def fixed (self):
978        """If this instance constraints a fixed value, return that
979        value; otherwise return None."""
980        if not isinstance(self.__valueConstraint, tuple):
981            return None
982        if self.VC_fixed != self.__valueConstraint[1]:
983            return None
984        return self.__valueConstraint[0]
985
986    def _valueConstraintFromDOM (self, node):
987        adefault = domutils.NodeAttribute(node, 'default')
988        afixed = domutils.NodeAttribute(node, 'fixed')
989        ause = domutils.NodeAttribute(node, 'use')
990        if (adefault is not None) and (afixed is not None):
991            raise pyxb.SchemaValidationError('Attributes default and fixed may not both appear (3.2.3r1)')
992        if adefault is not None:
993            if (ause is not None) and ('optional' != ause):
994                raise pyxb.SchemaValidationError('Attribute use must be optional when default present (3.2.3r2)')
995            self.__valueConstraint = (adefault, self.VC_default)
996            return self
997        if afixed is not None:
998            self.__valueConstraint = (afixed, self.VC_fixed)
999            return self
1000        self.__valueConstraint = None
1001        return self
1002
1003class _ScopedDeclaration_mixin (pyxb.cscRoot):
1004    """Mix-in class for named components that have a scope.
1005
1006    Scope is important when doing cross-namespace inheritance,
1007    e.g. extending or restricting a complex type definition that is
1008    from a different namespace.  In this case, we will need to retain
1009    a reference to the external component when the schema is
1010    serialized.
1011
1012    This is done in the pickling process by including the scope when
1013    pickling a component as a reference.  The scope is the
1014    SCOPE_global if global; otherwise, it is a tuple containing the
1015    external namespace URI and the NCName of the complex type
1016    definition in that namespace.  We assume that the complex type
1017    definition has global scope; otherwise, it should not have been
1018    possible to extend or restrict it.  (Should this be untrue, there
1019    are comments in the code about a possible solution.)
1020
1021    @warning: This mix-in must follow L{_NamedComponent_mixin} in the C{mro}.
1022    """
1023
1024    SCOPE_global = 'global'     #<<< Marker to indicate global scope
1025    XSCOPE_indeterminate = 'indeterminate' #<<< Marker to indicate scope has not been assigned
1026
1027    @classmethod
1028    def IsValidScope (cls, value):
1029        return (cls.SCOPE_global == value) or isinstance(value, ComplexTypeDefinition)
1030
1031    @classmethod
1032    def ScopeIsIndeterminate (cls, value):
1033        return (cls.XSCOPE_indeterminate == value)
1034
1035    @classmethod
1036    def ScopeIsGlobal (cls, value):
1037        return (cls.SCOPE_global == value)
1038
1039    def _scopeIsCompatible (self, scope):
1040        """Return True if this scope currently assigned to this instance is compatible with the given scope.
1041
1042        If either scope is indeterminate, presume they will ultimately be
1043        compatible.  Scopes that are equal are compatible, as is a local scope
1044        if this already has a global scope."""
1045        if self.ScopeIsIndeterminate(scope) or self.ScopeIsIndeterminate(self.scope()):
1046            return True
1047        if self.scope() == scope:
1048            return True
1049        return (self.SCOPE_global == self.scope()) and isinstance(scope, ComplexTypeDefinition)
1050
1051    # The scope for the element.  Valid values are SCOPE_global or a
1052    # complex type definition.  None is an invalid value, but may
1053    # appear if scope is determined by an ancestor component.
1054    def scope (self):
1055        """The scope for the declaration.
1056
1057        Valid values are SCOPE_global, or a complex type definition.
1058        A value of None means a non-global declaration that is not
1059        owned by a complex type definition.  These can only appear in
1060        attribute group definitions, model group definitions, and element
1061        declarations.
1062
1063        @todo: For declarations in named model groups (viz., local
1064        elements that aren't references), the scope needs to be set by
1065        the owning complex type.
1066        """
1067        return self._scope()
1068
1069    # The base declaration is the original _ScopedDeclaration_mixin which
1070    # introduced the element into its scope.  This is used to retain a
1071    # particular defining declaration when each extension type gets its own
1072    # clone adapted for its scope.
1073    __baseDeclaration = None
1074    def baseDeclaration (self):
1075        return self.__baseDeclaration or self
1076    def _baseDeclaration (self, referenced_declaration):
1077        self.__baseDeclaration = referenced_declaration.baseDeclaration()
1078        return self.__baseDeclaration
1079
1080    # Indicates that declaration replaces a (compatible) declaration with the
1081    # same name within its scope.  Also provide access to the declaration it
1082    # replaces.
1083    __overridesParentScope = False
1084    def overridesParentScope (self):
1085        return self.__overridesParentScope
1086    def _overrideParentScope (self, value):
1087        self.__overriddenDeclaration = value;
1088        self.__overridesParentScope = True
1089    def overriddenDeclaration (self):
1090        return self.__overriddenDeclaration
1091
1092class _AttributeWildcard_mixin (pyxb.cscRoot):
1093    """Support for components that accept attribute wildcards.
1094
1095    That is L{AttributeGroupDefinition} and L{ComplexTypeDefinition}.  The
1096    calculations of the appropriate wildcard are sufficiently complex that
1097    they need to be abstracted out to a mix-in class."""
1098
1099    # Optional wildcard that constrains attributes
1100    __attributeWildcard = None
1101
1102    def attributeWildcard (self):
1103        """Return the L{Wildcard} component associated with attributes of this
1104        instance, or C{None} if attribute wildcards are not present in the
1105        instance."""
1106        return self.__attributeWildcard
1107
1108    def _setAttributeWildcard (self, attribute_wildcard):
1109        """Set the attribute wildcard property for this instance."""
1110        assert (attribute_wildcard is None) or isinstance(attribute_wildcard, Wildcard)
1111        self.__attributeWildcard = attribute_wildcard
1112        return self
1113
1114    def _attributeRelevantChildren (self, node_list):
1115        """Return the nodes that are relevant for attribute processing.
1116
1117        @param node_list: A sequence of nodes found in a definition content
1118        information item.
1119
1120        @return: A tuple C{( attributes, attributeGroups, attributeWildcard)}
1121        where C{attributes} is the subsequence of C{node_list} that are
1122        XMLSchema C{attribute} nodes; C{attributeGroups} is analogous; and
1123        C{attributeWildcard} is a single DOM node with XMLSchema name
1124        C{anyAttribute} (or C{None}, if no such node is present in the list).
1125
1126        @raise pyxb.SchemaValidationError: An C{attributeGroup} node is
1127        present but does not have the required C{ref} attribute.
1128        @raise pyxb.SchemaValidationError: Multiple C{anyAttribute} nodes are
1129        identified.
1130        """
1131
1132        attributes = []
1133        attribute_groups = []
1134        any_attribute = None
1135        # Handle clauses 1 and 2 (common between simple and complex types)
1136        for node in node_list:
1137            if Node.ELEMENT_NODE != node.nodeType:
1138                continue
1139            if xsd.nodeIsNamed(node, 'attribute'):
1140                # Note: This attribute use instance may have use=prohibited
1141                attributes.append(node)
1142            elif xsd.nodeIsNamed(node, 'attributeGroup'):
1143                # This must be an attributeGroupRef
1144                agd_en = domutils.NodeAttributeQName(node, 'ref')
1145                if agd_en is None:
1146                    raise pyxb.SchemaValidationError('Require ref attribute on internal attributeGroup elements')
1147                attribute_groups.append(agd_en)
1148            elif xsd.nodeIsNamed(node, 'anyAttribute'):
1149                if any_attribute is not None:
1150                    raise pyxb.SchemaValidationError('Multiple anyAttribute children are not allowed')
1151                any_attribute = node
1152
1153        return (attributes, attribute_groups, any_attribute)
1154
1155    @classmethod
1156    def CompleteWildcard (cls, namespace_context, attribute_groups, local_wildcard):
1157        """Implement the algorithm as described the
1158        U{specification<http://www.w3.org/TR/xmlschema-1/#declare-type>}.
1159
1160        @param namespace_context: The L{pyxb.namespace.NamespaceContext} to be
1161        associated with any created L{Wildcard} instance
1162        @param attribute_groups: A list of L{AttributeGroupDefinition} instances
1163        @param local_wildcard: A L{Wildcard} instance computed from a relevant
1164        XMLSchema C{anyAttribute} element, or C{None} if no attribute wildcard
1165        is relevant
1166        """
1167
1168        # Non-absent wildcard properties of attribute groups
1169        agd_wildcards = []
1170        for agd in attribute_groups:
1171            assert isinstance(agd, AttributeGroupDefinition)
1172            if agd.attributeWildcard() is not None:
1173                agd_wildcards.append(agd.attributeWildcard())
1174        agd_constraints = [ _agd.namespaceConstraint() for _agd in agd_wildcards ]
1175
1176        # Clause 2.1
1177        if 0 == len(agd_wildcards):
1178            return local_wildcard
1179
1180        if local_wildcard is not None:
1181            # Clause 2.2.1
1182            return Wildcard(process_contents=local_wildcard.processContents(),
1183                            namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints + [local_wildcard.namespaecConstraint()]),
1184                            annotation=local_wildcard.annotation(),
1185                            namespace_context=namespace_context)
1186        # Clause 2.2.2
1187        return Wildcard(process_contents=agd_wildcards[0].processContents(),
1188                        namespace_constraint=Wildcard.IntensionalIntersection(agd_constraints),
1189                        namespace_context=namespace_context)
1190
1191class AttributeDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1192    """An XMLSchema U{Attribute Declaration<http://www.w3.org/TR/xmlschema-1/#cAttribute_Declarations>} component.
1193    """
1194
1195    # The STD to which attribute values must conform
1196    __typeDefinition = None
1197    def typeDefinition (self):
1198        """The simple type definition to which an attribute value must
1199         conform."""
1200        return self.__typeDefinition
1201
1202    # The expanded name content of the XSD type attribute
1203    __typeExpandedName = None
1204
1205    def __init__ (self, *args, **kw):
1206        super(AttributeDeclaration, self).__init__(*args, **kw)
1207        assert 'scope' in kw
1208
1209    def __str__ (self):
1210        if self.typeDefinition():
1211            return 'AD[%s:%s]' % (self.name(), self.typeDefinition().expandedName())
1212        return 'AD[%s:?]' % (self.expandedName(),)
1213
1214    @classmethod
1215    def CreateBaseInstance (cls, name, schema, std=None):
1216        """Create an attribute declaration component for a specified namespace."""
1217        kw = { 'name' : name,
1218               'schema' : schema,
1219               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
1220               'scope' : _ScopedDeclaration_mixin.SCOPE_global }
1221        assert schema is not None
1222        bi = cls(**kw)
1223        if std is not None:
1224            bi.__typeDefinition = std
1225        bi.__typeExpandedName = None
1226        return bi
1227
1228    # CFD:AD CFD:AttributeDeclaration
1229    @classmethod
1230    def CreateFromDOM (cls, node, **kw):
1231        """Create an attribute declaration from the given DOM node.
1232
1233        wxs is a Schema instance within which the attribute is being
1234        declared.
1235
1236        node is a DOM element.  The name must be one of ( 'all',
1237        'choice', 'sequence' ), and the node must be in the XMLSchema
1238        namespace.
1239
1240        scope is the _ScopeDeclaration_mxin context into which the
1241        attribute declaration is placed.  It can be SCOPE_global, a
1242        complex type definition, or XSCOPE_indeterminate if this is an
1243        anonymous declaration within an attribute group.  It is a
1244        required parameter for this function.
1245        """
1246
1247        scope = kw['scope']
1248        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
1249
1250        # Node should be an XMLSchema attribute node
1251        assert xsd.nodeIsNamed(node, 'attribute')
1252
1253        name = domutils.NodeAttribute(node, 'name')
1254
1255        # Implement per section 3.2.2
1256        if xsd.nodeIsNamed(node.parentNode, 'schema'):
1257            assert cls.SCOPE_global == scope
1258        elif domutils.NodeAttribute(node, 'ref') is None:
1259            # This is an anonymous declaration within an attribute use
1260            assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1261        else:
1262            raise pyxb.SchemaValidationError('Internal attribute declaration by reference')
1263
1264        rv = cls(name=name, node=node, **kw)
1265        rv._annotationFromDOM(node)
1266        rv._valueConstraintFromDOM(node)
1267
1268        rv.__typeExpandedName = domutils.NodeAttributeQName(node, 'type')
1269
1270        kw.pop('node', None)
1271        kw['owner'] = rv
1272
1273        st_node = domutils.LocateUniqueChild(node, 'simpleType')
1274        if st_node is not None:
1275            rv.__typeDefinition = SimpleTypeDefinition.CreateFromDOM(st_node, **kw)
1276        elif rv.__typeExpandedName is None:
1277            rv.__typeDefinition = SimpleTypeDefinition.SimpleUrTypeDefinition()
1278
1279        if rv.__typeDefinition is None:
1280            rv._queueForResolution('creation')
1281        return rv
1282
1283    def isResolved (self):
1284        return self.__typeDefinition is not None
1285
1286    # res:AD res:AttributeDeclaration
1287    def _resolve (self):
1288        if self.isResolved():
1289            return self
1290
1291        # Although the type definition may not be resolved, *this* component
1292        # is resolved, since we don't look into the type definition for anything.
1293        assert self.__typeExpandedName is not None, 'AD %s is unresolved but had no type attribute field' % (self.expandedName(),)
1294        self.__typeDefinition = self.__typeExpandedName.typeDefinition()
1295        if self.__typeDefinition is None:
1296            raise pyxb.SchemaValidationError('Type reference %s cannot be found' % (self.__typeExpandedName,))
1297        if not isinstance(self.__typeDefinition, SimpleTypeDefinition):
1298            raise pyxb.SchemaValidationError('Need %s to be a simple type' % (self.__typeExpandedName,))
1299
1300        return self
1301
1302    def _updateFromOther_csc (self, other):
1303        """Override fields in this instance with those from the other.
1304
1305        This method is invoked only by Schema._addNamedComponent, and
1306        then only when a built-in type collides with a schema-defined
1307        type.  Material like facets is not (currently) held in the
1308        built-in copy, so the DOM information is copied over to the
1309        built-in STD, which is subsequently re-resolved.
1310
1311        Returns self.
1312        """
1313        assert self != other
1314        assert self.name() is not None
1315        assert self.isNameEquivalent(other)
1316        super(AttributeDeclaration, self)._updateFromOther_csc(other)
1317
1318        # The other STD should be an unresolved schema-defined type.
1319        # Mark this instance as unresolved so it is re-examined
1320        if not other.isResolved():
1321            if pyxb.namespace.BuiltInObjectUID == self._objectOrigin().generationUID():
1322                #assert self.isResolved(), 'Built-in %s is not resolved' % (self.expandedName(),)
1323                _log.warning('Not destroying builtin %s: %s', self.expandedName(), self.__typeDefinition)
1324            else:
1325                self.__typeDefinition = None
1326        return self
1327
1328    # bR:AD
1329    def _bindingRequires_vx (self, include_lax):
1330        """Attribute declarations require their type."""
1331        return frozenset([ self.__typeDefinition ])
1332
1333class AttributeUse (_SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _ValueConstraint_mixin):
1334    """An XMLSchema U{Attribute Use<http://www.w3.org/TR/xmlschema-1/#cAttribute_Use>} component."""
1335
1336    # How this attribute can be used.  The component property
1337    # "required" is true iff the value is USE_required.
1338    __use = None
1339
1340    USE_required = 0x01         #<<< The attribute is required
1341    USE_optional = 0x02         #<<< The attribute may or may not appear
1342    USE_prohibited = 0x04       #<<< The attribute must not appear
1343
1344    def required (self):
1345        return self.USE_required == self.__use
1346
1347    def prohibited (self):
1348        return self.USE_prohibited == self.__use
1349
1350    # The expanded name value of the XSD ref attribute
1351    __refExpandedName = None
1352
1353    __restrictionOf = None
1354    def restrictionOf (self):
1355        return self.__restrictionOf
1356    def _setRestrictionOf (self, au):
1357        assert isinstance(au, AttributeUse)
1358        # Might re-assign if had to suspend resolution
1359        assert (self.__restrictionOf is None) or (self.__restrictionOf == au)
1360        self.__restrictionOf = au
1361
1362    # A reference to an AttributeDeclaration
1363    def attributeDeclaration (self):
1364        """The attribute declaration for this use.
1365
1366        When the use scope is assigned, the declaration is cloned (if
1367        necessary) so that each declaration corresponds to only one use.  We
1368        rely on this in code generation, because the template map for the use
1369        is stored in its declaration."""
1370        return self.__attributeDeclaration
1371    __attributeDeclaration = None
1372
1373    # Define so superclasses can take keywords
1374    def __init__ (self, **kw):
1375        super(AttributeUse, self).__init__(**kw)
1376
1377    def matchingQNameMembers (self, au_set):
1378        """Return the subset of au_set for which the use names match this use."""
1379
1380        if not self.isResolved():
1381            return None
1382        this_ad = self.attributeDeclaration()
1383        rv = set()
1384        for au in au_set:
1385            if not au.isResolved():
1386                return None
1387            that_ad = au.attributeDeclaration()
1388            if this_ad.isNameEquivalent(that_ad):
1389                rv.add(au)
1390        return rv
1391
1392    @classmethod
1393    def CreateBaseInstance (cls, schema, attribute_declaration, use=USE_optional):
1394        kw = { 'schema' : schema,
1395               'namespace_context' : schema.targetNamespace().initialNamespaceContext() }
1396        bi = cls(**kw)
1397        assert isinstance(attribute_declaration, AttributeDeclaration)
1398        bi.__attributeDeclaration = attribute_declaration
1399        bi.__use = use
1400        return bi
1401
1402    # CFD:AU CFD:AttributeUse
1403    @classmethod
1404    def CreateFromDOM (cls, node, **kw):
1405        """Create an Attribute Use from the given DOM node.
1406
1407        wxs is a Schema instance within which the attribute use is
1408        being defined.
1409
1410        node is a DOM element.  The name must be 'attribute', and the
1411        node must be in the XMLSchema namespace.
1412
1413        scope is the _ScopeDeclaration_mixin context into which any
1414        required anonymous attribute declaration is put.  This must be
1415        a complex type definition, or None if this use is in an
1416        attribute group.
1417        """
1418
1419        scope = kw['scope']
1420        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1421        assert xsd.nodeIsNamed(node, 'attribute')
1422        schema = kw['schema']
1423        rv = cls(node=node, **kw)
1424
1425        rv.__use = cls.USE_optional
1426        use = domutils.NodeAttribute(node, 'use')
1427        if use is not None:
1428            if 'required' == use:
1429                rv.__use = cls.USE_required
1430            elif 'optional' == use:
1431                rv.__use = cls.USE_optional
1432            elif 'prohibited' == use:
1433                rv.__use = cls.USE_prohibited
1434            else:
1435                raise pyxb.SchemaValidationError('Unexpected value %s for attribute use attribute' % (use,))
1436
1437        rv._valueConstraintFromDOM(node)
1438
1439        rv.__refExpandedName = domutils.NodeAttributeQName(node, 'ref')
1440        if rv.__refExpandedName is None:
1441            # Create an anonymous declaration
1442            kw.pop('node', None)
1443            kw['owner'] = rv
1444            kw['target_namespace'] = schema.targetNamespaceForNode(node, AttributeDeclaration)
1445            rv.__attributeDeclaration = AttributeDeclaration.CreateFromDOM(node, **kw)
1446
1447        if not rv.isResolved():
1448            rv._queueForResolution('creation')
1449
1450        return rv
1451
1452    def isResolved (self):
1453        return self.__attributeDeclaration is not None
1454
1455    # res:AU res:AttributeUse
1456    def _resolve (self):
1457        if self.isResolved():
1458            return self
1459        self.__attributeDeclaration = self.__refExpandedName.attributeDeclaration()
1460        if self.__attributeDeclaration is None:
1461            raise pyxb.SchemaValidationError('Attribute declaration %s cannot be found' % (self.__refExpandedName,))
1462
1463        assert isinstance(self.__attributeDeclaration, AttributeDeclaration)
1464
1465        return self
1466
1467    # bR:AU
1468    def _bindingRequires_vx (self, include_lax):
1469        """Attribute uses require their declarations, but only if lax."""
1470        if not include_lax:
1471            return frozenset()
1472        return frozenset([ self.attributeDeclaration() ])
1473
1474    # aFS:AU
1475    def _adaptForScope (self, ctd):
1476        """Adapt this instance for the given complex type.
1477
1478        If the attribute declaration for this use is not associated with a
1479        complex type definition, then associate a clone of it with this CTD,
1480        and clone a new attribute use that uses the associated declaration.
1481        This attribute use is then inherited by extensions and restrictions,
1482        while retaining its original scope."""
1483        rv = self
1484        assert self.isResolved()
1485        ad = self.__attributeDeclaration
1486        assert ad.scope() is not None
1487        assert isinstance(ctd, ComplexTypeDefinition)
1488        if not isinstance(ad.scope(), ComplexTypeDefinition):
1489            rv = self._clone(ctd, ctd._objectOrigin())
1490            rv.__attributeDeclaration = ad._clone(rv, ctd._objectOrigin())
1491            rv.__attributeDeclaration._setScope(ctd)
1492        ctd._recordLocalDeclaration(rv.__attributeDeclaration)
1493        return rv
1494
1495    def __str__ (self):
1496        return 'AU[%s]' % (self.attributeDeclaration(),)
1497
1498
1499class ElementDeclaration (_ParticleTree_mixin, _SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _ValueConstraint_mixin, _ScopedDeclaration_mixin):
1500    """An XMLSchema U{Element Declaration<http://www.w3.org/TR/xmlschema-1/#cElement_Declarations>} component."""
1501
1502    # Simple or complex type definition
1503    __typeDefinition = None
1504    def typeDefinition (self):
1505        """The simple or complex type to which the element value conforms."""
1506        return self.__typeDefinition
1507    def _typeDefinition (self, type_definition):
1508        self.__typeDefinition = type_definition
1509        if (type_definition is not None) and (self.valueConstraint() is not None):
1510            failed = True
1511            if isinstance(self.__typeDefinition, SimpleTypeDefinition):
1512                failed = False
1513            elif isinstance(self.__typeDefinition, ComplexTypeDefinition):
1514                # The corresponding type may not be resolved so we can't check
1515                # its contentType, but we should know whether it could be
1516                # complex.
1517                ct = type_definition.contentType()
1518                if ct is None:
1519                    # Either it's not complex, or we can't tell yet; neither
1520                    # are failures, but in the latter case delay assigning the
1521                    # type until we know.
1522                    failed = False
1523                    if False != self.__typeDefinition._isComplexContent():
1524                        self.__typeDefinition = None
1525                        self._queueForResolution('unresolved base type');
1526                else:
1527                    failed = not (isinstance(ct, tuple) and (ComplexTypeDefinition.CT_SIMPLE == ct[0]))
1528            if failed:
1529                if self.__typeExpandedName is None:
1530                    raise pyxb.SchemaValidationError('Value constraint on element %s with non-simple content' % (self.expandedName(),))
1531                raise pyxb.SchemaValidationError('Value constraint on element %s with non-simple type %s' % (self.expandedName(), self.__typeExpandedName))
1532        return self
1533
1534    __substitutionGroupExpandedName = None
1535
1536    __typeExpandedName = None
1537
1538    __nillable = False
1539    def nillable (self):
1540        return self.__nillable
1541
1542    __identityConstraintDefinitions = None
1543    def identityConstraintDefinitions (self):
1544        """A list of IdentityConstraintDefinition instances."""
1545        return self.__identityConstraintDefinitions
1546
1547    __substitutionGroupAffiliation = None
1548    def substitutionGroupAffiliation (self):
1549        """None, or a reference to an ElementDeclaration."""
1550        return self.__substitutionGroupAffiliation
1551
1552    SGE_none = 0                #<<< No substitution group exclusion specified
1553    SGE_extension = 0x01        #<<< Substitution by an extension of the base type
1554    SGE_restriction = 0x02      #<<< Substitution by a restriction of the base type
1555    SGE_substitution = 0x04     #<<< Substitution by replacement (?)
1556
1557    _SGE_Map = { 'extension' : SGE_extension
1558               , 'restriction' : SGE_restriction }
1559    _DS_Map = _SGE_Map.copy()
1560    _DS_Map.update( { 'substitution' : SGE_substitution } )
1561
1562    # Subset of SGE marks formed by bitmask.  SGE_substitution is disallowed.
1563    __substitutionGroupExclusions = SGE_none
1564
1565    # Subset of SGE marks formed by bitmask
1566    __disallowedSubstitutions = SGE_none
1567
1568    __abstract = False
1569    def abstract (self):
1570        return self.__abstract
1571
1572    def hasWildcardElement (self):
1573        """Return False, since element declarations are not wildcards."""
1574        return False
1575
1576    # bR:ED
1577    def _bindingRequires_vx (self, include_lax):
1578        """Element declarations depend on the type definition of their
1579        content."""
1580        return frozenset([self.__typeDefinition])
1581
1582    def __init__ (self, *args, **kw):
1583        super(ElementDeclaration, self).__init__(*args, **kw)
1584
1585    # CFD:ED CFD:ElementDeclaration
1586    @classmethod
1587    def CreateFromDOM (cls, node, **kw):
1588        """Create an element declaration from the given DOM node.
1589
1590        wxs is a Schema instance within which the element is being
1591        declared.
1592
1593        scope is the _ScopeDeclaration_mixin context into which the
1594        element declaration is recorded.  It can be SCOPE_global, a
1595        complex type definition, or None in the case of elements
1596        declared in a named model group.
1597
1598        node is a DOM element.  The name must be 'element', and the
1599        node must be in the XMLSchema namespace."""
1600
1601        scope = kw['scope']
1602        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
1603
1604        # Node should be an XMLSchema element node
1605        assert xsd.nodeIsNamed(node, 'element')
1606
1607        # Might be top-level, might be local
1608        name = domutils.NodeAttribute(node, 'name')
1609        if xsd.nodeIsNamed(node.parentNode, 'schema'):
1610            assert _ScopedDeclaration_mixin.SCOPE_global == scope
1611        elif domutils.NodeAttribute(node, 'ref') is None:
1612            # Scope may be None or a CTD.
1613            assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
1614        else:
1615            raise pyxb.SchemaValidationError('Created reference as element declaration')
1616
1617        rv = cls(name=name, node=node, **kw)
1618        rv._annotationFromDOM(node)
1619        rv._valueConstraintFromDOM(node)
1620
1621        rv.__substitutionGroupExpandedName = domutils.NodeAttributeQName(node, 'substitutionGroup')
1622
1623        kw.pop('node', None)
1624        kw['owner'] = rv
1625
1626        # Global EDs should be given indeterminate scope to ensure subordinate
1627        # declarations are not inappropriately associated with the element's
1628        # namespace.  If the ED is within a non-global scope that scope should
1629        # be retained.
1630        if rv._scopeIsGlobal():
1631            kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate
1632
1633        identity_constraints = []
1634        for cn in node.childNodes:
1635            if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'key', 'unique', 'keyref'):
1636                identity_constraints.append(IdentityConstraintDefinition.CreateFromDOM(cn, **kw))
1637        rv.__identityConstraintDefinitions = identity_constraints
1638
1639        rv.__typeDefinition = None
1640        rv.__typeExpandedName = domutils.NodeAttributeQName(node, 'type')
1641        simpleType_node = domutils.LocateUniqueChild(node, 'simpleType')
1642        complexType_node = domutils.LocateUniqueChild(node, 'complexType')
1643        if rv.__typeExpandedName is not None:
1644            if (simpleType_node is not None) and (complexType_node is not None):
1645                raise pyxb.SchemaValidationError('Cannot combine type attribute with simpleType or complexType child')
1646        if (rv.__typeDefinition is None) and (simpleType_node is not None):
1647            rv._typeDefinition(SimpleTypeDefinition.CreateFromDOM(simpleType_node, **kw))
1648        if (rv.__typeDefinition is None) and (complexType_node is not None):
1649            rv._typeDefinition(ComplexTypeDefinition.CreateFromDOM(complexType_node, **kw))
1650        if rv.__typeDefinition is None:
1651            if rv.__typeExpandedName is None:
1652                # Scan for particle types which were supposed to be enclosed in a complexType
1653                for cn in node.childNodes:
1654                    if Particle.IsParticleNode(cn):
1655                        raise pyxb.SchemaValidationError('Node %s in element must be wrapped by complexType.' % (cn.localName,))
1656                rv._typeDefinition(ComplexTypeDefinition.UrTypeDefinition())
1657        rv.__isResolved = (rv.__typeDefinition is not None) and (rv.__substitutionGroupExpandedName is None)
1658        if not rv.__isResolved:
1659            rv._queueForResolution('creation')
1660
1661        attr_val = domutils.NodeAttribute(node, 'nillable')
1662        if attr_val is not None:
1663            rv.__nillable = datatypes.boolean(attr_val)
1664
1665        attr_val = domutils.NodeAttribute(node, 'abstract')
1666        if attr_val is not None:
1667            rv.__abstract = datatypes.boolean(attr_val)
1668
1669        schema = kw['schema']
1670        rv.__disallowedSubstitutions = schema.blockForNode(node, cls._DS_Map)
1671        rv.__substitutionGroupExclusions = schema.finalForNode(node, cls._SGE_Map)
1672
1673        return rv
1674
1675    def isAdaptable (self, ctd):
1676        """Determine whether this element declaration is adaptable.
1677
1678        OK, this gets ugly.  First, if this declaration isn't resolved, it's
1679        clearly not adaptable.
1680
1681        Now: For it to be adaptable, we must know enough about its type to
1682        verify that it is derivation-consistent with any other uses of the
1683        same name in the same complex type.  If the element's type is
1684        resolved, that's good enough.
1685
1686        If the element's type isn't resolved, we're golden as long as
1687        type-equivalent types were used.  But it's also allowed for the
1688        derived ctd to use the element name constraining it to a derivation of
1689        the element base type.  (Go see namespace
1690        http://www.opengis.net/ows/1.1 types PositionType, PositionType2D,
1691        BoundingBox, and WGS84BoundingBox for an example).  So, we really do
1692        have to have the element's type resolved.
1693
1694        Except that if a CTD's content incorporates an element with the same
1695        type as the CTD (i.e., nested), this will never happen, because the
1696        CTD can't get resolved until after it has been resolved.
1697        (Go see {http://www.opengis.net/ows/1.1}ContentsBaseType and
1698        {http://www.opengis.net/ows/1.1}DatasetDescriptionSummaryBaseType for
1699        an example).
1700
1701        So, we give the world a break and assume that if the type we're trying
1702        to resolve is the same as the type of an element in that type, then
1703        the element type will be resolved by the point it's needed.  In point
1704        of fact, it won't, but we'll only notice that if a CTD contains an
1705        element whose type is a restriction of the CTD.  In that case,
1706        isDerivationConsistent will blow chunks and somebody'll have to come
1707        back and finish up this mess.
1708        """
1709
1710        if not self.isResolved():
1711            return False
1712        if self.typeDefinition().isResolved():
1713            return True
1714        # Aw, dammit.  See if we're gonna need the type resolved before we can
1715        # adapt this thing.
1716        existing_decl = ctd.lookupScopedElementDeclaration(self.expandedName())
1717        if existing_decl is None:
1718            # Nobody else has this name, so we don't have to check for
1719            # consistency.
1720            return True
1721        # OK, we've got a name clash.  Are the two types trivially equivalent?
1722        if self.typeDefinition().isTypeEquivalent(existing_decl.typeDefinition()):
1723            # Yes! Go for it.
1724            return True
1725        # No.  Can't proceed until the type definition is resolved.  Hope it
1726        # can be....
1727        _log.warning('Require %s to be resolved; might be a loop.', self.typeDefinition())
1728        return False
1729
1730    # aFS:ED
1731    def _adaptForScope (self, owner, ctd):
1732        rv = self
1733        assert isinstance(ctd, ComplexTypeDefinition), '%s is not a CTD' % (ctd,)
1734        if not isinstance(self.scope(), ComplexTypeDefinition):
1735            assert owner is not None
1736            rv = self._clone(owner, ctd._objectOrigin())
1737            rv._setScope(ctd)
1738        ctd._recordLocalDeclaration(rv)
1739        return rv
1740
1741    __isResolved = False
1742    def isResolved (self):
1743        return self.__isResolved
1744
1745    # res:ED res:ElementDeclaration
1746    def _resolve (self):
1747        if self.isResolved():
1748            return self
1749
1750        #if self._scopeIsIndeterminate():
1751        #   _log.debug('WARNING: Resolving ED %s with indeterminate scope (is this a problem?)', self.expandedName())
1752        if self.__substitutionGroupExpandedName is not None:
1753            sga = self.__substitutionGroupExpandedName.elementDeclaration()
1754            if sga is None:
1755                raise pyxb.SchemaValidationError('Element declaration refers to unrecognized substitution group %s' % (self.__substitutionGroupExpandedName,))
1756            self.__substitutionGroupAffiliation = sga
1757
1758        resolved = True
1759        if self.__typeDefinition is None:
1760            assert self.__typeExpandedName is not None
1761            td = self.__typeExpandedName.typeDefinition()
1762            if td is None:
1763                raise pyxb.SchemaValidationError('Type declaration %s cannot be found' % (self.__typeExpandedName,))
1764            # Type definition may be delayed for default value validation; if
1765            # so, we're not really resolved.
1766            self._typeDefinition(td)
1767            resolved = self.typeDefinition() is not None
1768
1769        self.__isResolved = resolved
1770
1771        return self
1772
1773    def _walkParticleTree (self, visit, arg):
1774        visit(self, None, arg)
1775
1776    def __str__ (self):
1777        if self.typeDefinition() is not None:
1778            return 'ED[%s:%s]' % (self.name(), self.typeDefinition().name())
1779        return 'ED[%s:?]' % (self.name(),)
1780
1781
1782class ComplexTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
1783    __PrivateTransient = set()
1784
1785    # The type resolved from the base attribute.
1786    __baseTypeDefinition = None
1787    def baseTypeDefinition (self):
1788        """The type resolved from the base attribute."""
1789        return self.__baseTypeDefinition
1790
1791    DM_empty = 0                #<<< No derivation method specified
1792    DM_extension = 0x01         #<<< Derivation by extension
1793    DM_restriction = 0x02       #<<< Derivation by restriction
1794
1795    _DM_Map = { 'extension' : DM_extension
1796              , 'restriction' : DM_restriction }
1797
1798    # How the type was derived (a DM_* value)
1799    # (This field is used to identify unresolved definitions.)
1800    __derivationMethod = None
1801    def derivationMethod (self):
1802        """How the type was derived."""
1803        return self.__derivationMethod
1804
1805    # Derived from the final and finalDefault attributes
1806    __final = DM_empty
1807
1808    # Derived from the abstract attribute
1809    __abstract = False
1810    def abstract (self):
1811        return self.__abstract
1812
1813    # A frozenset() of AttributeUse instances.
1814    __attributeUses = None
1815    def attributeUses (self):
1816        """A frozenset() of AttributeUse instances."""
1817        return self.__attributeUses
1818
1819    # A map from NCNames to AttributeDeclaration instances that are
1820    # local to this type.
1821    __scopedAttributeDeclarations = None
1822    def lookupScopedAttributeDeclaration (self, expanded_name):
1823        """Find an attribute declaration with the given name that is local to this type.
1824
1825        Returns None if there is no such local attribute declaration."""
1826        if self.__scopedAttributeDeclarations is None:
1827            return None
1828        return self.__scopedAttributeDeclarations.get(expanded_name)
1829
1830    # A map from NCNames to ElementDeclaration instances that are
1831    # local to this type.
1832    __scopedElementDeclarations = None
1833    def lookupScopedElementDeclaration (self, expanded_name):
1834        """Find an element declaration with the given name that is local to this type.
1835
1836        Returns None if there is no such local element declaration."""
1837        if self.__scopedElementDeclarations is None:
1838            return None
1839        return self.__scopedElementDeclarations.get(expanded_name)
1840
1841    __localScopedDeclarations = None
1842    def localScopedDeclarations (self, reset=False):
1843        """Return a list of element and attribute declarations that were
1844        introduced in this definition (i.e., their scope is this CTD).
1845
1846        @note: This specifically returns a list, with element declarations
1847        first, because name binding should privilege the elements over the
1848        attributes.  Within elements and attributes, the components are sorted
1849        by expanded name, to ensure consistency across a series of binding
1850        generations.
1851
1852        @keyword reset: If C{False} (default), a cached previous value (if it
1853        exists) will be returned.
1854        """
1855        if reset or (self.__localScopedDeclarations is None):
1856            rve = [ _ed for _ed in six.itervalues(self.__scopedElementDeclarations) if (self == _ed.scope()) ]
1857            rve.sort(key=lambda _x: _x.expandedName())
1858            rva = [ _ad for _ad in six.itervalues(self.__scopedAttributeDeclarations) if (self == _ad.scope()) ]
1859            rva.sort(key=lambda _x: _x.expandedName())
1860            self.__localScopedDeclarations = rve
1861            self.__localScopedDeclarations.extend(rva)
1862        return self.__localScopedDeclarations
1863
1864    def _recordLocalDeclaration (self, decl):
1865        """Record the given declaration as being locally scoped in
1866        this type."""
1867        assert isinstance(decl, _ScopedDeclaration_mixin)
1868        if isinstance(decl, ElementDeclaration):
1869            scope_map = self.__scopedElementDeclarations
1870        elif isinstance(decl, AttributeDeclaration):
1871            scope_map = self.__scopedAttributeDeclarations
1872        else:
1873            raise pyxb.LogicError('Unexpected instance of %s recording as local declaration' % (type(decl),))
1874        decl_en = decl.expandedName()
1875        existing_decl = scope_map.setdefault(decl_en, decl)
1876        if decl != existing_decl:
1877            if isinstance(decl, ElementDeclaration):
1878                # Test cos-element-consistent
1879                existing_type = existing_decl.typeDefinition()
1880                pending_type = decl.typeDefinition()
1881                if not pending_type.isDerivationConsistent(existing_type):
1882                    raise pyxb.SchemaValidationError('Conflicting element declarations for %s: existing %s versus new %s' % (decl.expandedName(), existing_type, pending_type))
1883                # If we're deriving by restriction and the declaration has a
1884                # different type than the one in the parent scope, discard the
1885                # parent scope declaration and replace it with this one rather
1886                # than treating the parent as a base.
1887                if (existing_type != pending_type) and (self.DM_restriction == self.derivationMethod()):
1888                    decl._overrideParentScope(existing_decl);
1889                    scope_map[decl_en] = decl;
1890                    existing_decl = decl
1891            elif isinstance(decl, AttributeDeclaration):
1892                raise pyxb.SchemaValidationError('Multiple attribute declarations for %s' % (decl.expandedName(),))
1893            else:
1894                assert False, 'Unrecognized type %s' % (type(decl),)
1895        decl._baseDeclaration(existing_decl)
1896        return self
1897
1898    def _isHierarchyRoot (self):
1899        """Return C{True} iff this is the root of a complex type definition hierarchy.
1900        """
1901        base = self.__baseTypeDefinition
1902        return isinstance(base, SimpleTypeDefinition) or base.isUrTypeDefinition()
1903
1904    CT_EMPTY = 'EMPTY'                 #<<< No content
1905    CT_SIMPLE = 'SIMPLE'               #<<< Simple (character) content
1906    CT_MIXED = 'MIXED'                 #<<< Children may be elements or other (e.g., character) content
1907    CT_ELEMENT_ONLY = 'ELEMENT_ONLY'   #<<< Expect only element content.
1908
1909    def _contentTypeTag (self):
1910        """Return the value of the content type identifier, i.e. one of the
1911        CT_ constants.  Return value is None if no content type has been
1912        defined."""
1913        if isinstance(self.__contentType, tuple):
1914            return self.__contentType[0]
1915        return self.__contentType
1916
1917    def _contentTypeComponent (self):
1918        if isinstance(self.__contentType, tuple):
1919            return self.__contentType[1]
1920        return None
1921
1922    # Identify the sort of content in this type.
1923    __contentType = None
1924    def contentType (self):
1925        """Identify the sort of content in this type.
1926
1927        Valid values are:
1928         - C{CT_EMPTY}
1929         - ( C{CT_SIMPLE}, a L{SimpleTypeDefinition} instance )
1930         - ( C{CT_MIXED}, a L{Particle} instance )
1931         - ( C{CT_ELEMENT_ONLY}, a L{Particle} instance )
1932        """
1933        return self.__contentType
1934
1935    def contentTypeAsString (self):
1936        if self.CT_EMPTY == self.contentType():
1937            return 'EMPTY'
1938        ( tag, particle ) = self.contentType()
1939        if self.CT_SIMPLE == tag:
1940            return 'Simple [%s]' % (particle,)
1941        if self.CT_MIXED == tag:
1942            return 'Mixed [%s]' % (particle,)
1943        if self.CT_ELEMENT_ONLY == tag:
1944            return 'Element [%s]' % (particle,)
1945        raise pyxb.LogicError('Unhandled content type')
1946
1947    # Derived from the block and blockDefault attributes
1948    __prohibitedSubstitutions = DM_empty
1949
1950    # @todo: Extracted from children of various types
1951    __annotations = None
1952
1953    def __init__ (self, *args, **kw):
1954        super(ComplexTypeDefinition, self).__init__(*args, **kw)
1955        self.__derivationMethod = kw.get('derivation_method')
1956        self.__scopedElementDeclarations = { }
1957        self.__scopedAttributeDeclarations = { }
1958
1959    def hasWildcardElement (self):
1960        """Return True iff this type includes a wildcard element in
1961        its content model."""
1962        if self.CT_EMPTY == self.contentType():
1963            return False
1964        ( tag, particle ) = self.contentType()
1965        if self.CT_SIMPLE == tag:
1966            return False
1967        return particle.hasWildcardElement()
1968
1969    def _updateFromOther_csc (self, other):
1970        """Override fields in this instance with those from the other.
1971
1972        This method is invoked only by Schema._addNamedComponent, and
1973        then only when a built-in type collides with a schema-defined
1974        type.  Material like facets is not (currently) held in the
1975        built-in copy, so the DOM information is copied over to the
1976        built-in STD, which is subsequently re-resolved.
1977
1978        Returns self.
1979        """
1980        assert self != other
1981        assert self.isNameEquivalent(other)
1982        super(ComplexTypeDefinition, self)._updateFromOther_csc(other)
1983
1984        if not other.isResolved():
1985            if pyxb.namespace.BuiltInObjectUID != self._objectOrigin().generationUID():
1986                self.__isResolved = False
1987
1988        return self
1989
1990    __UrTypeDefinition = None
1991    @classmethod
1992    def UrTypeDefinition (cls, schema=None, in_builtin_definition=False):
1993        """Create the ComplexTypeDefinition instance that approximates
1994        the ur-type.
1995
1996        See section 3.4.7.
1997        """
1998
1999        # The first time, and only the first time, this is called, a
2000        # namespace should be provided which is the XMLSchema
2001        # namespace for this run of the system.  Please, do not try to
2002        # allow this by clearing the type definition.
2003        #if in_builtin_definition and (cls.__UrTypeDefinition is not None):
2004        #    raise pyxb.LogicError('Multiple definitions of UrType')
2005        if cls.__UrTypeDefinition is None:
2006            # NOTE: We use a singleton subclass of this class
2007            assert schema is not None
2008
2009            ns_ctx = schema.targetNamespace().initialNamespaceContext()
2010
2011            kw = { 'name' : 'anyType',
2012                   'schema' : schema,
2013                   'namespace_context' : ns_ctx,
2014                   'binding_namespace' : schema.targetNamespace(),
2015                   'derivation_method' : cls.DM_restriction,
2016                   'scope' : _ScopedDeclaration_mixin.SCOPE_global }
2017            bi = _UrTypeDefinition(**kw)
2018
2019            # The ur-type is its own baseTypeDefinition
2020            bi.__baseTypeDefinition = bi
2021
2022            # No constraints on attributes
2023            bi._setAttributeWildcard(Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw))
2024
2025            # There isn't anything to look up, but context is still global.
2026            # No declarations will be created, so use indeterminate scope to
2027            # be consistent with validity checks in Particle constructor.
2028            # Content is mixed, with elements completely unconstrained. @todo:
2029            # not associated with a schema (it should be)
2030            kw = { 'namespace_context' : ns_ctx
2031                 , 'schema' : schema
2032                 , 'scope': _ScopedDeclaration_mixin.XSCOPE_indeterminate }
2033            w = Wildcard(namespace_constraint=Wildcard.NC_any, process_contents=Wildcard.PC_lax, **kw)
2034            p = Particle(w, min_occurs=0, max_occurs=None, **kw)
2035            m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ p ], **kw)
2036            bi.__contentType = ( cls.CT_MIXED, Particle(m, **kw) )
2037
2038            # No attribute uses
2039            bi.__attributeUses = set()
2040
2041            # No constraints on extension or substitution
2042            bi.__final = cls.DM_empty
2043            bi.__prohibitedSubstitutions = cls.DM_empty
2044
2045            bi.__abstract = False
2046
2047            # Refer to it by name
2048            bi.setNameInBinding(bi.name())
2049
2050            # The ur-type is always resolved
2051            bi.__isResolved = True
2052
2053            cls.__UrTypeDefinition = bi
2054        return cls.__UrTypeDefinition
2055
2056    def isBuiltin (self):
2057        """Indicate whether this simple type is a built-in type."""
2058        return (self.UrTypeDefinition() == self)
2059
2060    # bR:CTD
2061    def _bindingRequires_vx (self, include_lax):
2062        """Complex type definitions depend on their base type definition, the
2063        type definitions of any local attribute declarations, and if strict
2064        the type definitions of any local element declarations."""
2065        rv = set()
2066        assert self.__baseTypeDefinition is not None
2067        rv.add(self.__baseTypeDefinition)
2068        for decl in self.localScopedDeclarations():
2069            if include_lax or isinstance(decl, AttributeDeclaration):
2070                rv.add(decl.typeDefinition())
2071        if include_lax:
2072            ct = self._contentTypeComponent()
2073            if ct is not None:
2074                rv.add(ct)
2075        return frozenset(rv)
2076
2077    # CFD:CTD CFD:ComplexTypeDefinition
2078    @classmethod
2079    def CreateFromDOM (cls, node, **kw):
2080        # Node should be an XMLSchema complexType node
2081        assert xsd.nodeIsNamed(node, 'complexType')
2082
2083        name = domutils.NodeAttribute(node, 'name')
2084
2085        rv = cls(name=name, node=node, derivation_method=None, **kw)
2086
2087        # Most of the time, the scope will be global.  It can be something
2088        # else only if this is an anonymous CTD (created within an element
2089        # declaration which itself may be global, in a containing CTD, or in a
2090        # model group).
2091        if rv._scopeIsGlobal():
2092            assert isinstance(rv.owner(), Schema)
2093            if rv.isAnonymous():
2094                raise pyxb.SchemaValidationError("Anonymous complex type at schema top level")
2095        else:
2096            assert not isinstance(rv.owner(), Schema)
2097            if not rv.isAnonymous():
2098                raise pyxb.SchemaValidationError('Name attribute invalid on non-global complex types: %s' % (rv.expandedName(),))
2099
2100        kw.pop('node', None)
2101        kw['owner'] = rv
2102        kw['scope'] = rv
2103
2104        return rv.__setContentFromDOM(node, **kw)
2105
2106    __baseExpandedName = None
2107
2108    __ckw = None
2109    __anyAttribute = None
2110    __attributeGroupNames = None
2111    __usesC1 = None
2112    __usesC1C2 = None
2113    __attributeGroups = None
2114    __PrivateTransient.update(['ckw', 'anyAttribute', 'attributeGroupNames', 'usesC1', 'usesC1C2', 'attributeGroups' ])
2115
2116    # Handle attributeUses, attributeWildcard, contentType
2117    def __completeProcessing (self, method, content_style):
2118
2119        if self.__usesC1C2 is None:
2120            # Handle clauses 1 and 2 (common between simple and complex types)
2121            uses_c1 = self.__usesC1 # attribute children
2122            uses_c2 = set()  # attribute group children
2123            self.__attributeGroups = []
2124            for ag_en in self.__attributeGroupNames:
2125                agd = ag_en.attributeGroupDefinition()
2126                if agd is None:
2127                    raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,))
2128                if not agd.isResolved():
2129                    self._queueForResolution('unresolved attribute group', depends_on=agd)
2130                    return self
2131                self.__attributeGroups.append(agd)
2132                uses_c2.update(agd.attributeUses())
2133
2134            uses_c1c2 = uses_c1.union(uses_c2)
2135            for au in uses_c1c2:
2136                if not au.isResolved():
2137                    self._queueForResolution('attribute use not resolved')
2138                    return self
2139                ad = au.attributeDeclaration()
2140                if not ad.isResolved():
2141                    ad_en = ad.expandedName()
2142                    self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad)
2143                    return self
2144
2145            self.__usesC1C2 = frozenset([ _u._adaptForScope(self) for _u in uses_c1c2 ])
2146
2147        # Handle clause 3.  Note the slight difference in description between
2148        # simple and complex content is just that the complex content doesn't
2149        # bother to check that the base type definition is a complex type
2150        # definition.  So the same code should work for both, and we don't
2151        # bother to check content_style.
2152        uses_c3 = set()  # base attributes
2153        if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition):
2154            # NB: The base type definition should be resolved, which means
2155            # that all its attribute uses have been adapted for scope already
2156            uses_c3 = set(self.__baseTypeDefinition.__attributeUses)
2157            assert self.__baseTypeDefinition.isResolved()
2158            for au in uses_c3:
2159                if not au.isResolved():
2160                    self._queueForResolution('unresolved attribute use from base type', depends_on=au)
2161                    return self
2162                ad = au.attributeDeclaration()
2163                if not ad.isResolved():
2164                    ad_en = ad.expandedName()
2165                    self._queueForResolution('unresolved attribute declaration %s from base type' % (ad_en,), depends_on=ad)
2166                    return self
2167                assert not au.attributeDeclaration()._scopeIsIndeterminate()
2168
2169            if self.DM_restriction == method:
2170                # Exclude attributes per clause 3.  Note that this process
2171                # handles both 3.1 and 3.2, since we have not yet filtered
2172                # uses_c1 for prohibited attributes.
2173                for au in self.__usesC1C2:
2174                    matching_uses = au.matchingQNameMembers(uses_c3)
2175                    assert matching_uses is not None
2176                    assert 1 >= len(matching_uses), 'Multiple inherited attribute uses with name %s'
2177                    for au2 in matching_uses:
2178                        assert au2.isResolved()
2179                        uses_c3.remove(au2)
2180                        au._setRestrictionOf(au2)
2181            else:
2182                # In theory, the same attribute name can't appear in the base
2183                # and sub types because that would violate the local
2184                # declaration constraint.
2185                assert self.DM_extension == method
2186
2187        use_map = { }
2188        for au in self.__usesC1C2.union(uses_c3):
2189            assert au.isResolved()
2190            ad_en = au.attributeDeclaration().expandedName()
2191            if ad_en in use_map:
2192                raise pyxb.SchemaValidationError('Multiple definitions for %s in CTD %s' % (ad_en, self.expandedName()))
2193            use_map[ad_en] = au
2194
2195        # Past the last point where we might not resolve this instance.  Store
2196        # the attribute uses, also recording local attribute declarations.
2197        self.__attributeUses = frozenset(six.itervalues(use_map))
2198        if not self._scopeIsIndeterminate():
2199            for au in self.__attributeUses:
2200                assert not au.attributeDeclaration()._scopeIsIndeterminate(), 'indeterminate scope for %s' % (au,)
2201
2202        # @todo: Handle attributeWildcard
2203        # Clause 1
2204        local_wildcard = None
2205        if self.__anyAttribute is not None:
2206            local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute)
2207
2208        # Clause 2
2209        complete_wildcard = _AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), self.__attributeGroups, local_wildcard)
2210
2211        # Clause 3
2212        if self.DM_restriction == method:
2213            # Clause 3.1
2214            self._setAttributeWildcard(complete_wildcard)
2215        else:
2216            assert (self.DM_extension == method)
2217            assert self.baseTypeDefinition().isResolved()
2218            # 3.2.1
2219            base_wildcard = None
2220            if isinstance(self.baseTypeDefinition(), ComplexTypeDefinition):
2221                base_wildcard = self.baseTypeDefinition().attributeWildcard()
2222            # 3.2.2
2223            if base_wildcard is not None:
2224                if complete_wildcard is None:
2225                    # 3.2.2.1.1
2226                    self._setAttributeWildcard(base_wildcard)
2227                else:
2228                    # 3.2.2.1.2
2229                    self._setAttributeWildcard(Wildcard (process_contents=complete_wildcard.processContents(),
2230                                                         namespace_constraint = Wildcard.IntensionalUnion([complete_wildcard.namespaceConstraint(),
2231                                                                                                 base_wildcard.namespaceConstraint()]),
2232                                                         annotation=complete_wildcard.annotation(),
2233                                                         namespace_context=self._namespaceContext()))
2234            else:
2235                # 3.2.2.2
2236                self._setAttributeWildcard(complete_wildcard)
2237
2238        # @todo: Make sure we didn't miss any child nodes
2239
2240        # Remove local attributes we will never use again
2241        del self.__usesC1
2242        del self.__usesC1C2
2243        del self.__attributeGroups
2244        self.__ckw = None
2245
2246        # Mark the type resolved
2247        self.__isResolved = True
2248        return self
2249
2250    def __simpleContent (self, method, **kw):
2251        # Do content type
2252        if isinstance(self.__baseTypeDefinition, ComplexTypeDefinition):
2253            # Clauses 1, 2, and 3 might apply
2254            parent_content_type = self.__baseTypeDefinition.__contentType
2255            if ((type(parent_content_type) == tuple) \
2256                    and (self.CT_SIMPLE == parent_content_type[0]) \
2257                    and (self.DM_restriction == method)):
2258                # Clause 1
2259                assert self.__ctscRestrictionNode is not None
2260                std = self.__ctscClause2STD
2261                if std is None:
2262                    std = parent_content_type[1]
2263                assert isinstance(std, SimpleTypeDefinition)
2264                if not std.isResolved():
2265                    return None
2266                restriction_node = self.__ctscRestrictionNode
2267                self.__ctscClause2STD = None
2268                self.__ctscRestrictionNode = None
2269                return ( self.CT_SIMPLE, std._createRestriction(self, restriction_node) )
2270            if ((type(parent_content_type) == tuple) \
2271                    and (self.CT_MIXED == parent_content_type[0]) \
2272                    and parent_content_type[1].isEmptiable()):
2273                # Clause 2
2274                assert isinstance(self.__ctscClause2STD, SimpleTypeDefinition)
2275                return ( self.CT_SIMPLE, self.__ctscClause2STD )
2276            # Clause 3
2277            return parent_content_type
2278        # Clause 4
2279        return ( self.CT_SIMPLE, self.__baseTypeDefinition )
2280
2281    __ctscClause2STD = None
2282    __ctscRestrictionNode = None
2283    __PrivateTransient.update(['ctscRestrictionNode' ])
2284    __effectiveMixed = None
2285    __effectiveContent = None
2286    __isComplexContent = None
2287    def _isComplexContent (self):
2288        return self.__isComplexContent
2289    __ctscRestrictionMode = None
2290    __contentStyle = None
2291
2292    def __setComplexContentFromDOM (self, type_node, content_node, definition_node_list, method, **kw):
2293        # Do content type.  Cache the keywords that need to be used
2294        # for newly created schema components.
2295        ckw = kw.copy()
2296        ckw['namespace_context'] = pyxb.namespace.NamespaceContext.GetNodeContext(type_node)
2297
2298        # Definition 1: effective mixed
2299        mixed_attr = None
2300        if content_node is not None:
2301            mixed_attr = domutils.NodeAttribute(content_node, 'mixed')
2302        if mixed_attr is None:
2303            mixed_attr = domutils.NodeAttribute(type_node, 'mixed')
2304        if mixed_attr is not None:
2305            effective_mixed = datatypes.boolean(mixed_attr)
2306        else:
2307            effective_mixed = False
2308
2309        # Definition 2: effective content
2310        test_2_1_1 = True
2311        test_2_1_2 = False
2312        test_2_1_3 = False
2313        typedef_node = None
2314        for cn in definition_node_list:
2315            if Node.ELEMENT_NODE != cn.nodeType:
2316                continue
2317            if xsd.nodeIsNamed(cn, 'simpleContent', 'complexContent'):
2318                # Should have found the content node earlier.
2319                raise pyxb.LogicError('Missed explicit wrapper in complexType content')
2320            if Particle.IsTypedefNode(cn):
2321                typedef_node = cn
2322                test_2_1_1 = False
2323            if xsd.nodeIsNamed(cn, 'all', 'sequence') \
2324                    and (not domutils.HasNonAnnotationChild(cn)):
2325                test_2_1_2 = True
2326            if xsd.nodeIsNamed(cn, 'choice') \
2327                    and (not domutils.HasNonAnnotationChild(cn)):
2328                mo_attr = domutils.NodeAttribute(cn, 'minOccurs')
2329                if ((mo_attr is not None) \
2330                        and (0 == datatypes.integer(mo_attr))):
2331                    test_2_1_3 = True
2332        satisfied_predicates = 0
2333        if test_2_1_1:
2334            satisfied_predicates += 1
2335        if test_2_1_2:
2336            satisfied_predicates += 1
2337        if test_2_1_3:
2338            satisfied_predicates += 1
2339        if 1 == satisfied_predicates:
2340            if effective_mixed:
2341                # Clause 2.1.4
2342                assert (typedef_node is None) or test_2_1_2
2343                m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[], **ckw)
2344                effective_content = Particle(m, **ckw)
2345            else:
2346                # Clause 2.1.5
2347                effective_content = self.CT_EMPTY
2348        else:
2349            # Clause 2.2
2350            assert typedef_node is not None
2351            effective_content = Particle.CreateFromDOM(typedef_node, **kw)
2352
2353        # For issues related to soapenc:Array and the fact that PyXB
2354        # determines the content of types derived from it is empty, see
2355        # http://tech.groups.yahoo.com/group/soapbuilders/message/5879 and
2356        # lament the fact that the WSDL spec is not compatible with XSD.  It
2357        # is *not* an error in PyXB.
2358
2359        self.__effectiveMixed = effective_mixed
2360        self.__effectiveContent = effective_content
2361        self.__ckw = ckw
2362
2363    def __complexContent (self, method):
2364        ckw = self.__ckw
2365
2366        # Shared from clause 3.1.2
2367        if self.__effectiveMixed:
2368            ct = self.CT_MIXED
2369        else:
2370            ct = self.CT_ELEMENT_ONLY
2371        # Clause 3
2372        if self.DM_restriction == method:
2373            # Clause 3.1
2374            if self.CT_EMPTY == self.__effectiveContent:
2375                # Clause 3.1.1
2376                content_type = self.CT_EMPTY                     # ASSIGN CT_EMPTY
2377            else:
2378                # Clause 3.1.2(.2)
2379                content_type = ( ct, self.__effectiveContent )         # ASSIGN RESTRICTION
2380                assert 0 == len(self.__scopedElementDeclarations)
2381                # Reference the parent element declarations; normally this
2382                # would happen naturally as a consequence of appending this
2383                # type's content model to the parent's, but with restriction
2384                # there is no such re-use unless we do this.
2385                self.__scopedElementDeclarations.update(self.__baseTypeDefinition.__scopedElementDeclarations)
2386        else:
2387            # Clause 3.2
2388            assert self.DM_extension == method
2389            assert self.__baseTypeDefinition.isResolved()
2390            parent_content_type = self.__baseTypeDefinition.contentType()
2391            if self.CT_EMPTY == self.__effectiveContent:
2392                content_type = parent_content_type               # ASSIGN EXTENSION PARENT ONLY
2393            elif self.CT_EMPTY == parent_content_type:
2394                # Clause 3.2.2
2395                content_type = ( ct, self.__effectiveContent )         # ASSIGN EXTENSION LOCAL ONLY
2396            else:
2397                assert type(parent_content_type) == tuple
2398                m = ModelGroup(compositor=ModelGroup.C_SEQUENCE, particles=[ parent_content_type[1], self.__effectiveContent ], **ckw)
2399                content_type = ( ct, Particle(m, **ckw) )        # ASSIGN EXTENSION PARENT AND LOCAL
2400
2401        assert (self.CT_EMPTY == content_type) or ((type(content_type) == tuple) and (content_type[1] is not None))
2402        return content_type
2403
2404    __isResolved = False
2405    def isResolved (self):
2406        """Indicate whether this complex type is fully defined.
2407
2408        All built-in type definitions are resolved upon creation.
2409        Schema-defined type definitionss are held unresolved until the
2410        schema has been completely read, so that references to later
2411        schema-defined types can be resolved.  Resolution is performed
2412        after the entire schema has been scanned and type-definition
2413        instances created for all topLevel{Simple,Complex}Types.
2414
2415        If a built-in type definition is also defined in a schema
2416        (which it should be), the built-in definition is kept, with
2417        the schema-related information copied over from the matching
2418        schema-defined type definition.  The former then replaces the
2419        latter in the list of type definitions to be resolved.  See
2420        Schema._addNamedComponent.
2421        """
2422        return self.__isResolved
2423
2424    # Back door to allow the ur-type to re-resolve itself.  Only needed when
2425    # we're generating bindings for XMLSchema itself.
2426    def _setDerivationMethod (self, derivation_method):
2427        self.__derivationMethod = derivation_method
2428        self.__isResolved = True
2429        return self
2430
2431    def __setContentFromDOM (self, node, **kw):
2432        schema = kw.get('schema')
2433        assert schema is not None
2434        self.__prohibitedSubstitutions = schema.blockForNode(node, self._DM_Map)
2435        self.__final = schema.finalForNode(node, self._DM_Map)
2436
2437        attr_val = domutils.NodeAttribute(node, 'abstract')
2438        if attr_val is not None:
2439            self.__abstract = datatypes.boolean(attr_val)
2440
2441        # Assume we're in the short-hand case: the entire content is
2442        # implicitly wrapped in a complex restriction of the ur-type.
2443        definition_node_list = node.childNodes
2444        is_complex_content = True
2445        self.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition()
2446        method = self.DM_restriction
2447
2448        # Determine whether above assumption is correct by looking for
2449        # element content and seeing if it's one of the wrapper
2450        # elements.
2451        first_elt = domutils.LocateFirstChildElement(node)
2452        content_node = None
2453        clause2_std = None
2454        ctsc_restriction_node = None
2455        if first_elt:
2456            have_content = False
2457            if xsd.nodeIsNamed(first_elt, 'simpleContent'):
2458                have_content = True
2459                is_complex_content = False
2460            elif xsd.nodeIsNamed(first_elt, 'complexContent'):
2461                have_content = True
2462            else:
2463                # Not one of the wrappers; use implicit wrapper around
2464                # the children
2465                if not Particle.IsParticleNode(first_elt, 'attributeGroup', 'attribute', 'anyAttribute'):
2466                    raise pyxb.SchemaValidationError('Unexpected element %s at root of complexType' % (first_elt.nodeName,))
2467            if have_content:
2468                # Repeat the search to verify that only the one child is present.
2469                content_node = domutils.LocateFirstChildElement(node, require_unique=True)
2470                assert content_node == first_elt
2471
2472                # Identify the contained restriction or extension
2473                # element, and extract the base type.
2474                ions = domutils.LocateFirstChildElement(content_node, absent_ok=False)
2475                if xsd.nodeIsNamed(ions, 'restriction'):
2476                    method = self.DM_restriction
2477                    if not is_complex_content:
2478                        # Clause 2 of complex type with simple content
2479                        ctsc_restriction_node = ions
2480                        ions_st = domutils.LocateUniqueChild(ions,'simpleType')
2481                        if ions_st is not None:
2482                            clause2_std = SimpleTypeDefinition.CreateFromDOM(ions_st, **kw)
2483                elif xsd.nodeIsNamed(ions, 'extension'):
2484                    method = self.DM_extension
2485                else:
2486                    raise pyxb.SchemaValidationError('Expected restriction or extension as sole child of %s in %s' % (content_node.nodeName, self.name()))
2487                self.__baseExpandedName = domutils.NodeAttributeQName(ions, 'base')
2488                if self.__baseExpandedName is None:
2489                    raise pyxb.SchemaValidationError('Element %s missing base attribute' % (ions.nodeName,))
2490                self.__baseTypeDefinition = None
2491                # The content is defined by the restriction/extension element
2492                definition_node_list = ions.childNodes
2493        self.__derivationMethod = method
2494        self.__isComplexContent = is_complex_content
2495        self.__ctscRestrictionNode = ctsc_restriction_node
2496        self.__ctscClause2STD = clause2_std
2497
2498        (attributes, attribute_group_names, any_attribute) = self._attributeRelevantChildren(definition_node_list)
2499        self.__usesC1 = set()
2500        for cn in attributes:
2501            au = AttributeUse.CreateFromDOM(cn, **kw)
2502            self.__usesC1.add(au)
2503        self.__attributeGroupNames = attribute_group_names
2504        self.__anyAttribute = any_attribute
2505
2506        if self.__isComplexContent:
2507            self.__setComplexContentFromDOM(node, content_node, definition_node_list, self.__derivationMethod, **kw)
2508
2509        # Creation does not attempt to do resolution.  Queue up the newly created
2510        # whatsis so we can resolve it after everything's been read in.
2511        self._annotationFromDOM(node)
2512
2513        if not self.isResolved():
2514            self._queueForResolution('creation')
2515
2516        return self
2517
2518    # Resolution of a CTD can be delayed for the following reasons:
2519    #
2520    # * It extends or restricts a base type that has not been resolved
2521    #   [_resolve]
2522    #
2523    # * It refers to an attribute or attribute group that has not been
2524    #   resolved [__completeProcessing]
2525    #
2526    # * It includes an attribute that matches in NCName and namespace
2527    #   an unresolved attribute from the base type
2528    #   [__completeProcessing]
2529    #
2530    # * The content model includes a particle which cannot be resolved
2531    #   (so has not contributed any local element declarations).
2532    # res:CTD
2533    def _resolve (self):
2534        if self.isResolved():
2535            return self
2536
2537        # @todo: implement prohibitedSubstitutions, final, annotations
2538
2539        # See whether we've resolved through to the base type
2540        if self.__baseTypeDefinition is None:
2541            base_type = self.__baseExpandedName.typeDefinition()
2542            if base_type is None:
2543                raise pyxb.SchemaValidationError('Cannot locate %s: need import?' % (self.__baseExpandedName,))
2544            if not base_type.isResolved():
2545                # Have to delay resolution until the type this
2546                # depends on is available.
2547                self._queueForResolution('unresolved base type %s' % (self.__baseExpandedName,), depends_on=base_type)
2548                return self
2549            self.__baseTypeDefinition = base_type
2550
2551        # Only build the content once.  This will not complete if the content
2552        # is a restriction of an unresolved simple type; otherwise, it only
2553        # depends on the base type which we know is good.
2554        if self.__contentType is None:
2555            if self.__isComplexContent:
2556                content_type = self.__complexContent(self.__derivationMethod)
2557                self.__contentStyle = 'complex'
2558            else:
2559                # The definition node list is not relevant to simple content
2560                content_type = self.__simpleContent(self.__derivationMethod)
2561                if content_type is None:
2562                    self._queueForResolution('restriction of unresolved simple type')
2563                    return self
2564                self.__contentStyle = 'simple'
2565            assert content_type is not None
2566            self.__contentType = content_type
2567
2568        # Last chance for failure is if we haven't been able to
2569        # extract all the element declarations that might appear in
2570        # this complex type.  That technically wouldn't stop this from
2571        # being resolved, but it does prevent us from using it as a
2572        # context.
2573        if isinstance(self.__contentType, tuple) and isinstance(self.__contentType[1], Particle):
2574            prt = self.__contentType[1]
2575            if not prt.isAdaptable(self):
2576                self._queueForResolution('content particle %s is not deep-resolved' % (prt,))
2577                return self
2578            self.__contentType = (self.__contentType[0], prt._adaptForScope(self, self))
2579
2580        return self.__completeProcessing(self.__derivationMethod, self.__contentStyle)
2581
2582    def pythonSupport (self):
2583        """Complex type definitions have no built-in type support."""
2584        return None
2585
2586    def __str__ (self):
2587        if self.isAnonymous():
2588            return 'CTD{Anonymous}[%x]' % (id(self),)
2589        return 'CTD[%s]' % (self.expandedName(),)
2590
2591class _UrTypeDefinition (ComplexTypeDefinition, _Singleton_mixin):
2592    """Subclass ensures there is only one ur-type."""
2593    def pythonSupport (self):
2594        """The ur-type does have a Python class backing it up."""
2595        return datatypes.anyType
2596
2597    def _resolve (self):
2598        # The ur type is always resolved, except when it gets unresolved
2599        # through being updated from an instance read from the schema.
2600        return self._setDerivationMethod(self.DM_restriction)
2601
2602
2603class AttributeGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin, _AttributeWildcard_mixin):
2604    """An XMLSchema U{Attribute Group Definition<http://www.w3.org/TR/xmlschema-1/#cAttribute_Group_Definitions>} component."""
2605    __PrivateTransient = set()
2606
2607    # A frozenset of AttributeUse instances
2608    __attributeUses = None
2609
2610    def __init__ (self, *args, **kw):
2611        super(AttributeGroupDefinition, self).__init__(*args, **kw)
2612        #assert 'scope' in kw
2613        #assert self._scopeIsIndeterminate()
2614
2615    def __str__ (self):
2616        return 'AGD[%s]' % (self.expandedName(),)
2617
2618    @classmethod
2619    def CreateBaseInstance (cls, name, schema, attribute_uses):
2620        """Create an attribute declaration component for a specified namespace."""
2621        kw = { 'name' : name,
2622               'schema' : schema,
2623               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
2624               'scope' : _ScopedDeclaration_mixin.SCOPE_global }
2625        bi = cls(**kw)
2626        bi.__attributeUses = frozenset(attribute_uses)
2627        bi.__isResolved = True
2628        return bi
2629
2630    __anyAttribute = None
2631    __attributeGroupNames = None
2632    __PrivateTransient.update(['anyAttribute', 'attributeGroupNames'])
2633
2634    # CFD:AGD CFD:AttributeGroupDefinition
2635    @classmethod
2636    def CreateFromDOM (cls, node, **kw):
2637        """Create an attribute group definition from the given DOM node.
2638
2639        """
2640
2641        assert xsd.nodeIsNamed(node, 'attributeGroup')
2642        name = domutils.NodeAttribute(node, 'name')
2643
2644        # Attribute group definitions can only appear at the top level of the
2645        # schema, and any definitions in them are scope indeterminate until
2646        # they're referenced in a complex type.
2647        kw.update({ 'scope' : _ScopedDeclaration_mixin.XSCOPE_indeterminate })
2648        rv = cls(name=name, node=node, **kw)
2649
2650        rv._annotationFromDOM(node)
2651
2652        # Attribute group definitions must not be references
2653        if domutils.NodeAttribute(node, 'ref'):
2654            raise pyxb.SchemaValidationError('Attribute reference at top level')
2655
2656        kw.pop('node', None)
2657        kw['owner'] = rv
2658
2659        (attributes, attribute_group_names, any_attribute) = rv._attributeRelevantChildren(node.childNodes)
2660        rv.__attributeUses = set()
2661        for cn in attributes:
2662            rv.__attributeUses.add(AttributeUse.CreateFromDOM(cn, **kw))
2663        rv.__attributeGroupNames = attribute_group_names
2664        rv.__anyAttribute = any_attribute
2665
2666        # Unconditionally queue for resolution, to avoid repeating the
2667        # wildcard code.
2668        rv._queueForResolution('creation')
2669
2670        return rv
2671
2672    # Indicates whether we have resolved any references
2673    __isResolved = False
2674    def isResolved (self):
2675        return self.__isResolved
2676
2677    def _resolve (self):
2678        if self.__isResolved:
2679            return self
2680
2681        uses = self.__attributeUses
2682        attribute_groups = []
2683        for ag_en in self.__attributeGroupNames:
2684            agd = ag_en.attributeGroupDefinition()
2685            if agd is None:
2686                raise pyxb.SchemaValidationError('Attribute group %s cannot be found' % (ag_en,))
2687            if not agd.isResolved():
2688                self._queueForResolution('attributeGroup %s not resolved' % (ag_en,))
2689                return self
2690            attribute_groups.append(agd)
2691            uses = uses.union(agd.attributeUses())
2692
2693        self.__attributeUses = frozenset(uses)
2694
2695        # "Complete wildcard" per CTD
2696        local_wildcard = None
2697        if self.__anyAttribute is not None:
2698            local_wildcard = Wildcard.CreateFromDOM(self.__anyAttribute)
2699        self._setAttributeWildcard(_AttributeWildcard_mixin.CompleteWildcard(self._namespaceContext(), attribute_groups, local_wildcard))
2700
2701        self.__isResolved = True
2702        return self
2703
2704    # bR:AGD
2705    def _bindingRequires_vx (self, include_lax):
2706        """Attribute group declarations require their uses, but only if lax."""
2707        if not include_lax:
2708            return frozenset()
2709        return frozenset(self.attributeUses())
2710
2711    def attributeUses (self):
2712        return self.__attributeUses
2713
2714class ModelGroupDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
2715    """An XMLSchema U{Model Group Definition<http://www.w3.org/TR/xmlschema-1/#cModel_Group_Definitions>} component."""
2716    # Reference to a _ModelGroup
2717    __modelGroup = None
2718
2719    def modelGroup (self):
2720        """The model group for which this definition provides a name."""
2721        return self.__modelGroup
2722
2723    # CFD:MGD CFD:ModelGroupDefinition
2724    @classmethod
2725    def CreateFromDOM (cls, node, **kw):
2726        """Create a Model Group Definition from a DOM element node.
2727
2728        wxs is a Schema instance within which the model group is being
2729        defined.
2730
2731        node is a DOM element.  The name must be 'group', and the node
2732        must be in the XMLSchema namespace.  The node must have a
2733        'name' attribute, and must not have a 'ref' attribute.
2734        """
2735        assert xsd.nodeIsNamed(node, 'group')
2736
2737        assert domutils.NodeAttribute(node, 'ref') is None
2738
2739        name = domutils.NodeAttribute(node, 'name')
2740        kw['scope'] = _ScopedDeclaration_mixin.XSCOPE_indeterminate
2741        rv = cls(name=name, node=node, **kw)
2742        rv._annotationFromDOM(node)
2743
2744        kw.pop('node', None)
2745        kw['owner'] = rv
2746
2747        for cn in node.childNodes:
2748            if Node.ELEMENT_NODE != cn.nodeType:
2749                continue
2750            if ModelGroup.IsGroupMemberNode(cn):
2751                assert not rv.__modelGroup
2752                # Model group definitions always occur at the top level of the
2753                # schema, so the elements declared in them are not bound to a
2754                # scope until they are referenced in a complex type.
2755                rv.__modelGroup = ModelGroup.CreateFromDOM(cn, model_group_definition=rv, **kw)
2756        assert rv.__modelGroup is not None
2757        return rv
2758
2759    # bR:MGD
2760    def _bindingRequires_vx (self, include_lax):
2761        """Model group definitions depend on the contained model group."""
2762        if not include_lax:
2763            return frozenset()
2764        return frozenset([self.__modelGroup])
2765
2766    def __str__ (self):
2767        return 'MGD[%s: %s]' % (self.name(), self.modelGroup())
2768
2769
2770class ModelGroup (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
2771    """An XMLSchema U{Model Group<http://www.w3.org/TR/xmlschema-1/#cModel_Group>} component."""
2772    C_INVALID = 0
2773    C_ALL = 0x01
2774    C_CHOICE = 0x02
2775    C_SEQUENCE = 0x03
2776
2777    # One of the C_* values above.  Set at construction time from the
2778    # keyword parameter "compositor".
2779    __compositor = C_INVALID
2780    def compositor (self):
2781        return self.__compositor
2782
2783    @classmethod
2784    def CompositorToString (cls, compositor):
2785        """Map a compositor value to a string."""
2786        if cls.C_ALL == compositor:
2787            return 'all'
2788        if cls.C_CHOICE == compositor:
2789            return 'choice'
2790        if cls.C_SEQUENCE == compositor:
2791            return 'sequence'
2792        return 'invalid'
2793
2794    def compositorToString (self):
2795        """Return a string representing the compositor value."""
2796        return self.CompositorToString(self.__compositor)
2797
2798    # A list of Particle instances.  Set at construction time from
2799    # the keyword parameter "particles".
2800    __particles = None
2801    def particles (self):
2802        return self.__particles
2803
2804    def isAdaptable (self, ctd):
2805        """A model group has an unresolvable particle if any of its
2806        particles is unresolvable.  Duh."""
2807        for p in self.particles():
2808            if not p.isAdaptable(ctd):
2809                return False
2810        return True
2811
2812    def effectiveTotalRange (self, particle):
2813        """Return the minimum and maximum of the number of elements that can
2814        appear in a sequence matched by this particle.
2815
2816        See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range}
2817        """
2818        if self.__compositor in (self.C_ALL, self.C_SEQUENCE):
2819            sum_minoccurs = 0
2820            sum_maxoccurs = 0
2821            for prt in self.__particles:
2822                (prt_min, prt_max) = prt.effectiveTotalRange()
2823                sum_minoccurs += prt_min
2824                if sum_maxoccurs is not None:
2825                    if prt_max is None:
2826                        sum_maxoccurs = None
2827                    else:
2828                        sum_maxoccurs += prt_max
2829            prod_maxoccurs = particle.maxOccurs()
2830            if prod_maxoccurs is not None:
2831                if sum_maxoccurs is None:
2832                    prod_maxoccurs = None
2833                else:
2834                    prod_maxoccurs *= sum_maxoccurs
2835            return (sum_minoccurs * particle.minOccurs(), prod_maxoccurs)
2836        assert self.__compositor == self.C_CHOICE
2837        if 0 == len(self.__particles):
2838            min_minoccurs = 0
2839            max_maxoccurs = 0
2840        else:
2841            (min_minoccurs, max_maxoccurs) = self.__particles[0].effectiveTotalRange()
2842            for prt in self.__particles[1:]:
2843                (prt_min, prt_max) = prt.effectiveTotalRange()
2844                if prt_min < min_minoccurs:
2845                    min_minoccurs = prt_min
2846                if prt_max is None:
2847                    max_maxoccurs = None
2848                elif (max_maxoccurs is not None) and (prt_max > max_maxoccurs):
2849                    max_maxoccurs = prt_max
2850        min_minoccurs *= particle.minOccurs()
2851        if (max_maxoccurs is not None) and (particle.maxOccurs() is not None):
2852            max_maxoccurs *=  particle.maxOccurs()
2853        return (min_minoccurs, max_maxoccurs)
2854
2855    # The ModelGroupDefinition that names this ModelGroup, or None if
2856    # the ModelGroup is anonymous.  This is set at construction time
2857    # from the keyword parameter "model_group_definition".
2858    __modelGroupDefinition = None
2859    def modelGroupDefinition (self):
2860        """The ModelGroupDefinition that names this group, or None if it is unnamed."""
2861        return self.__modelGroupDefinition
2862
2863    def __init__ (self, compositor, particles, *args, **kw):
2864        """Create a new model group.
2865
2866        compositor must be a legal compositor value (one of C_ALL, C_CHOICE, C_SEQUENCE).
2867
2868        particles must be a list of zero or more Particle instances.
2869
2870        scope is the _ScopeDeclaration_mixin context into which new
2871        declarations are recorded.  It can be SCOPE_global, a complex
2872        type definition, or None if this is (or is within) a named
2873        model group.
2874
2875        model_group_definition is an instance of ModelGroupDefinition
2876        if this is a named model group.  It defaults to None
2877        indicating a local group.
2878        """
2879
2880        super(ModelGroup, self).__init__(*args, **kw)
2881        assert 'scope' in kw
2882        self.__compositor = compositor
2883        self.__particles = particles
2884        self.__modelGroupDefinition = kw.get('model_group_definition')
2885
2886    def hasWildcardElement (self):
2887        """Return True if the model includes a wildcard amongst its particles."""
2888        for p in self.particles():
2889            if p.hasWildcardElement():
2890                return True
2891        return False
2892
2893    # bR:MG
2894    def _bindingRequires_vx (self, include_lax):
2895        if not include_lax:
2896            return frozenset()
2897        return frozenset(self.__particles)
2898
2899    # CFD:MG CFD:ModelGroup
2900    @classmethod
2901    def CreateFromDOM (cls, node, **kw):
2902        """Create a model group from the given DOM node.
2903
2904        wxs is a Schema instance within which the model group is being
2905        defined.
2906
2907        node is a DOM element.  The name must be one of ( 'all',
2908        'choice', 'sequence' ), and the node must be in the XMLSchema
2909        namespace.
2910
2911        scope is the _ScopeDeclaration_mxin context that is assigned
2912        to declarations that appear within the model group.  It can be
2913        None, indicating no scope defined, or a complex type
2914        definition.
2915        """
2916
2917        scope = kw['scope']
2918        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
2919
2920        if xsd.nodeIsNamed(node, 'all'):
2921            compositor = cls.C_ALL
2922        elif xsd.nodeIsNamed(node, 'choice'):
2923            compositor = cls.C_CHOICE
2924        else:
2925            assert xsd.nodeIsNamed(node, 'sequence')
2926            compositor = cls.C_SEQUENCE
2927        particles = []
2928        # Remove the owner from particle constructor arguments: we need to set it later
2929        kw.pop('owner', None)
2930        for cn in node.childNodes:
2931            if Node.ELEMENT_NODE != cn.nodeType:
2932                continue
2933            if Particle.IsParticleNode(cn):
2934                # NB: Ancestor of particle is set in the ModelGroup constructor
2935                particle = Particle.CreateFromDOM(node=cn, **kw);
2936                if 0 == particle.maxOccurs():
2937                    if getattr(cn, '_location', False):
2938                        location = ' at ' + str(cn._location());
2939                    else:
2940                        location = '';
2941                    _log.warning('Particle %s%s discarded due to maxOccurs 0' % (particle, location))
2942                else:
2943                    particles.append(particle)
2944            elif not xsd.nodeIsNamed(cn, 'annotation'):
2945                raise pyxb.SchemaValidationError('Unexpected element %s in model group' % (cn.nodeName,))
2946        rv = cls(compositor, particles, node=node, **kw)
2947        for p in particles:
2948            p._setOwner(rv)
2949        rv._annotationFromDOM(node)
2950        return rv
2951
2952    @classmethod
2953    def IsGroupMemberNode (cls, node):
2954        return xsd.nodeIsNamed(node, 'all', 'choice', 'sequence')
2955
2956    # aFS:MG
2957    def _adaptForScope (self, owner, ctd):
2958        rv = self
2959        assert isinstance(ctd, ComplexTypeDefinition)
2960        maybe_rv = self._clone(owner, ctd._objectOrigin())
2961        scoped_particles = [ _p._adaptForScope(maybe_rv, ctd) for _p in self.particles() ]
2962        do_clone = (self._scope() != ctd) or (self.particles() != scoped_particles)
2963        if do_clone:
2964            rv = maybe_rv
2965            rv.__particles = scoped_particles
2966        return rv
2967
2968    def _walkParticleTree (self, visit, arg):
2969        visit(self, True, arg)
2970        for p in self.particles():
2971            p._walkParticleTree(visit, arg)
2972        visit(self, False, arg)
2973
2974    def __str__ (self):
2975        comp = None
2976        if self.C_ALL == self.compositor():
2977            comp = 'ALL'
2978        elif self.C_CHOICE == self.compositor():
2979            comp = 'CHOICE'
2980        elif self.C_SEQUENCE == self.compositor():
2981            comp = 'SEQUENCE'
2982        return '%s:(%s)' % (comp, six.u(',').join( [ six.text_type(_p) for _p in self.particles() ] ) )
2983
2984class Particle (_ParticleTree_mixin, _SchemaComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin):
2985    """An XMLSchema U{Particle<http://www.w3.org/TR/xmlschema-1/#cParticle>} component."""
2986
2987    # The minimum number of times the term may appear.
2988    __minOccurs = 1
2989    def minOccurs (self):
2990        """The minimum number of times the term may appear.
2991
2992        Defaults to 1."""
2993        return self.__minOccurs
2994
2995    # Upper limit on number of times the term may appear.
2996    __maxOccurs = 1
2997    def maxOccurs (self):
2998        """Upper limit on number of times the term may appear.
2999
3000        If None, the term may appear any number of times; otherwise,
3001        this is an integral value indicating the maximum number of times
3002        the term may appear.  The default value is 1; the value, unless
3003        None, must always be at least minOccurs().
3004        """
3005        return self.__maxOccurs
3006
3007    # A reference to a ModelGroup, WildCard, or ElementDeclaration
3008    __term = None
3009    def term (self):
3010        """A reference to a ModelGroup, Wildcard, or ElementDeclaration."""
3011        return self.__term
3012    __pendingTerm = None
3013
3014    __refExpandedName = None
3015    __resolvableType = None
3016
3017    def effectiveTotalRange (self):
3018        """Extend the concept of effective total range to all particles.
3019
3020        See U{http://www.w3.org/TR/xmlschema-1/#cos-seq-range} and
3021        U{http://www.w3.org/TR/xmlschema-1/#cos-choice-range}
3022        """
3023        if isinstance(self.__term, ModelGroup):
3024            return self.__term.effectiveTotalRange(self)
3025        return (self.minOccurs(), self.maxOccurs())
3026
3027    def isEmptiable (self):
3028        """Return C{True} iff this particle can legitimately match an empty
3029        sequence (no content).
3030
3031        See U{http://www.w3.org/TR/xmlschema-1/#cos-group-emptiable}
3032        """
3033        return 0 == self.effectiveTotalRange()[0]
3034
3035    def hasWildcardElement (self):
3036        """Return True iff this particle has a wildcard in its term.
3037
3038        Note that the wildcard may be in a nested model group."""
3039        return self.term().hasWildcardElement()
3040
3041    def __init__ (self, term, *args, **kw):
3042        """Create a particle from the given DOM node.
3043
3044        term is a XML Schema Component: one of ModelGroup,
3045        ElementDeclaration, and Wildcard.
3046
3047        The following keyword arguments are processed:
3048
3049        min_occurs is a non-negative integer value with default 1,
3050        denoting the minimum number of terms required by the content
3051        model.
3052
3053        max_occurs is a positive integer value with default 1, or None
3054        indicating unbounded, denoting the maximum number of terms
3055        allowed by the content model.
3056
3057        scope is the _ScopeDeclaration_mxin context that is assigned
3058        to declarations that appear within the particle.  It can be
3059        None, indicating no scope defined, or a complex type
3060        definition.
3061        """
3062
3063        super(Particle, self).__init__(*args, **kw)
3064
3065        min_occurs = kw.get('min_occurs', 1)
3066        max_occurs = kw.get('max_occurs', 1)
3067
3068        assert 'scope' in kw
3069        assert (self._scopeIsIndeterminate()) or isinstance(self._scope(), ComplexTypeDefinition)
3070
3071        if term is not None:
3072            self.__term = term
3073
3074        assert isinstance(min_occurs, six.integer_types)
3075        self.__minOccurs = min_occurs
3076        assert (max_occurs is None) or isinstance(max_occurs, six.integer_types)
3077        self.__maxOccurs = max_occurs
3078        if self.__maxOccurs is not None:
3079            if self.__minOccurs > self.__maxOccurs:
3080                raise pyxb.LogicError('Particle minOccurs %s is greater than maxOccurs %s on creation' % (min_occurs, max_occurs))
3081
3082    # res:Particle
3083    def _resolve (self):
3084        if self.isResolved():
3085            return self
3086
3087        # @RESOLUTION@
3088        if ModelGroup == self.__resolvableType:
3089            group_decl = self.__refExpandedName.modelGroupDefinition()
3090            if group_decl is None:
3091                raise pyxb.SchemaValidationError('Model group reference %s cannot be found' % (self.__refExpandedName,))
3092
3093            self.__pendingTerm = group_decl.modelGroup()
3094            assert self.__pendingTerm is not None
3095        elif ElementDeclaration == self.__resolvableType:
3096            # 3.9.2 says use 3.3.2, which is Element.  The element inside a
3097            # particle is a localElement, so we either get the one it refers
3098            # to (which is top-level), or create a local one here.
3099            if self.__refExpandedName is not None:
3100                assert self.__pendingTerm is None
3101                self.__pendingTerm = self.__refExpandedName.elementDeclaration()
3102                if self.__pendingTerm is None:
3103                    raise pyxb.SchemaValidationError('Unable to locate element referenced by %s' % (self.__refExpandedName,))
3104            assert self.__pendingTerm is not None
3105
3106            # Whether this is a local declaration or one pulled in from the
3107            # global type definition symbol space, its name is now reserved in
3108            # this type.
3109            assert self.__pendingTerm is not None
3110        else:
3111            assert False
3112
3113        self.__term = self.__pendingTerm
3114        assert self.__term is not None
3115
3116        return self
3117
3118    def isResolved (self):
3119        return self.__term is not None
3120
3121    # CFD:Particle
3122    @classmethod
3123    def CreateFromDOM (cls, node, **kw):
3124        """Create a particle from the given DOM node.
3125
3126        wxs is a Schema instance within which the model group is being
3127        defined.
3128
3129        node is a DOM element.  The name must be one of ( 'group',
3130        'element', 'any', 'all', 'choice', 'sequence' ), and the node
3131        must be in the XMLSchema namespace.
3132
3133        scope is the _ScopeDeclaration_mxin context that is assigned
3134        to declarations that appear within the model group.  It can be
3135        None, indicating no scope defined, or a complex type
3136        definition.
3137        """
3138        scope = kw['scope']
3139        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or isinstance(scope, ComplexTypeDefinition)
3140
3141        kw.update({ 'min_occurs' : 1
3142                  , 'max_occurs' : 1
3143                  , 'node' : node })
3144
3145        if not Particle.IsParticleNode(node):
3146            raise pyxb.LogicError('Attempted to create particle from illegal element %s' % (node.nodeName,))
3147        attr_val = domutils.NodeAttribute(node, 'minOccurs')
3148        if attr_val is not None:
3149            kw['min_occurs'] = datatypes.nonNegativeInteger(attr_val)
3150        attr_val = domutils.NodeAttribute(node, 'maxOccurs')
3151        if attr_val is not None:
3152            if 'unbounded' == attr_val:
3153                kw['max_occurs'] = None
3154            else:
3155                kw['max_occurs'] = datatypes.nonNegativeInteger(attr_val)
3156
3157        rv = cls(None, **kw)
3158
3159        kw.pop('node', None)
3160        kw['owner'] = rv
3161
3162        rv.__refExpandedName = domutils.NodeAttributeQName(node, 'ref')
3163        rv.__pendingTerm = None
3164        rv.__resolvableType = None
3165        if xsd.nodeIsNamed(node, 'group'):
3166            # 3.9.2 says use 3.8.2, which is ModelGroup.  The group
3167            # inside a particle is a groupRef.  If there is no group
3168            # with that name, this throws an exception as expected.
3169            if rv.__refExpandedName is None:
3170                raise pyxb.SchemaValidationError('group particle without reference')
3171            rv.__resolvableType = ModelGroup
3172        elif xsd.nodeIsNamed(node, 'element'):
3173            if rv.__refExpandedName is None:
3174                schema = kw.get('schema')
3175                assert schema is not None
3176                target_namespace = schema.targetNamespaceForNode(node, ElementDeclaration)
3177                incoming_tns = kw.get('target_namespace')
3178                if incoming_tns is not None:
3179                    assert incoming_tns == target_namespace
3180                else:
3181                    kw['target_namespace'] = target_namespace
3182                rv.__term = ElementDeclaration.CreateFromDOM(node=node, **kw)
3183            else:
3184                # NOTE: 3.3.3 clause 2.2 specifies that if ref is used, all
3185                # the other configuration attributes like nillable and default
3186                # must be absent.
3187                for tag in ('nillable', 'default', 'fixed', 'form', 'block', 'type'):
3188                    av = domutils.NodeAttribute(node, tag)
3189                    if av is not None:
3190                        raise pyxb.SchemaValidationError('element with "ref" cannot have "%s"' % (tag,))
3191                rv.__resolvableType = ElementDeclaration
3192                assert not xsd.nodeIsNamed(node.parentNode, 'schema')
3193        elif xsd.nodeIsNamed(node, 'any'):
3194            # 3.9.2 says use 3.10.2, which is Wildcard.
3195            rv.__term = Wildcard.CreateFromDOM(node=node)
3196        elif ModelGroup.IsGroupMemberNode(node):
3197            # Choice, sequence, and all inside a particle are explicit
3198            # groups (or a restriction of explicit group, in the case
3199            # of all)
3200            rv.__term = ModelGroup.CreateFromDOM(node, **kw)
3201        else:
3202            raise pyxb.LogicError('Unhandled node in Particle.CreateFromDOM: %s' % (node.toxml("utf-8"),))
3203
3204        if not rv.isResolved():
3205            rv._queueForResolution('creation')
3206        return rv
3207
3208    # bR:PRT
3209    def _bindingRequires_vx (self, include_lax):
3210        if not include_lax:
3211            return frozenset()
3212        return frozenset([ self.__term ])
3213
3214    # aFS:PRT
3215    def _adaptForScope (self, owner, ctd):
3216        rv = self
3217        assert isinstance(ctd, ComplexTypeDefinition)
3218        maybe_rv = self._clone(owner, ctd._objectOrigin())
3219        term = rv.__term._adaptForScope(maybe_rv, ctd)
3220        do_clone = (self._scope() != ctd) or (rv.__term != term)
3221        if  do_clone:
3222            rv = maybe_rv
3223            rv.__term = term
3224        return rv
3225
3226    def isAdaptable (self, ctd):
3227        """A particle has an unresolvable particle if it cannot be
3228        resolved, or if it has resolved to a term which is a model
3229        group that has an unresolvable particle.
3230        """
3231        if not self.isResolved():
3232            return False
3233        return self.term().isAdaptable(ctd)
3234
3235    def walkParticleTree (self, visit, arg):
3236        """The entry-point to walk a particle tree defining a content model.
3237
3238        See L{_ParticleTree_mixin._walkParticleTree}."""
3239        self._walkParticleTree(visit, arg)
3240
3241    def _walkParticleTree (self, visit, arg):
3242        visit(self, True, arg)
3243        self.__term._walkParticleTree(visit, arg)
3244        visit(self, False, arg)
3245
3246    @classmethod
3247    def IsTypedefNode (cls, node):
3248        return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence')
3249
3250    @classmethod
3251    def IsParticleNode (cls, node, *others):
3252        return xsd.nodeIsNamed(node, 'group', 'all', 'choice', 'sequence', 'element', 'any', *others)
3253
3254    def __str__ (self):
3255        #return 'PART{%s:%d,%s}' % (self.term(), self.minOccurs(), self.maxOccurs())
3256        return 'PART{%s:%d,%s}[%x]' % ('TERM', self.minOccurs(), self.maxOccurs(), id(self))
3257
3258
3259# 3.10.1
3260class Wildcard (_ParticleTree_mixin, _SchemaComponent_mixin, _Annotated_mixin):
3261    """An XMLSchema U{Wildcard<http://www.w3.org/TR/xmlschema-1/#cParticle>} component."""
3262
3263    NC_any = '##any'            #<<< The namespace constraint "##any"
3264    NC_not = '##other'          #<<< A flag indicating constraint "##other"
3265    NC_targetNamespace = '##targetNamespace'
3266    NC_local = '##local'
3267
3268    __namespaceConstraint = None
3269    def namespaceConstraint (self):
3270        """A constraint on the namespace for the wildcard.
3271
3272        Valid values are:
3273         - L{Wildcard.NC_any}
3274         - A tuple ( L{Wildcard.NC_not}, a_namespace )
3275         - set(of_namespaces)
3276
3277        Note that namespace are represented by
3278        L{Namespace<pyxb.namespace.Namespace>} instances, not the URIs that
3279        actually define a namespace.  Absence of a namespace is represented by
3280        C{None}, both in the "not" pair and in the set.
3281        """
3282        return self.__namespaceConstraint
3283
3284    @classmethod
3285    def IntensionalUnion (cls, constraints):
3286        """http://www.w3.org/TR/xmlschema-1/#cos-aw-union"""
3287        assert 0 < len(constraints)
3288        o1 = constraints.pop(0)
3289        while 0 < len(constraints):
3290            o2 = constraints.pop(0)
3291            # 1
3292            if (o1 == o2):
3293                continue
3294            # 2
3295            if (cls.NC_any == o1) or (cls.NC_any == o2):
3296                o1 = cls.NC_any
3297                continue
3298            # 3
3299            if isinstance(o1, set) and isinstance(o2, set):
3300                o1 = o1.union(o2)
3301                continue
3302            # 4
3303            if (isinstance(o1, tuple) and isinstance(o2, tuple)) and (o1[1] != o2[1]):
3304                o1 = ( cls.NC_not, None )
3305                continue
3306            # At this point, one must be a negated namespace and the
3307            # other a set.  Identify them.
3308            c_tuple = None
3309            c_set = None
3310            if isinstance(o1, tuple):
3311                assert isinstance(o2, set)
3312                c_tuple = o1
3313                c_set = o2
3314            else:
3315                assert isinstance(o1, set)
3316                assert isinstance(o2, tuple)
3317                c_tuple = o2
3318                c_set = o1
3319            negated_ns = c_tuple[1]
3320            if negated_ns is not None:
3321                # 5.1
3322                if (negated_ns in c_set) and (None in c_set):
3323                    o1 = cls.NC_any
3324                    continue
3325                # 5.2
3326                if negated_ns in c_set:
3327                    o1 = ( cls.NC_not, None )
3328                    continue
3329                # 5.3
3330                if None in c_set:
3331                    raise pyxb.SchemaValidationError('Union of wildcard namespace constraints not expressible')
3332                o1 = c_tuple
3333                continue
3334            # 6
3335            if None in c_set:
3336                o1 = cls.NC_any
3337            else:
3338                o1 = ( cls.NC_not, None )
3339        return o1
3340
3341    @classmethod
3342    def IntensionalIntersection (cls, constraints):
3343        """http://www.w3.org/TR/xmlschema-1/#cos-aw-intersect"""
3344        assert 0 < len(constraints)
3345        o1 = constraints.pop(0)
3346        while 0 < len(constraints):
3347            o2 = constraints.pop(0)
3348            # 1
3349            if (o1 == o2):
3350                continue
3351            # 2
3352            if (cls.NC_any == o1) or (cls.NC_any == o2):
3353                if cls.NC_any == o1:
3354                    o1 = o2
3355                continue
3356            # 4
3357            if isinstance(o1, set) and isinstance(o2, set):
3358                o1 = o1.intersection(o2)
3359                continue
3360            if isinstance(o1, tuple) and isinstance(o2, tuple):
3361                ns1 = o1[1]
3362                ns2 = o2[1]
3363                # 5
3364                if (ns1 is not None) and (ns2 is not None) and (ns1 != ns2):
3365                    raise pyxb.SchemaValidationError('Intersection of wildcard namespace constraints not expressible')
3366                # 6
3367                assert (ns1 is None) or (ns2 is None)
3368                if ns1 is None:
3369                    assert ns2 is not None
3370                    o1 = ( cls.NC_not, ns2 )
3371                else:
3372                    assert ns1 is not None
3373                    o1 = ( cls.NC_not, ns1 )
3374                continue
3375            # 3
3376            # At this point, one must be a negated namespace and the
3377            # other a set.  Identify them.
3378            c_tuple = None
3379            c_set = None
3380            if isinstance(o1, tuple):
3381                assert isinstance(o2, set)
3382                c_tuple = o1
3383                c_set = o2
3384            else:
3385                assert isinstance(o1, set)
3386                assert isinstance(o2, tuple)
3387                c_tuple = o2
3388                c_set = o1
3389            negated_ns = c_tuple[1]
3390            if negated_ns in c_set:
3391                c_set.remove(negated_ns)
3392            if None in c_set:
3393                c_set.remove(None)
3394            o1 = c_set
3395        return o1
3396
3397    PC_skip = 'skip'            #<<< No constraint is applied
3398    PC_lax = 'lax'              #<<< Validate against available uniquely determined declaration
3399    PC_strict = 'strict'        #<<< Validate against declaration or xsi:type which must be available
3400
3401    # One of PC_*
3402    __processContents = None
3403    def processContents (self):
3404        return self.__processContents
3405
3406    def hasWildcardElement (self):
3407        """Return True, since Wildcard components are wildcards."""
3408        return True
3409
3410    def __init__ (self, *args, **kw):
3411        assert 0 == len(args)
3412        super(Wildcard, self).__init__(*args, **kw)
3413        self.__namespaceConstraint = kw['namespace_constraint']
3414        self.__processContents = kw['process_contents']
3415
3416    def isAdaptable (self, ctd):
3417        return True
3418
3419    def _walkParticleTree (self, visit, arg):
3420        visit(self, None, arg)
3421
3422    # aFS:WC
3423    def _adaptForScope (self, owner, ctd):
3424        """Wildcards are scope-independent; return self"""
3425        return self
3426
3427    # CFD:Wildcard
3428    @classmethod
3429    def CreateFromDOM (cls, node, **kw):
3430        namespace_context = pyxb.namespace.NamespaceContext.GetNodeContext(node)
3431        assert xsd.nodeIsNamed(node, 'any', 'anyAttribute')
3432        nc = domutils.NodeAttribute(node, 'namespace')
3433        if nc is None:
3434            namespace_constraint = cls.NC_any
3435        else:
3436            if cls.NC_any == nc:
3437                namespace_constraint = cls.NC_any
3438            elif cls.NC_not == nc:
3439                namespace_constraint = ( cls.NC_not, namespace_context.targetNamespace() )
3440            else:
3441                ncs = set()
3442                for ns_uri in nc.split():
3443                    if cls.NC_local == ns_uri:
3444                        ncs.add(None)
3445                    elif cls.NC_targetNamespace == ns_uri:
3446                        ncs.add(namespace_context.targetNamespace())
3447                    else:
3448                        ncs.add(pyxb.namespace.NamespaceForURI(ns_uri, create_if_missing=True))
3449                namespace_constraint = frozenset(ncs)
3450
3451        pc = domutils.NodeAttribute(node, 'processContents')
3452        if pc is None:
3453            process_contents = cls.PC_strict
3454        else:
3455            if pc in [ cls.PC_skip, cls.PC_lax, cls.PC_strict ]:
3456                process_contents = pc
3457            else:
3458                raise pyxb.SchemaValidationError('illegal value "%s" for any processContents attribute' % (pc,))
3459
3460        rv = cls(node=node, namespace_constraint=namespace_constraint, process_contents=process_contents, **kw)
3461        rv._annotationFromDOM(node)
3462        return rv
3463
3464# 3.11.1
3465class IdentityConstraintDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin, pyxb.namespace.resolution._Resolvable_mixin):
3466    """An XMLSchema U{Identity Constraint Definition<http://www.w3.org/TR/xmlschema-1/#cIdentity-constraint_Definitions>} component."""
3467
3468    ICC_KEY = 0x01
3469    ICC_KEYREF = 0x02
3470    ICC_UNIQUE = 0x04
3471
3472    __identityConstraintCategory = None
3473    def identityConstraintCategory (self):
3474        return self.__identityConstraintCategory
3475
3476    __selector = None
3477    def selector (self):
3478        return self.__selector
3479
3480    __fields = None
3481    def fields (self):
3482        return self.__fields
3483
3484    __referencedKey = None
3485    __referAttribute = None
3486    __icc = None
3487
3488    __annotations = None
3489    def annotations (self):
3490        return self.__annotations
3491
3492    # CFD:ICD CFD:IdentityConstraintDefinition
3493    @classmethod
3494    def CreateFromDOM (cls, node, **kw):
3495        name = domutils.NodeAttribute(node, 'name')
3496        scope = kw['scope']
3497        assert _ScopedDeclaration_mixin.ScopeIsIndeterminate(scope) or _ScopedDeclaration_mixin.IsValidScope(scope)
3498        rv = cls(name=name, node=node, **kw)
3499
3500        kw.pop('node', None)
3501        kw['owner'] = rv
3502
3503        #self._annotationFromDOM(node)
3504        rv.__isResolved = True
3505        icc = None
3506        if xsd.nodeIsNamed(node, 'key'):
3507            icc = rv.ICC_KEY
3508        elif xsd.nodeIsNamed(node, 'keyref'):
3509            icc = rv.ICC_KEYREF
3510            rv.__referAttribute = domutils.NodeAttribute(node, 'refer')
3511            if rv.__referAttribute is None:
3512                raise pyxb.SchemaValidationError('Require refer attribute on keyref elements')
3513            rv.__isResolved = False
3514        elif xsd.nodeIsNamed(node, 'unique'):
3515            icc = rv.ICC_UNIQUE
3516        else:
3517            raise pyxb.LogicError('Unexpected identity constraint node %s' % (node.toxml("utf-8"),))
3518        rv.__icc = icc
3519
3520        cn = domutils.LocateUniqueChild(node, 'selector')
3521        rv.__selector = domutils.NodeAttribute(cn, 'xpath')
3522        if rv.__selector is None:
3523            raise pyxb.SchemaValidationError('selector element missing xpath attribute')
3524
3525        rv.__fields = []
3526        for cn in domutils.LocateMatchingChildren(node, 'field'):
3527            xp_attr = domutils.NodeAttribute(cn, 'xpath')
3528            if xp_attr is None:
3529                raise pyxb.SchemaValidationError('field element missing xpath attribute')
3530            rv.__fields.append(xp_attr)
3531
3532        rv._annotationFromDOM(node)
3533        rv.__annotations = []
3534        if rv.annotation() is not None:
3535            rv.__annotations.append(rv)
3536
3537        for cn in node.childNodes:
3538            if (Node.ELEMENT_NODE != cn.nodeType):
3539                continue
3540            an = None
3541            if xsd.nodeIsNamed(cn, 'selector', 'field'):
3542                an = domutils.LocateUniqueChild(cn, 'annotation')
3543            elif xsd.nodeIsNamed(cn, 'annotation'):
3544                an = cn
3545            if an is not None:
3546                rv.__annotations.append(Annotation.CreateFromDOM(an, **kw))
3547
3548        rv.__identityConstraintCategory = icc
3549        if rv.ICC_KEYREF != rv.__identityConstraintCategory:
3550            rv._namespaceContext().targetNamespace().addCategoryObject('identityConstraintDefinition', rv.name(), rv)
3551
3552        if not rv.isResolved():
3553            rv._queueForResolution('creation')
3554        return rv
3555
3556    __isResolved = False
3557    def isResolved (self):
3558        return self.__isResolved
3559
3560    # res:ICD res:IdentityConstraintDefinition
3561    def _resolve (self):
3562        if self.isResolved():
3563            return self
3564
3565        icc = self.__icc
3566        if self.ICC_KEYREF == icc:
3567            refer_en = self._namespaceContext().interpretQName(self.__referAttribute)
3568            refer = refer_en.identityConstraintDefinition()
3569            if refer is None:
3570                self._queueForResolution('Identity constraint definition %s cannot be found' % (refer_en,), depends_on=refer)
3571                return self
3572            self.__referencedKey = refer
3573        self.__isResolved = True
3574        return self
3575
3576    # bR:ICD
3577    def _bindingRequires_vx (self, include_lax):
3578        """Constraint definitions that are by reference require the referenced constraint."""
3579        rv = set()
3580        if include_lax and (self.__referencedKey is not None):
3581            rv.add(self.__referencedKey)
3582        return frozenset(rv)
3583
3584
3585
3586# 3.12.1
3587class NotationDeclaration (_SchemaComponent_mixin, _NamedComponent_mixin, _Annotated_mixin):
3588    """An XMLSchema U{Notation Declaration<http://www.w3.org/TR/xmlschema-1/#cNotation_Declarations>} component."""
3589    __systemIdentifier = None
3590    def systemIdentifier (self):
3591        return self.__systemIdentifier
3592
3593    __publicIdentifier = None
3594    def publicIdentifier (self):
3595        return self.__publicIdentifier
3596
3597    # CFD:ND CFD:NotationDeclaration
3598    @classmethod
3599    def CreateFromDOM (cls, node, **kw):
3600        name = domutils.NodeAttribute(node, 'name')
3601        rv = cls(name=name, node=node, **kw)
3602
3603        rv.__systemIdentifier = domutils.NodeAttribute(node, 'system')
3604        rv.__publicIdentifier = domutils.NodeAttribute(node, 'public')
3605
3606        rv._annotationFromDOM(node)
3607        return rv
3608
3609    # bR:ND
3610    def _bindingRequires_vx (self, include_lax):
3611        return frozenset()
3612
3613# 3.13.1
3614class Annotation (_SchemaComponent_mixin):
3615    """An XMLSchema U{Annotation<http://www.w3.org/TR/xmlschema-1/#cAnnotation>} component."""
3616
3617    __applicationInformation = None
3618    def applicationInformation (self):
3619        return self.__applicationInformation
3620
3621    __userInformation = None
3622    def userInformation (self):
3623        return self.__userInformation
3624
3625    # Define so superclasses can take keywords
3626    def __init__ (self, **kw):
3627        application_information = kw.pop('application_information', None)
3628        user_information = kw.pop('user_information', None)
3629        super(Annotation, self).__init__(**kw)
3630        if (user_information is not None) and (not isinstance(user_information, list)):
3631            user_information = [ six.text_type(user_information) ]
3632        if (application_information is not None) and (not isinstance(application_information, list)):
3633            application_information = [ six.text_type(application_information) ]
3634        self.__userInformation = user_information
3635        self.__applicationInformation = application_information
3636
3637    # @todo: what the hell is this?  From 3.13.2, I think it's a place
3638    # to stuff attributes from the annotation element, which makes
3639    # sense, as well as from the annotation's parent element, which
3640    # doesn't.  Apparently it's for attributes that don't belong to
3641    # the XMLSchema namespace; so maybe we're not supposed to add
3642    # those to the other components.  Note that these are attribute
3643    # information items, not attribute uses.
3644    __attributes = None
3645
3646    # CFD:Annotation
3647    @classmethod
3648    def CreateFromDOM (cls, node, **kw):
3649        rv = cls(node=node, **kw)
3650
3651        # @todo:: Scan for attributes in the node itself that do not
3652        # belong to the XMLSchema namespace.
3653
3654        # Node should be an XMLSchema annotation node
3655        assert xsd.nodeIsNamed(node, 'annotation')
3656        app_info = []
3657        user_info = []
3658        for cn in node.childNodes:
3659            if xsd.nodeIsNamed(cn, 'appinfo'):
3660                app_info.append(cn)
3661            elif xsd.nodeIsNamed(cn, 'documentation'):
3662                user_info.append(cn)
3663            else:
3664                pass
3665        if 0 < len(app_info):
3666            rv.__applicationInformation = app_info
3667        if 0 < len(user_info):
3668            rv.__userInformation = user_info
3669
3670        return rv
3671
3672    __RemoveMultiQuote_re = re.compile('""+')
3673    def asDocString (self):
3674        """Return the text in a form suitable for embedding in a
3675        triple-double-quoted docstring.
3676
3677        Any sequence of two or more double quotes is replaced by a sequence of
3678        single quotes that is the same length.  Following this, spaces are
3679        added at the start and the end as necessary to ensure a double quote
3680        does not appear in those positions."""
3681        rv = self.text()
3682        rv = self.__RemoveMultiQuote_re.sub(lambda _mo: "'" * (_mo.end(0) - _mo.start(0)), rv)
3683        if rv.startswith('"'):
3684            rv = ' ' + rv
3685        if rv.endswith('"'):
3686            rv = rv + ' '
3687        return rv
3688
3689    def text (self):
3690        if self.__userInformation is None:
3691            return ''
3692        text = []
3693        # Values in userInformation are DOM "documentation" elements.
3694        # We want their combined content.
3695        for dn in self.__userInformation:
3696            for cn in dn.childNodes:
3697                if Node.TEXT_NODE == cn.nodeType:
3698                    text.append(cn.data)
3699        return ''.join(text)
3700
3701    def __str__ (self):
3702        """Return the catenation of all user information elements in the
3703        annotation as a single unicode string.  Returns the empty string if
3704        there are no user information elements."""
3705        return self.text()
3706
3707# Section 3.14.
3708class SimpleTypeDefinition (_SchemaComponent_mixin, _NamedComponent_mixin, pyxb.namespace.resolution._Resolvable_mixin, _Annotated_mixin):
3709    """An XMLSchema U{Simple Type Definition<http://www.w3.org/TR/xmlschema-1/#Simple_Type_Definitions>} component."""
3710
3711    # Reference to the SimpleTypeDefinition on which this is based.
3712    # The value must be non-None except for the simple ur-type
3713    # definition.
3714    __baseTypeDefinition = None
3715    def baseTypeDefinition (self):
3716        return self.__baseTypeDefinition
3717
3718    __memberTypes = None
3719    __itemTypeExpandedName = None
3720    __baseExpandedName = None
3721    __memberTypesExpandedNames = None
3722    __localFacets = None
3723
3724    # A map from a subclass of facets.Facet to an instance of that class.
3725    # Presence of a facet class as a key in this map is the indicator that the
3726    # type definition and its subtypes are permitted to use the corresponding
3727    # facet.  All facets in force for this type are present in the map,
3728    # including those constraints inherited parent types.
3729    __facets = None
3730    def facets (self):
3731        assert (self.__facets is None) or isinstance(self.__facets, six.dictionary_type)
3732        return self.__facets
3733
3734    # The facets.FundamentalFacet instances that describe this type
3735    __fundamentalFacets = None
3736    def fundamentalFacets (self):
3737        """A frozenset of instances of facets.FundamentallFacet."""
3738        return self.__fundamentalFacets
3739
3740    STD_empty = 0          #<<< Marker indicating an empty set of STD forms
3741    STD_extension = 0x01   #<<< Representation for extension in a set of STD forms
3742    STD_list = 0x02        #<<< Representation for list in a set of STD forms
3743    STD_restriction = 0x04 #<<< Representation of restriction in a set of STD forms
3744    STD_union = 0x08       #<<< Representation of union in a set of STD forms
3745
3746    _STD_Map = { 'extension' : STD_extension
3747               , 'list' : STD_list
3748               , 'restriction' : STD_restriction
3749               , 'union' : STD_union }
3750
3751    # Bitmask defining the subset that comprises the final property
3752    __final = STD_empty
3753    @classmethod
3754    def _FinalToString (cls, final_value):
3755        """Convert a final value to a string."""
3756        tags = []
3757        if final_value & cls.STD_extension:
3758            tags.append('extension')
3759        if final_value & cls.STD_list:
3760            tags.append('list')
3761        if final_value & cls.STD_restriction:
3762            tags.append('restriction')
3763        if final_value & cls.STD_union:
3764            tags.append('union')
3765        return ' '.join(tags)
3766
3767    VARIETY_absent = 0x01       #<<< Only used for the ur-type
3768    VARIETY_atomic = 0x02       #<<< Use for types based on a primitive type
3769    VARIETY_list = 0x03         #<<< Use for lists of atomic-variety types
3770    VARIETY_union = 0x04        #<<< Use for types that aggregate other types
3771
3772    # Derivation alternative
3773    _DA_empty = 'none specified'
3774    _DA_restriction = 'restriction'
3775    _DA_list = 'list'
3776    _DA_union = 'union'
3777
3778    def _derivationAlternative (self):
3779        return self.__derivationAlternative
3780    __derivationAlternative = None
3781
3782    # Identify the sort of value collection this holds.  This field is
3783    # used to identify unresolved definitions.
3784    __variety = None
3785    def variety (self):
3786        return self.__variety
3787    @classmethod
3788    def VarietyToString (cls, variety):
3789        """Convert a variety value to a string."""
3790        if cls.VARIETY_absent == variety:
3791            return 'absent'
3792        if cls.VARIETY_atomic == variety:
3793            return 'atomic'
3794        if cls.VARIETY_list == variety:
3795            return 'list'
3796        if cls.VARIETY_union == variety:
3797            return 'union'
3798        return '?NoVariety?'
3799
3800    # For atomic variety only, the root (excepting ur-type) type.
3801    __primitiveTypeDefinition = None
3802    def primitiveTypeDefinition (self, throw_if_absent=True):
3803        if throw_if_absent:
3804            assert self.VARIETY_atomic == self.variety()
3805            if self.__primitiveTypeDefinition is None:
3806                raise pyxb.LogicError('Expected primitive type for %s in %s', self, self.targetNamespace())
3807        return self.__primitiveTypeDefinition
3808
3809    # For list variety only, the type of items in the list
3810    __itemTypeDefinition = None
3811    def itemTypeDefinition (self):
3812        assert self.VARIETY_list == self.variety()
3813        if self.__itemTypeDefinition is None:
3814            raise pyxb.LogicError('Expected item type')
3815        return self.__itemTypeDefinition
3816
3817    # For union variety only, the sequence of candidate members
3818    __memberTypeDefinitions = None
3819    def memberTypeDefinitions (self):
3820        assert self.VARIETY_union == self.variety()
3821        if self.__memberTypeDefinitions is None:
3822            raise pyxb.LogicError('Expected member types')
3823        return self.__memberTypeDefinitions
3824
3825    # bR:STD
3826    def _bindingRequires_vx (self, include_lax):
3827        """Implement base class method.
3828
3829        This STD depends on its baseTypeDefinition, unless its variety
3830        is absent.  Other dependencies are on item, primitive, or
3831        member type definitions."""
3832        type_definitions = set()
3833        if self != self.baseTypeDefinition():
3834            type_definitions.add(self.baseTypeDefinition())
3835        if self.VARIETY_absent == self.variety():
3836            type_definitions = set()
3837        elif self.VARIETY_atomic == self.variety():
3838            if self != self.primitiveTypeDefinition():
3839                type_definitions.add(self.primitiveTypeDefinition())
3840        elif self.VARIETY_list == self.variety():
3841            assert self != self.itemTypeDefinition()
3842            type_definitions.add(self.itemTypeDefinition())
3843        else:
3844            assert self.VARIETY_union == self.variety()
3845            assert self not in self.memberTypeDefinitions()
3846            type_definitions.update(self.memberTypeDefinitions())
3847        # NB: This type also depends on the value type definitions for
3848        # any facets that apply to it.  This fact only matters when
3849        # generating the datatypes_facets source.  That, and the fact
3850        # that there are dependency loops (e.g., integer requires a
3851        # nonNegativeInteger for its length facet) means we don't
3852        # bother adding in those.
3853        return frozenset(type_definitions)
3854
3855    # A non-property field that holds a reference to the DOM node from
3856    # which the type is defined.  The value is held only between the
3857    # point where the simple type definition instance is created until
3858    # the point it is resolved.
3859    __domNode = None
3860
3861    # Indicate that this instance was defined as a built-in rather
3862    # than from a DOM instance.
3863    __isBuiltin = False
3864
3865    # Allocate one of these.  Users should use one of the Create*
3866    # factory methods instead.
3867
3868    def __init__ (self, *args, **kw):
3869        super(SimpleTypeDefinition, self).__init__(*args, **kw)
3870        self.__variety = kw['variety']
3871
3872    def __setstate__ (self, state):
3873        """Extend base class unpickle support to retain link between
3874        this instance and the Python class that it describes.
3875
3876        This is because the pythonSupport value is a class reference,
3877        not an instance reference, so it wasn't deserialized, and its
3878        class member link was never set.
3879        """
3880        super_fn = getattr(super(SimpleTypeDefinition, self), '__setstate__', lambda _state: self.__dict__.update(_state))
3881        super_fn(state)
3882        if self.__pythonSupport is not None:
3883            self.__pythonSupport._SimpleTypeDefinition(self)
3884
3885    def __str__ (self):
3886        if self.name() is not None:
3887            elts = [ self.name(), ':' ]
3888        else:
3889            elts = [ '<anonymous>:' ]
3890        if self.VARIETY_absent == self.variety():
3891            elts.append('the ur-type')
3892        elif self.VARIETY_atomic == self.variety():
3893            elts.append('restriction of %s' % (self.baseTypeDefinition().name(),))
3894        elif self.VARIETY_list == self.variety():
3895            elts.append('list of %s' % (self.itemTypeDefinition().name(),))
3896        elif self.VARIETY_union == self.variety():
3897            elts.append('union of %s' % (six.u(' ').join([six.text_type(_mtd.name()) for _mtd in self.memberTypeDefinitions()],)))
3898        else:
3899            # Gets here if the type has not been resolved.
3900            elts.append('?')
3901            #raise pyxb.LogicError('Unexpected variety %s' % (self.variety(),))
3902        if self.__facets:
3903            felts = []
3904            for (k, v) in six.iteritems(self.__facets):
3905                if v is not None:
3906                    felts.append(six.text_type(v))
3907            elts.append(six.u('\n  %s') % (','.join(felts),))
3908        if self.__fundamentalFacets:
3909            elts.append("\n  ")
3910            elts.append(six.u(',').join( [six.text_type(_f) for _f in self.__fundamentalFacets ]))
3911        return 'STD[%s]' % (''.join(elts),)
3912
3913    def _updateFromOther_csc (self, other):
3914        """Override fields in this instance with those from the other.
3915
3916        This method is invoked only by Schema._addNamedComponent, and
3917        then only when a built-in type collides with a schema-defined
3918        type.  Material like facets is not (currently) held in the
3919        built-in copy, so the DOM information is copied over to the
3920        built-in STD, which is subsequently re-resolved.
3921
3922        Returns self.
3923        """
3924        assert self != other
3925        assert self.isNameEquivalent(other)
3926        super(SimpleTypeDefinition, self)._updateFromOther_csc(other)
3927
3928        # The other STD should be an unresolved schema-defined type.
3929        assert other.__baseTypeDefinition is None, 'Update from resolved STD %s' % (other,)
3930        assert other.__domNode is not None
3931        self.__domNode = other.__domNode
3932
3933        # Preserve the python support
3934        if other.__pythonSupport is not None:
3935            # @todo: ERROR multiple references
3936            self.__pythonSupport = other.__pythonSupport
3937
3938        # Mark this instance as unresolved so it is re-examined
3939        self.__variety = None
3940        return self
3941
3942    def isBuiltin (self):
3943        """Indicate whether this simple type is a built-in type."""
3944        return self.__isBuiltin
3945
3946    __SimpleUrTypeDefinition = None
3947    @classmethod
3948    def SimpleUrTypeDefinition (cls, schema=None, in_builtin_definition=False):
3949        """Create the SimpleTypeDefinition instance that approximates the simple ur-type.
3950
3951        See section 3.14.7."""
3952
3953        #if in_builtin_definition and (cls.__SimpleUrTypeDefinition is not None):
3954        #    raise pyxb.LogicError('Multiple definitions of SimpleUrType')
3955        if cls.__SimpleUrTypeDefinition is None:
3956            # Note: We use a singleton subclass
3957            assert schema is not None
3958
3959            ns_ctx = schema.targetNamespace().initialNamespaceContext()
3960
3961            kw = { 'name' : 'anySimpleType',
3962                   'schema' : schema,
3963                   'namespace_context' : ns_ctx,
3964                   'binding_namespace' : schema.targetNamespace(),
3965                   'variety' : cls.VARIETY_absent,
3966                   'scope' : _ScopedDeclaration_mixin.SCOPE_global }
3967            bi = _SimpleUrTypeDefinition(**kw)
3968            bi._setPythonSupport(datatypes.anySimpleType)
3969
3970            # The baseTypeDefinition is the ur-type.
3971            bi.__baseTypeDefinition = ComplexTypeDefinition.UrTypeDefinition()
3972            bi.__derivationAlternative = cls._DA_restriction
3973            # The simple ur-type has an absent variety, not an atomic
3974            # variety, so does not have a primitiveTypeDefinition
3975
3976            # No facets on the ur type
3977            bi.__facets = {}
3978            bi.__fundamentalFacets = frozenset()
3979
3980            bi.__resolveBuiltin()
3981
3982            cls.__SimpleUrTypeDefinition = bi
3983        return cls.__SimpleUrTypeDefinition
3984
3985    @classmethod
3986    def _CreateXMLInstance (cls, name, schema):
3987        """Create STD instances for built-in types.
3988
3989        For example, xml:space is a restriction of NCName; xml:lang is a union.
3990
3991        """
3992        from pyxb.binding import xml_
3993        kw = { 'schema' : schema,
3994               'binding_namespace' : schema.targetNamespace(),
3995               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
3996               'scope' : _ScopedDeclaration_mixin.SCOPE_global,
3997               'variety' : cls.VARIETY_atomic }
3998        if 'space' == name:
3999            bi = cls(**kw)
4000            bi.__derivationAlternative = cls._DA_restriction
4001            bi.__baseTypeDefinition = datatypes.NCName.SimpleTypeDefinition()
4002            bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition
4003            bi._setPythonSupport(xml_.STD_ANON_space)
4004            bi.setNameInBinding('STD_ANON_space')
4005        elif 'lang' == name:
4006            bi = cls(**kw)
4007            bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition()
4008            bi.__memberTypes = [ datatypes.language.SimpleTypeDefinition() ]
4009            bi.__derivationAlternative = cls._DA_union
4010            bi.__primitiveTypeDefinition = bi
4011            bi._setPythonSupport(xml_.STD_ANON_lang)
4012            bi.setNameInBinding('STD_ANON_lang')
4013        else:
4014            raise pyxb.IncompleteImplementationError('No implementation for xml:%s' % (name,))
4015        bi.__facets = { }
4016        for v in six.itervalues(bi.pythonSupport().__dict__):
4017            if isinstance(v, facets.ConstrainingFacet):
4018                bi.__facets[v.__class__] = v
4019        return bi
4020
4021    @classmethod
4022    def CreatePrimitiveInstance (cls, name, schema, python_support):
4023        """Create a primitive simple type in the target namespace.
4024
4025        This is mainly used to pre-load standard built-in primitive
4026        types, such as those defined by XMLSchema Datatypes.  You can
4027        use it for your own schemas as well, if you have special types
4028        that require explicit support to for Pythonic conversion.
4029
4030        All parameters are required and must be non-None.
4031        """
4032
4033        kw = { 'name' : name,
4034               'schema' : schema,
4035               'binding_namespace' : schema.targetNamespace(),
4036               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
4037               'scope' : _ScopedDeclaration_mixin.SCOPE_global,
4038               'variety' : cls.VARIETY_atomic }
4039
4040        bi = cls(**kw)
4041        bi._setPythonSupport(python_support)
4042
4043        # Primitive types are based on the ur-type, and have
4044        # themselves as their primitive type definition.
4045        bi.__derivationAlternative = cls._DA_restriction
4046        bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition()
4047        bi.__primitiveTypeDefinition = bi
4048
4049        # Primitive types are built-in
4050        bi.__resolveBuiltin()
4051        assert bi.isResolved()
4052        return bi
4053
4054    @classmethod
4055    def CreateDerivedInstance (cls, name, schema, parent_std, python_support):
4056        """Create a derived simple type in the target namespace.
4057
4058        This is used to pre-load standard built-in derived types.  You
4059        can use it for your own schemas as well, if you have special
4060        types that require explicit support to for Pythonic
4061        conversion.
4062        """
4063        assert parent_std
4064        assert parent_std.__variety in (cls.VARIETY_absent, cls.VARIETY_atomic)
4065        kw = { 'name' : name,
4066               'schema' : schema,
4067               'binding_namespace' : schema.targetNamespace(),
4068               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
4069               'scope' : _ScopedDeclaration_mixin.SCOPE_global,
4070               'variety' : parent_std.__variety }
4071
4072        bi = cls(**kw)
4073        bi._setPythonSupport(python_support)
4074
4075        # We were told the base type.  If this is atomic, we re-use
4076        # its primitive type.  Note that these all may be in different
4077        # namespaces.
4078        bi.__baseTypeDefinition = parent_std
4079        bi.__derivationAlternative = cls._DA_restriction
4080        if cls.VARIETY_atomic == bi.__variety:
4081            bi.__primitiveTypeDefinition = bi.__baseTypeDefinition.__primitiveTypeDefinition
4082
4083        # Derived types are built-in
4084        bi.__resolveBuiltin()
4085        return bi
4086
4087    @classmethod
4088    def CreateListInstance (cls, name, schema, item_std, python_support):
4089        """Create a list simple type in the target namespace.
4090
4091        This is used to preload standard built-in list types.  You can
4092        use it for your own schemas as well, if you have special types
4093        that require explicit support to for Pythonic conversion; but
4094        note that such support is identified by the item_std.
4095        """
4096
4097        kw = { 'name' : name,
4098               'schema' : schema,
4099               'binding_namespace' : schema.targetNamespace(),
4100               'namespace_context' : schema.targetNamespace().initialNamespaceContext(),
4101               'scope' : _ScopedDeclaration_mixin.SCOPE_global,
4102               'variety' : cls.VARIETY_list }
4103        bi = cls(**kw)
4104        bi._setPythonSupport(python_support)
4105
4106        # The base type is the ur-type.  We were given the item type.
4107        bi.__baseTypeDefinition = cls.SimpleUrTypeDefinition()
4108        assert item_std
4109        bi.__itemTypeDefinition = item_std
4110
4111        # List types are built-in
4112        bi.__resolveBuiltin()
4113        return bi
4114
4115    @classmethod
4116    def CreateUnionInstance (cls, name, schema, member_stds):
4117        """(Placeholder) Create a union simple type in the target namespace.
4118
4119        This function has not been implemented."""
4120        raise pyxb.IncompleteImplementationError('No support for built-in union types')
4121
4122    def __singleSimpleTypeChild (self, body, other_elts_ok=False):
4123        simple_type_child = None
4124        for cn in body.childNodes:
4125            if (Node.ELEMENT_NODE == cn.nodeType):
4126                if not xsd.nodeIsNamed(cn, 'simpleType'):
4127                    if other_elts_ok:
4128                        continue
4129                    raise pyxb.SchemaValidationError('Context requires element to be xs:simpleType')
4130                assert not simple_type_child
4131                simple_type_child = cn
4132        if simple_type_child is None:
4133            raise pyxb.SchemaValidationError('Content requires an xs:simpleType member (or a base attribute)')
4134        return simple_type_child
4135
4136    # The __initializeFrom* methods are responsible for identifying
4137    # the variety and the baseTypeDefinition.  The remainder of the
4138    # resolution is performed by the __completeResolution method.
4139    # Note that in some cases resolution might yet be premature, so
4140    # variety is not saved until it is complete.  All this stuff is
4141    # from section 3.14.2.
4142
4143    def __initializeFromList (self, body, **kw):
4144        self.__baseTypeDefinition = self.SimpleUrTypeDefinition()
4145        self.__itemTypeExpandedName = domutils.NodeAttributeQName(body, 'itemType')
4146        if self.__itemTypeExpandedName is None:
4147            # NOTE: The newly created anonymous item type will
4148            # not be resolved; the caller needs to handle
4149            # that.
4150            self.__itemTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body), **kw)
4151        return self.__completeResolution(body, self.VARIETY_list, self._DA_list)
4152
4153    def __initializeFromRestriction (self, body, **kw):
4154        if self.__baseTypeDefinition is None:
4155            self.__baseExpandedName = domutils.NodeAttributeQName(body, 'base')
4156            if self.__baseExpandedName is None:
4157                self.__baseTypeDefinition = self.CreateFromDOM(self.__singleSimpleTypeChild(body, other_elts_ok=True), **kw)
4158        return self.__completeResolution(body, None, self._DA_restriction)
4159
4160    __localMemberTypes = None
4161    def __initializeFromUnion (self, body, **kw):
4162        self.__baseTypeDefinition = self.SimpleUrTypeDefinition()
4163        mta = domutils.NodeAttribute(body, 'memberTypes')
4164        self.__memberTypesExpandedNames = None
4165        if mta is not None:
4166            nsc = pyxb.namespace.NamespaceContext.GetNodeContext(body)
4167            self.__memberTypesExpandedNames = [ nsc.interpretQName(_mten) for _mten in mta.split() ]
4168        if self.__localMemberTypes is None:
4169            self.__localMemberTypes = []
4170            for cn in body.childNodes:
4171                if (Node.ELEMENT_NODE == cn.nodeType) and xsd.nodeIsNamed(cn, 'simpleType'):
4172                    self.__localMemberTypes.append(self.CreateFromDOM(cn, **kw))
4173        return self.__completeResolution(body, self.VARIETY_union, self._DA_union)
4174
4175    def __resolveBuiltin (self):
4176        if self.hasPythonSupport():
4177            self.__facets = { }
4178            for v in six.itervalues(self.pythonSupport().__dict__):
4179                if isinstance(v, facets.ConstrainingFacet):
4180                    self.__facets[v.__class__] = v
4181                    if v.ownerTypeDefinition() is None:
4182                        v.setFromKeywords(_constructor=True, owner_type_definition=self)
4183        self.__isBuiltin = True
4184        return self
4185
4186    def __defineDefaultFacets (self, variety):
4187        """Create facets for varieties that can take facets that are undeclared.
4188
4189        This means unions, which per section 4.1.2.3 of
4190        http://www.w3.org/TR/xmlschema-2/ can have enumeration or
4191        pattern restrictions."""
4192        if self.VARIETY_union != variety:
4193            return self
4194        self.__facets.setdefault(facets.CF_pattern)
4195        self.__facets.setdefault(facets.CF_enumeration)
4196        return self
4197
4198    def __processHasFacetAndProperty (self, variety):
4199        """Identify the facets and properties for this stype.
4200
4201        This method simply identifies the facets that apply to this
4202        specific type, and records property values.  Only
4203        explicitly-associated facets and properties are stored; others
4204        from base types will also affect this type.  The information
4205        is taken from the applicationInformation children of the
4206        definition's annotation node, if any.  If there is no support
4207        for the XMLSchema_hasFacetAndProperty namespace, this is a
4208        no-op.
4209
4210        Upon return, self.__facets is a map from the class for an
4211        associated fact to None, and self.__fundamentalFacets is a
4212        frozenset of instances of FundamentalFacet.
4213
4214        The return value is self.
4215        """
4216        self.__facets = { }
4217        self.__fundamentalFacets = frozenset()
4218        if self.annotation() is None:
4219            return self.__defineDefaultFacets(variety)
4220        app_info = self.annotation().applicationInformation()
4221        if app_info is  None:
4222            return self.__defineDefaultFacets(variety)
4223        facet_map = { }
4224        fundamental_facets = set()
4225        seen_facets = set()
4226        for ai in app_info:
4227            for cn in ai.childNodes:
4228                if Node.ELEMENT_NODE != cn.nodeType:
4229                    continue
4230                if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasFacet'):
4231                    facet_name = domutils.NodeAttribute(cn, 'name')# , pyxb.namespace.XMLSchema_hfp)
4232                    if facet_name is None:
4233                        raise pyxb.SchemaValidationError('hasFacet missing name attribute in %s' % (cn,))
4234                    if facet_name in seen_facets:
4235                        raise pyxb.SchemaValidationError('Multiple hasFacet specifications for %s' % (facet_name,))
4236                    seen_facets.add(facet_name)
4237                    facet_class = facets.ConstrainingFacet.ClassForFacet(facet_name)
4238                    #facet_map[facet_class] = facet_class(base_type_definition=self)
4239                    facet_map[facet_class] = None
4240                if pyxb.namespace.XMLSchema_hfp.nodeIsNamed(cn, 'hasProperty'):
4241                    fundamental_facets.add(facets.FundamentalFacet.CreateFromDOM(cn, self))
4242        if 0 < len(facet_map):
4243            assert self.__baseTypeDefinition == self.SimpleUrTypeDefinition()
4244            self.__facets = facet_map
4245            assert isinstance(self.__facets, six.dictionary_type)
4246        if 0 < len(fundamental_facets):
4247            self.__fundamentalFacets = frozenset(fundamental_facets)
4248        return self
4249
4250    # NB: Must be done after resolution of the base type
4251    def __updateFacets (self, body):
4252
4253        # Create local list consisting of facet classes matched in children
4254        # and the map of keywords used to initialize the local instance.
4255
4256        local_facets = {}
4257        for fc in facets.Facet.Facets:
4258            children = domutils.LocateMatchingChildren(body, fc.Name())
4259            if 0 < len(children):
4260                fi = fc(base_type_definition=self.__baseTypeDefinition,
4261                        owner_type_definition=self)
4262                if isinstance(fi, facets._LateDatatype_mixin):
4263                    fi.bindValueDatatype(self)
4264                for cn in children:
4265                    kw = { 'annotation': domutils.LocateUniqueChild(cn, 'annotation') }
4266                    for ai in range(0, cn.attributes.length):
4267                        attr = cn.attributes.item(ai)
4268                        # Convert name from unicode to string
4269                        kw[six.text_type(attr.localName)] = attr.value
4270                    try:
4271                        fi.setFromKeywords(**kw)
4272                    except pyxb.PyXBException as e:
4273                        raise pyxb.SchemaValidationError('Error assigning facet %s in %s: %s' % (fc.Name(), self.expandedName(), e))
4274                local_facets[fc] = fi
4275        self.__localFacets = local_facets
4276
4277        # We want a map from the union of the facet classes from this STD up
4278        # through its baseTypeDefinition (if present).  Map elements should be
4279        # to None if the facet has not been constrained, or to the nearest
4280        # ConstrainingFacet instance if it is.  ConstrainingFacet instances
4281        # created for local constraints also need a pointer to the
4282        # corresponding facet from the ancestor type definition, because those
4283        # constraints also affect this type.
4284        base_facets = {}
4285
4286        # Built-ins didn't get their facets() setting configured, so use the
4287        # _FacetMap() instead.
4288        if self.__baseTypeDefinition.isBuiltin():
4289            pstd = self.__baseTypeDefinition.pythonSupport()
4290            if pstd != datatypes.anySimpleType:
4291                base_facets.update(pstd._FacetMap())
4292        elif self.__baseTypeDefinition.facets():
4293            assert isinstance(self.__baseTypeDefinition.facets(), six.dictionary_type)
4294            base_facets.update(self.__baseTypeDefinition.facets())
4295        base_facets.update(self.facets())
4296
4297        self.__facets = self.__localFacets
4298        for fc in six.iterkeys(base_facets):
4299            self.__facets.setdefault(fc, base_facets[fc])
4300        assert isinstance(self.__facets, six.dictionary_type)
4301
4302    def _createRestriction (self, owner, body):
4303        """Create a new simple type with this as its base.
4304
4305        The type is owned by the provided owner, and may have facet
4306        restrictions defined by the body.
4307        @param owner: the owner for the newly created type
4308        @type owner: L{ComplexTypeDefinition}
4309        @param body: the DOM node from which facet information will be extracted
4310        @type body: C{xml.dom.Node}
4311        @rtype: L{SimpleTypeDefinition}
4312        """
4313        std = SimpleTypeDefinition(owner=owner, namespace_context=owner._namespaceContext(), variety=None, scope=self._scope(), schema=owner._schema())
4314        std.__baseTypeDefinition = self
4315        return std.__completeResolution(body, None, self._DA_restriction)
4316
4317    # Complete the resolution of some variety of STD.  Note that the
4318    # variety is compounded by an alternative, since there is no
4319    # 'restriction' variety.
4320    def __completeResolution (self, body, variety, alternative):
4321        assert self.__variety is None
4322        if self.__baseTypeDefinition is None:
4323            assert self.__baseExpandedName is not None
4324            base_type = self.__baseExpandedName.typeDefinition()
4325            if not isinstance(base_type, SimpleTypeDefinition):
4326                raise pyxb.SchemaValidationError('Unable to locate base type %s' % (self.__baseExpandedName,))
4327            self.__baseTypeDefinition = base_type
4328        # If the base type exists but has not yet been resolved,
4329        # delay processing this type until the one it depends on
4330        # has been completed.
4331        assert self.__baseTypeDefinition != self
4332        if not self.__baseTypeDefinition.isResolved():
4333            self._queueForResolution('base type %s is not resolved' % (self.__baseTypeDefinition,), depends_on=self.__baseTypeDefinition)
4334            return self
4335        if variety is None:
4336            # 3.14.1 specifies that the variety is the variety of the base
4337            # type definition which, by the way, can't be the ur type.
4338            variety = self.__baseTypeDefinition.__variety
4339        assert variety is not None
4340
4341        if self.VARIETY_absent == variety:
4342            # The ur-type is always resolved.  So are restrictions of it,
4343            # which is how we might get here.
4344            pass
4345        elif self.VARIETY_atomic == variety:
4346            # Atomic types (and their restrictions) use the primitive
4347            # type, which is the highest type that is below the
4348            # ur-type (which is not atomic).
4349            ptd = self
4350            while isinstance(ptd, SimpleTypeDefinition) and (self.VARIETY_atomic == ptd.__baseTypeDefinition.variety()):
4351                ptd = ptd.__baseTypeDefinition
4352
4353            self.__primitiveTypeDefinition = ptd
4354        elif self.VARIETY_list == variety:
4355            if self._DA_list == alternative:
4356                if self.__itemTypeExpandedName is not None:
4357                    self.__itemTypeDefinition = self.__itemTypeExpandedName.typeDefinition()
4358                    if not isinstance(self.__itemTypeDefinition, SimpleTypeDefinition):
4359                        raise pyxb.SchemaValidationError('Unable to locate STD %s for items' % (self.__itemTypeExpandedName,))
4360            elif self._DA_restriction == alternative:
4361                self.__itemTypeDefinition = self.__baseTypeDefinition.__itemTypeDefinition
4362            else:
4363                raise pyxb.LogicError('completeResolution list variety with alternative %s' % (alternative,))
4364        elif self.VARIETY_union == variety:
4365            if self._DA_union == alternative:
4366                # First time we try to resolve, create the member type
4367                # definitions.  If something later prevents us from resolving
4368                # this type, we don't want to create them again, because we
4369                # might already have references to them.
4370                if self.__memberTypeDefinitions is None:
4371                    mtd = []
4372                    # If present, first extract names from memberTypes,
4373                    # and add each one to the list
4374                    if self.__memberTypesExpandedNames is not None:
4375                        for mn_en in self.__memberTypesExpandedNames:
4376                            # THROW if type has not been defined
4377                            std = mn_en.typeDefinition()
4378                            if std is None:
4379                                raise pyxb.SchemaValidationError('Unable to locate member type %s' % (mn_en,))
4380                            # Note: We do not need these to be resolved (here)
4381                            assert isinstance(std, SimpleTypeDefinition)
4382                            mtd.append(std)
4383                    # Now look for local type definitions
4384                    mtd.extend(self.__localMemberTypes)
4385                    self.__memberTypeDefinitions = mtd
4386                    assert None not in self.__memberTypeDefinitions
4387
4388                # Replace any member types that are themselves unions with the
4389                # members of those unions, in order.  Note that doing this
4390                # might indicate we can't resolve this type yet, which is why
4391                # we separated the member list creation and the substitution
4392                # phases
4393                mtd = []
4394                for mt in self.__memberTypeDefinitions:
4395                    assert isinstance(mt, SimpleTypeDefinition)
4396                    if not mt.isResolved():
4397                        self._queueForResolution('member type not resolved', depends_on=mt)
4398                        return self
4399                    if self.VARIETY_union == mt.variety():
4400                        mtd.extend(mt.memberTypeDefinitions())
4401                    else:
4402                        mtd.append(mt)
4403            elif self._DA_restriction == alternative:
4404                assert self.__baseTypeDefinition
4405                # Base type should have been resolved before we got here
4406                assert self.__baseTypeDefinition.isResolved()
4407                mtd = self.__baseTypeDefinition.__memberTypeDefinitions
4408                assert mtd is not None
4409            else:
4410                raise pyxb.LogicError('completeResolution union variety with alternative %s' % (alternative,))
4411            # Save a unique copy
4412            self.__memberTypeDefinitions = mtd[:]
4413        else:
4414            raise pyxb.LogicError('completeResolution with variety 0x%02x' % (variety,))
4415
4416        # Determine what facets, if any, apply to this type.  This
4417        # should only do something if this is a primitive type.
4418        self.__processHasFacetAndProperty(variety)
4419        try:
4420            pyxb.namespace.NamespaceContext.PushContext(pyxb.namespace.NamespaceContext.GetNodeContext(body))
4421            self.__updateFacets(body)
4422        finally:
4423            pyxb.namespace.NamespaceContext.PopContext()
4424
4425        self.__derivationAlternative = alternative
4426        self.__variety = variety
4427        self.__domNode = None
4428        return self
4429
4430    def isResolved (self):
4431        """Indicate whether this simple type is fully defined.
4432
4433        Type resolution for simple types means that the corresponding
4434        schema component fields have been set.  Specifically, that
4435        means variety, baseTypeDefinition, and the appropriate
4436        additional fields depending on variety.  See _resolve() for
4437        more information.
4438        """
4439        # Only unresolved nodes have an unset variety
4440        return (self.__variety is not None)
4441
4442    # STD:res
4443    def _resolve (self):
4444        """Attempt to resolve the type.
4445
4446        Type resolution for simple types means that the corresponding
4447        schema component fields have been set.  Specifically, that
4448        means variety, baseTypeDefinition, and the appropriate
4449        additional fields depending on variety.
4450
4451        All built-in STDs are resolved upon creation.  Schema-defined
4452        STDs are held unresolved until the schema has been completely
4453        read, so that references to later schema-defined STDs can be
4454        resolved.  Resolution is performed after the entire schema has
4455        been scanned and STD instances created for all
4456        topLevelSimpleTypes.
4457
4458        If a built-in STD is also defined in a schema (which it should
4459        be for XMLSchema), the built-in STD is kept, with the
4460        schema-related information copied over from the matching
4461        schema-defined STD.  The former then replaces the latter in
4462        the list of STDs to be resolved.
4463
4464        Types defined by restriction have the same variety as the type
4465        they restrict.  If a simple type restriction depends on an
4466        unresolved type, this method simply queues it for resolution
4467        in a later pass and returns.
4468        """
4469        if self.__variety is not None:
4470            return self
4471        assert self.__domNode
4472        node = self.__domNode
4473
4474        kw = { 'owner' : self
4475              , 'schema' : self._schema() }
4476
4477        bad_instance = False
4478        # The guts of the node should be exactly one instance of
4479        # exactly one of these three types.
4480        candidate = domutils.LocateUniqueChild(node, 'list')
4481        if candidate:
4482            self.__initializeFromList(candidate, **kw)
4483
4484        candidate = domutils.LocateUniqueChild(node, 'restriction')
4485        if candidate:
4486            if self.__variety is None:
4487                self.__initializeFromRestriction(candidate, **kw)
4488            else:
4489                bad_instance = True
4490
4491        candidate = domutils.LocateUniqueChild(node, 'union')
4492        if candidate:
4493            if self.__variety is None:
4494                self.__initializeFromUnion(candidate, **kw)
4495            else:
4496                bad_instance = True
4497
4498        if self.__baseTypeDefinition is None:
4499            raise pyxb.SchemaValidationError('xs:simpleType must have list, union, or restriction as child')
4500
4501        if self._schema() is not None:
4502            self.__final = self._schema().finalForNode(node, self._STD_Map)
4503
4504        # It is NOT an error to fail to resolve the type.
4505        if bad_instance:
4506            raise pyxb.SchemaValidationError('Expected exactly one of list, restriction, union as child of simpleType')
4507
4508        return self
4509
4510    # CFD:STD CFD:SimpleTypeDefinition
4511    @classmethod
4512    def CreateFromDOM (cls, node, **kw):
4513        # Node should be an XMLSchema simpleType node
4514        assert xsd.nodeIsNamed(node, 'simpleType')
4515
4516        name = domutils.NodeAttribute(node, 'name')
4517
4518        rv = cls(name=name, node=node, variety=None, **kw)
4519        rv._annotationFromDOM(node)
4520
4521        # Creation does not attempt to do resolution.  Queue up the newly created
4522        # whatsis so we can resolve it after everything's been read in.
4523        rv.__domNode = node
4524        rv._queueForResolution('creation')
4525
4526        return rv
4527
4528    # pythonSupport is None, or a subclass of datatypes.simpleTypeDefinition.
4529    # When set, this simple type definition instance must be uniquely
4530    # associated with the python support type.
4531    __pythonSupport = None
4532
4533    def _setPythonSupport (self, python_support):
4534        # Includes check that python_support is not None
4535        assert issubclass(python_support, basis.simpleTypeDefinition)
4536        # Can't share support instances
4537        self.__pythonSupport = python_support
4538        self.__pythonSupport._SimpleTypeDefinition(self)
4539        if self.nameInBinding() is None:
4540            self.setNameInBinding(self.__pythonSupport.__name__)
4541        return self.__pythonSupport
4542
4543    def hasPythonSupport (self):
4544        return self.__pythonSupport is not None
4545
4546    def pythonSupport (self):
4547        if self.__pythonSupport is None:
4548            raise pyxb.LogicError('%s: No support defined' % (self.name(),))
4549        return self.__pythonSupport
4550
4551    def stringToPython (self, string):
4552        return self.pythonSupport().stringToPython(string)
4553
4554    def pythonToString (self, value):
4555        return self.pythonSupport().pythonToString(value)
4556
4557class _SimpleUrTypeDefinition (SimpleTypeDefinition, _Singleton_mixin):
4558    """Subclass ensures there is only one simple ur-type."""
4559    pass
4560
4561class _ImportElementInformationItem (_Annotated_mixin):
4562    """Data associated with an
4563    U{import<http://www.w3.org/TR/xmlschema-1/#composition-schemaImport>}
4564    statement within a schema."""
4565
4566    def id (self):
4567        """The value of the C{id} attribute from the import statement."""
4568        return self.__id
4569    __id = None
4570
4571    def namespace (self):
4572        """The L{pyxb.namespace.Namespace} instance corresponding to the value
4573        of the C{namespace} attribute from the import statement."""
4574        return self.__namespace
4575    __namespace = None
4576
4577    def schemaLocation (self):
4578        """The value of the C{schemaLocation} attribute from the import
4579        statement, normalized relative to the location of the importing
4580        schema."""
4581        return self.__schemaLocation
4582    __schemaLocation = None
4583
4584    def prefix (self):
4585        """The prefix from a namespace declaration for L{namespace} that was
4586        active in the context of the import element, or C{None} if there was
4587        no relevant namespace declaration in scope at that point.
4588
4589        This is propagated to be used as the default prefix for the
4590        corresponding namespace if no prefix had been assigned.
4591        """
4592        return self.__prefix
4593    __prefix = None
4594
4595    def schema (self):
4596        """The L{Schema} instance corresponding to the imported schema, if
4597        available.
4598
4599        Normally C{import} statements will be fulfilled by loading components
4600        from a L{namespace archive<pyxb.namespace.NamespaceArchive>} in which
4601        the corresponding namespace is marked as public.  Where there are
4602        cycles in the namespace dependency graph, or the schema for a
4603        namespace are associated with a restricted profile of another
4604        namespace, there may be no such archive and instead the components are
4605        obtained using this schema."""
4606        return self.__schema
4607    __schema = None
4608
4609    def __init__ (self, importing_schema, node, **kw):
4610        """Gather the information relative to an C{import} statement.
4611
4612        If the imported namespace can be loaded from an archive, the
4613        C{schemaLocation} attribute is ignored.  Otherwise, it attempts to
4614        retrieve and parse the corresponding schema (if this has not already
4615        been done).
4616
4617        @param importing_schema: The L{Schema} instance in which the import
4618        was found.
4619        @param node: The C{xml.dom.DOM} node incorporating the schema
4620        information.
4621
4622        @raise Exception: Any exception raised when attempting to retrieve and
4623        parse data from the schema location.
4624        """
4625
4626        super(_ImportElementInformationItem, self).__init__(**kw)
4627        uri = domutils.NodeAttribute(node, 'namespace')
4628        if uri is None:
4629            raise pyxb.IncompleteImplementationError('import statements without namespace not supported')
4630        schema_location = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), importing_schema.location())
4631        self.__schemaLocation = schema_location
4632        ns = self.__namespace = pyxb.namespace.NamespaceForURI(uri, create_if_missing=True)
4633        need_schema = ns.isImportAugmentable()
4634        if not need_schema:
4635            # Discard location if we expect to be able to learn about this
4636            # namespace from an archive or a built-in description
4637            self.__schemaLocation = None
4638
4639        ns_ctx = pyxb.namespace.NamespaceContext.GetNodeContext(node)
4640        if self.schemaLocation() is not None:
4641            # @todo: NOTICE
4642            (has_schema, schema_instance) = self.__namespace.lookupSchemaByLocation(schema_location)
4643            if not has_schema:
4644                ckw = { 'absolute_schema_location' : schema_location,
4645                        'generation_uid' : importing_schema.generationUID(),
4646                        'uri_content_archive_directory' : importing_schema._uriContentArchiveDirectory(),
4647                        }
4648                try:
4649                    schema_instance = Schema.CreateFromLocation(**ckw)
4650                except Exception:
4651                    _log.exception('Import %s cannot read schema location %s (%s)', ns, self.__schemaLocation, schema_location)
4652                    raise
4653            self.__schema = schema_instance
4654        elif need_schema:
4655            _log.warning('No information available on imported namespace %s', uri)
4656
4657        # If we think we found a schema, make sure it's in the right
4658        # namespace.
4659        if self.__schema is not None:
4660            if ns != self.__schema.targetNamespace():
4661                raise pyxb.SchemaValidationError('Import expected namespace %s but got %s' % (ns, self.__schema.targetNamespace()))
4662
4663        self.__prefix = ns_ctx.prefixForNamespace(self.namespace())
4664
4665        self._annotationFromDOM(node)
4666
4667class Schema (_SchemaComponent_mixin):
4668    """An XMLSchema U{Schema<http://www.w3.org/TR/xmlschema-1/#Schemas>}."""
4669
4670    def __getstate__ (self):
4671        raise pyxb.LogicError('Attempt to serialize Schema instance')
4672
4673    # List of annotations
4674    __annotations = None
4675
4676    # True when we have started seeing elements, attributes, or
4677    # notations.
4678    __pastProlog = False
4679
4680    def location (self):
4681        """URI or path to where the schema can be found.
4682
4683        For schema created by a user, the location should be provided to the
4684        constructor using the C{schema_location} keyword.  In the case of
4685        imported or included schema, the including schema's location is used
4686        as the base URI for determining the absolute URI of the included
4687        schema from its (possibly relative) location value.  For files,
4688        the scheme and authority portions are generally absent, as is often
4689        the abs_path part."""
4690        return self.__location
4691    __location = None
4692
4693    def locationTag (self):
4694        return self.__locationTag
4695    __locationTag = None
4696
4697    def signature (self):
4698        return self.__signature
4699    __signature = None
4700
4701    def generationUID (self):
4702        return self.__generationUID
4703    __generationUID = None
4704
4705    def originRecord (self):
4706        return self.__originRecord
4707    __originRecord = None
4708
4709    def targetNamespace (self):
4710        """The targetNamespace of a componen.
4711
4712        This is None, or a reference to a Namespace in which the
4713        component is declared (either as a global or local to one of
4714        the namespace's complex type definitions).  This is immutable
4715        after creation.
4716        """
4717        return self.__targetNamespace
4718    __targetNamespace = None
4719
4720    def defaultNamespace (self):
4721        """Default namespace of the schema.
4722
4723        Will be None unless the schema has an 'xmlns' attribute.  The
4724        value must currently be provided as a keyword parameter to the
4725        constructor.  """
4726        return self.__defaultNamespace
4727    __defaultNamespace = None
4728
4729    def referencedNamespaces (self):
4730        return self.__referencedNamespaces
4731    __referencedNamespaces = None
4732
4733    __namespaceData = None
4734
4735    def importEIIs (self):
4736        return self.__importEIIs
4737    __importEIIs = None
4738
4739    def importedSchema (self):
4740        return self.__importedSchema
4741    __importedSchema = None
4742    def includedSchema (self):
4743        return self.__includedSchema
4744    __includedSchema = None
4745
4746    _QUALIFIED = "qualified"
4747    _UNQUALIFIED = "unqualified"
4748
4749    # Default values for standard recognized schema attributes
4750    __attributeMap = { pyxb.namespace.ExpandedName(None, 'attributeFormDefault') : _UNQUALIFIED
4751                     , pyxb.namespace.ExpandedName(None, 'elementFormDefault') : _UNQUALIFIED
4752                     , pyxb.namespace.ExpandedName(None, 'blockDefault') : ''
4753                     , pyxb.namespace.ExpandedName(None, 'finalDefault') : ''
4754                     , pyxb.namespace.ExpandedName(None, 'id') : None
4755                     , pyxb.namespace.ExpandedName(None, 'targetNamespace') : None
4756                     , pyxb.namespace.ExpandedName(None, 'version') : None
4757                     , pyxb.namespace.XML.createExpandedName('lang') : None
4758                     }
4759
4760    def _setAttributeFromDOM (self, attr):
4761        """Override the schema attribute with the given DOM value."""
4762        self.__attributeMap[pyxb.namespace.ExpandedName(attr.name)] = attr.nodeValue
4763        return self
4764
4765    def _setAttributesFromMap (self, attr_map):
4766        """Override the schema attributes with values from the given map."""
4767        self.__attributeMap.update(attr_map)
4768        return self
4769
4770    def schemaHasAttribute (self, attr_name):
4771        """Return True iff the schema has an attribute with the given (nc)name."""
4772        if isinstance(attr_name, six.string_types):
4773            attr_name = pyxb.namespace.ExpandedName(None, attr_name)
4774        return attr_name in self.__attributeMap
4775
4776    def schemaAttribute (self, attr_name):
4777        """Return the schema attribute value associated with the given (nc)name.
4778
4779        @param attr_name: local name for the attribute in the schema element.
4780        @return: the value of the corresponding attribute, or C{None} if it
4781        has not been defined and has no default.
4782        @raise KeyError: C{attr_name} is not a valid attribute for a C{schema} element.
4783        """
4784        if isinstance(attr_name, six.string_types):
4785            attr_name = pyxb.namespace.ExpandedName(None, attr_name)
4786        return self.__attributeMap[attr_name]
4787
4788    __SchemaCategories = ( 'typeDefinition', 'attributeGroupDefinition', 'modelGroupDefinition',
4789                           'attributeDeclaration', 'elementDeclaration', 'notationDeclaration',
4790                           'identityConstraintDefinition' )
4791
4792    def _uriContentArchiveDirectory (self):
4793        return self.__uriContentArchiveDirectory
4794    __uriContentArchiveDirectory = None
4795
4796    def __init__ (self, *args, **kw):
4797        # Force resolution of available namespaces if not already done
4798        if not kw.get('_bypass_preload', False):
4799            pyxb.namespace.archive.NamespaceArchive.PreLoadArchives()
4800
4801        assert 'schema' not in kw
4802        self.__uriContentArchiveDirectory = kw.get('uri_content_archive_directory')
4803        self.__location = kw.get('schema_location')
4804        if self.__location is not None:
4805            schema_path = self.__location
4806            if 0 <= schema_path.find(':'):
4807                schema_path = urlparse.urlparse(schema_path)[2] # .path
4808            self.__locationTag = os.path.split(schema_path)[1].split('.')[0]
4809
4810        self.__generationUID = kw.get('generation_uid')
4811        if self.__generationUID is None:
4812            _log.warning('No generationUID provided')
4813            self.__generationUID = pyxb.utils.utility.UniqueIdentifier()
4814
4815        self.__signature = kw.get('schema_signature')
4816
4817        super(Schema, self).__init__(*args, **kw)
4818        self.__importEIIs = set()
4819        self.__includedSchema = set()
4820        self.__importedSchema = set()
4821        self.__targetNamespace = self._namespaceContext().targetNamespace()
4822        if not isinstance(self.__targetNamespace, pyxb.namespace.Namespace):
4823            raise pyxb.LogicError('Schema constructor requires valid Namespace instance as target_namespace')
4824
4825        # NB: This will raise pyxb.SchemaUniquenessError if it appears this
4826        # schema has already been incorporated into the target namespace.
4827        self.__originRecord = self.__targetNamespace.addSchema(self)
4828
4829        self.__targetNamespace.configureCategories(self.__SchemaCategories)
4830        if self.__defaultNamespace is not None:
4831            self.__defaultNamespace.configureCategories(self.__SchemaCategories)
4832
4833        self.__attributeMap = self.__attributeMap.copy()
4834        self.__annotations = []
4835        # @todo: This isn't right if namespaces are introduced deeper in the document
4836        self.__referencedNamespaces = list(six.itervalues(self._namespaceContext().inScopeNamespaces()))
4837
4838    __TopLevelComponentMap = {
4839        'element' : ElementDeclaration,
4840        'attribute' : AttributeDeclaration,
4841        'notation' : NotationDeclaration,
4842        'simpleType' : SimpleTypeDefinition,
4843        'complexType' : ComplexTypeDefinition,
4844        'group' : ModelGroupDefinition,
4845        'attributeGroup' : AttributeGroupDefinition
4846        }
4847
4848    @classmethod
4849    def CreateFromDocument (cls, xmls, **kw):
4850        if not ('schema_signature' in kw):
4851            kw['schema_signature'] = pyxb.utils.utility.HashForText(xmls)
4852        return cls.CreateFromDOM(domutils.StringToDOM(xmls, **kw), **kw)
4853
4854    @classmethod
4855    def CreateFromLocation (cls, **kw):
4856        """Create a schema from a schema location.
4857
4858        Reads an XML document from the schema location and creates a schema
4859        using it.  All keyword parameters are passed to L{CreateFromDOM}.
4860
4861        @keyword schema_location: A file path or a URI.  If this is a relative
4862        URI and C{parent_uri} is present, the actual location will be
4863        L{normallzed<pyxb.utils.utility.NormalizeLocation>}.
4864        @keyword parent_uri: The context within which schema_location will be
4865        normalized, if necessary.
4866        @keyword absolute_schema_location: A file path or URI.  This value is
4867        not normalized, and supersedes C{schema_location}.
4868        """
4869        schema_location = kw.pop('absolute_schema_location', pyxb.utils.utility.NormalizeLocation(kw.get('schema_location'), kw.get('parent_uri'), kw.get('prefix_map')))
4870        kw['location_base'] = kw['schema_location'] = schema_location
4871        assert isinstance(schema_location, six.string_types), 'Unexpected value %s type %s for schema_location' % (schema_location, type(schema_location))
4872        uri_content_archive_directory = kw.get('uri_content_archive_directory')
4873        return cls.CreateFromDocument(pyxb.utils.utility.DataFromURI(schema_location, archive_directory=uri_content_archive_directory), **kw)
4874
4875    @classmethod
4876    def CreateFromStream (cls, stream, **kw):
4877        return cls.CreateFromDocument(stream.read(), **kw)
4878
4879    @classmethod
4880    def CreateFromDOM (cls, node, namespace_context=None, schema_location=None, schema_signature=None, generation_uid=None, **kw):
4881        """Take the root element of the document, and scan its attributes under
4882        the assumption it is an XMLSchema schema element.  That means
4883        recognize namespace declarations and process them.  Also look for
4884        and set the default namespace.  All other attributes are passed up
4885        to the parent class for storage."""
4886
4887        # Get the context of any schema that is including (not importing) this
4888        # one.
4889        including_context = kw.get('including_context')
4890
4891        root_node = node
4892        if Node.DOCUMENT_NODE == node.nodeType:
4893            root_node = root_node.documentElement
4894        if Node.ELEMENT_NODE != root_node.nodeType:
4895            raise pyxb.LogicError('Must be given a DOM node of type ELEMENT')
4896
4897        assert (namespace_context is None) or isinstance(namespace_context, pyxb.namespace.NamespaceContext)
4898        ns_ctx = pyxb.namespace.NamespaceContext.GetNodeContext(root_node,
4899                                                                           parent_context=namespace_context,
4900                                                                           including_context=including_context)
4901
4902        tns = ns_ctx.targetNamespace()
4903        if tns is None:
4904            raise pyxb.SchemaValidationError('No targetNamespace associated with content (not a schema?)')
4905        schema = cls(namespace_context=ns_ctx, schema_location=schema_location, schema_signature=schema_signature, generation_uid=generation_uid, **kw)
4906        schema.__namespaceData = ns_ctx
4907
4908        if schema.targetNamespace() != ns_ctx.targetNamespace():
4909            raise pyxb.SchemaValidationError('targetNamespace %s conflicts with %s' % (schema.targetNamespace(), ns_ctx.targetNamespace()))
4910
4911        # Update the attribute map
4912        for ai in range(root_node.attributes.length):
4913            schema._setAttributeFromDOM(root_node.attributes.item(ai))
4914
4915        # Verify that the root node is an XML schema element
4916        if not xsd.nodeIsNamed(root_node, 'schema'):
4917            raise pyxb.SchemaValidationError('Root node %s of document is not an XML schema element' % (root_node.nodeName,))
4918
4919        for cn in root_node.childNodes:
4920            if Node.ELEMENT_NODE == cn.nodeType:
4921                rv = schema.__processTopLevelNode(cn)
4922                if rv is None:
4923                    _log.info('Unrecognized: %s %s', cn.nodeName, cn.toxml("utf-8"))
4924            elif Node.TEXT_NODE == cn.nodeType:
4925                # Non-element content really should just be whitespace.
4926                # If something else is seen, print it for inspection.
4927                text = cn.data.strip()
4928                if text:
4929                    _log.info('Ignored text: %s', text)
4930            elif Node.COMMENT_NODE == cn.nodeType:
4931                pass
4932            else:
4933                # ATTRIBUTE_NODE
4934                # CDATA_SECTION_NODE
4935                # ENTITY_NODE
4936                # PROCESSING_INSTRUCTION
4937                # DOCUMENT_NODE
4938                # DOCUMENT_TYPE_NODE
4939                # NOTATION_NODE
4940                _log.info('Ignoring non-element: %s', cn)
4941
4942        # Do not perform resolution yet: we may be done with this schema, but
4943        # the namespace may incorporate additional ones, and we can't resolve
4944        # until everything's present.
4945        return schema
4946
4947    _SA_All = '#all'
4948
4949    def __ebvForNode (self, attr, dom_node, candidate_map):
4950        ebv = domutils.NodeAttribute(dom_node, attr)
4951        if ebv is None:
4952            ebv = self.schemaAttribute('%sDefault' % (attr,))
4953        rv = 0
4954        if ebv == self._SA_All:
4955            for v in six.itervalues(candidate_map):
4956                rv += v
4957        else:
4958            for candidate in ebv.split():
4959                rv += candidate_map.get(candidate, 0)
4960        return rv
4961
4962    def blockForNode (self, dom_node, candidate_map):
4963        """Return a bit mask indicating a set of options read from the node's "block" attribute or the schema's "blockDefault" attribute.
4964
4965        A value of '#all' means enable every options; otherwise, the attribute
4966        value should be a list of tokens, for which the corresponding value
4967        will be added to the return value.
4968
4969        @param dom_node: the node from which the "block" attribute will be retrieved
4970        @type dom_node: C{xml.dom.Node}
4971        @param candidate_map: map from strings to bitmask values
4972        """
4973        return self.__ebvForNode('block', dom_node, candidate_map)
4974
4975    def finalForNode (self, dom_node, candidate_map):
4976        """Return a bit mask indicating a set of options read from the node's
4977        "final" attribute or the schema's "finalDefault" attribute.
4978
4979        A value of '#all' means enable every options; otherwise, the attribute
4980        value should be a list of tokens, for which the corresponding value
4981        will be added to the return value.
4982
4983        @param dom_node: the node from which the "final" attribute will be retrieved
4984        @type dom_node: C{xml.dom.Node}
4985        @param candidate_map: map from strings to bitmask values
4986        """
4987        return self.__ebvForNode('final', dom_node, candidate_map)
4988
4989    def targetNamespaceForNode (self, dom_node, declaration_type):
4990        """Determine the target namespace for a local attribute or element declaration.
4991
4992        Look at the node's C{form} attribute, or if none the schema's
4993        C{attributeFormDefault} or C{elementFormDefault} value.  If the
4994        resulting value is C{"qualified"} and the parent schema has a
4995        non-absent target namespace, return it to use as the declaration
4996        target namespace.  Otherwise, return None to indicate that the
4997        declaration has no namespace.
4998
4999        @param dom_node: The node defining an element or attribute declaration
5000        @param declaration_type: Either L{AttributeDeclaration} or L{ElementDeclaration}
5001        @return: L{pyxb.namespace.Namespace} or None
5002        """
5003
5004        form_type = domutils.NodeAttribute(dom_node, 'form')
5005        if form_type is None:
5006            if declaration_type == ElementDeclaration:
5007                form_type = self.schemaAttribute('elementFormDefault')
5008            elif declaration_type == AttributeDeclaration:
5009                form_type = self.schemaAttribute('attributeFormDefault')
5010            else:
5011                raise pyxb.LogicError('Expected ElementDeclaration or AttributeDeclaration: got %s' % (declaration_type,))
5012        tns = None
5013        if (self._QUALIFIED == form_type):
5014            tns = self.targetNamespace()
5015            if tns.isAbsentNamespace():
5016                tns = None
5017        else:
5018            if (self._UNQUALIFIED != form_type):
5019                raise pyxb.SchemaValidationError('Form type neither %s nor %s' % (self._QUALIFIED, self._UNQUALIFIED))
5020        return tns
5021
5022    def __requireInProlog (self, node_name):
5023        """Throw a SchemaValidationException referencing the given
5024        node if we have passed the sequence point representing the end
5025        of prolog elements."""
5026
5027        if self.__pastProlog:
5028            raise pyxb.SchemaValidationError('Unexpected node %s after prolog' % (node_name,))
5029
5030    def __processInclude (self, node):
5031        self.__requireInProlog(node.nodeName)
5032        # See section 4.2.1 of Structures.
5033        abs_uri = pyxb.utils.utility.NormalizeLocation(domutils.NodeAttribute(node, 'schemaLocation'), self.__location)
5034        (has_schema, schema_instance) = self.targetNamespace().lookupSchemaByLocation(abs_uri)
5035        if not has_schema:
5036            kw = { 'absolute_schema_location': abs_uri,
5037                   'including_context': self.__namespaceData,
5038                   'generation_uid': self.generationUID(),
5039                   'uri_content_archive_directory': self._uriContentArchiveDirectory(),
5040                 }
5041            try:
5042                schema_instance = self.CreateFromLocation(**kw)
5043            except pyxb.SchemaUniquenessError as e:
5044                _log.warning('Skipping apparent redundant inclusion of %s defining %s (hash matches %s)', e.schemaLocation(), e.namespace(), e.existingSchema().location())
5045            except Exception as e:
5046                _log.exception('INCLUDE %s caught', abs_uri)
5047                raise
5048        if schema_instance:
5049            if self.targetNamespace() != schema_instance.targetNamespace():
5050                raise pyxb.SchemaValidationError('Included namespace %s not consistent with including namespace %s' % (schema_instance.targetNamespace(), self.targetNamespace()))
5051            self.__includedSchema.add(schema_instance)
5052        return node
5053
5054    def __processImport (self, node):
5055        """Process an import directive.
5056
5057        This attempts to locate schema (named entity) information for
5058        a namespace that is referenced by this schema.
5059        """
5060
5061        self.__requireInProlog(node.nodeName)
5062        import_eii = _ImportElementInformationItem(self, node)
5063        if import_eii.schema() is not None:
5064            self.__importedSchema.add(import_eii.schema())
5065        self.targetNamespace().importNamespace(import_eii.namespace())
5066        ins = import_eii.namespace()
5067        if ins.prefix() is None:
5068            ins.setPrefix(import_eii.prefix())
5069        self.__importEIIs.add(import_eii)
5070        return node
5071
5072    def __processRedefine (self, node):
5073        self.__requireInProlog(node.nodeName)
5074        raise pyxb.IncompleteImplementationError('redefine not implemented')
5075
5076    def __processAnnotation (self, node):
5077        self._addAnnotation(Annotation.CreateFromDOM(node))
5078        return self
5079
5080    def __processTopLevelNode (self, node):
5081        """Process a DOM node from the top level of the schema.
5082
5083        This should return a non-None value if the node was
5084        successfully recognized."""
5085        if xsd.nodeIsNamed(node, 'include'):
5086            return self.__processInclude(node)
5087        if xsd.nodeIsNamed(node, 'import'):
5088            return self.__processImport(node)
5089        if xsd.nodeIsNamed(node, 'redefine'):
5090            return self.__processRedefine(node)
5091        if xsd.nodeIsNamed(node, 'annotation'):
5092            return self.__processAnnotation(node)
5093
5094        component = self.__TopLevelComponentMap.get(node.localName)
5095        if component is not None:
5096            self.__pastProlog = True
5097            kw = { 'scope' : _ScopedDeclaration_mixin.SCOPE_global,
5098                   'schema' : self,
5099                   'owner' : self }
5100            return self._addNamedComponent(component.CreateFromDOM(node, **kw))
5101
5102        raise pyxb.SchemaValidationError('Unexpected top-level element %s' % (node.nodeName,))
5103
5104    def _addAnnotation (self, annotation):
5105        self.__annotations.append(annotation)
5106        return annotation
5107
5108    def _addNamedComponent (self, nc):
5109        tns = self.targetNamespace()
5110        assert tns is not None
5111        if not isinstance(nc, _NamedComponent_mixin):
5112            raise pyxb.LogicError('Attempt to add unnamed %s instance to dictionary' % (nc.__class__,))
5113        if nc.isAnonymous():
5114            raise pyxb.LogicError('Attempt to add anonymous component to dictionary: %s', (nc.__class__,))
5115        if isinstance(nc, _ScopedDeclaration_mixin):
5116            assert _ScopedDeclaration_mixin.SCOPE_global == nc.scope()
5117        if isinstance(nc, (SimpleTypeDefinition, ComplexTypeDefinition)):
5118            return self.__addTypeDefinition(nc)
5119        if isinstance(nc, AttributeDeclaration):
5120            return self.__addAttributeDeclaration(nc)
5121        if isinstance(nc, AttributeGroupDefinition):
5122            return self.__addAttributeGroupDefinition(nc)
5123        if isinstance(nc, ModelGroupDefinition):
5124            return tns.addCategoryObject('modelGroupDefinition', nc.name(), nc)
5125        if isinstance(nc, ElementDeclaration):
5126            return tns.addCategoryObject('elementDeclaration', nc.name(), nc)
5127        if isinstance(nc, NotationDeclaration):
5128            return tns.addCategoryObject('notationDeclaration', nc.name(), nc)
5129        if isinstance(nc, IdentityConstraintDefinition):
5130            return tns.addCategoryObject('identityConstraintDefinition', nc.name(), nc)
5131        assert False, 'No support to record named component of type %s' % (nc.__class__,)
5132
5133    def __addTypeDefinition (self, td):
5134        local_name = td.name()
5135        assert self.__targetNamespace
5136        tns = self.targetNamespace()
5137        old_td = tns.typeDefinitions().get(local_name)
5138        if (old_td is not None) and (old_td != td):
5139            if isinstance(td, ComplexTypeDefinition) != isinstance(old_td, ComplexTypeDefinition):
5140                raise pyxb.SchemaValidationError('Name %s used for both simple and complex types' % (td.name(),))
5141
5142            if not old_td._allowUpdateFromOther(td):
5143                raise pyxb.SchemaValidationError('Attempt to re-define non-builtin type definition %s' % (tns.createExpandedName(local_name),))
5144
5145            # Copy schema-related information from the new definition
5146            # into the old one, and continue to use the old one.
5147            td = tns._replaceComponent(td, old_td._updateFromOther(td))
5148        else:
5149            tns.addCategoryObject('typeDefinition', td.name(), td)
5150        assert td is not None
5151        return td
5152
5153    def __addAttributeDeclaration (self, ad):
5154        local_name = ad.name()
5155        assert self.__targetNamespace
5156        tns = self.targetNamespace()
5157        old_ad = tns.attributeDeclarations().get(local_name)
5158        if (old_ad is not None) and (old_ad != ad):
5159            if not old_ad._allowUpdateFromOther(ad):
5160                raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute declaration %s' % (tns.createExpandedName(local_name),))
5161
5162            # Copy schema-related information from the new definition
5163            # into the old one, and continue to use the old one.
5164            ad = tns._replaceComponent(ad, old_ad._updateFromOther(ad))
5165        else:
5166            tns.addCategoryObject('attributeDeclaration', ad.name(), ad)
5167        assert ad is not None
5168        return ad
5169
5170    def __addAttributeGroupDefinition (self, agd):
5171        local_name = agd.name()
5172        assert self.__targetNamespace
5173        tns = self.targetNamespace()
5174        old_agd = tns.attributeGroupDefinitions().get(local_name)
5175        if (old_agd is not None) and (old_agd != agd):
5176            if not old_agd._allowUpdateFromOther(agd):
5177                raise pyxb.SchemaValidationError('Attempt to re-define non-builtin attribute group definition %s' % (tns.createExpandedName(local_name),))
5178
5179            # Copy schema-related information from the new definition
5180            # into the old one, and continue to use the old one.
5181            tns._replaceComponent(agd, old_agd._updateFromOther(agd))
5182        else:
5183            tns.addCategoryObject('attributeGroupDefinition', agd.name(), agd)
5184        assert agd is not None
5185        return agd
5186
5187    def __str__ (self):
5188        return 'SCH[%s]' % (self.location(),)
5189
5190
5191def _AddSimpleTypes (namespace):
5192    """Add to the schema the definitions of the built-in types of XMLSchema.
5193    This should only be invoked by L{pyxb.namespace} when the built-in
5194    namespaces are initialized. """
5195    # Add the ur type
5196    #schema = namespace.schema()
5197    schema = Schema(namespace_context=pyxb.namespace.XMLSchema.initialNamespaceContext(), schema_location='URN:noLocation:PyXB:XMLSchema', generation_uid=pyxb.namespace.BuiltInObjectUID, _bypass_preload=True)
5198    td = schema._addNamedComponent(ComplexTypeDefinition.UrTypeDefinition(schema, in_builtin_definition=True))
5199    assert td.isResolved()
5200    # Add the simple ur type
5201    td = schema._addNamedComponent(SimpleTypeDefinition.SimpleUrTypeDefinition(schema, in_builtin_definition=True))
5202    assert td.isResolved()
5203    # Add definitions for all primitive and derived simple types
5204    pts_std_map = {}
5205    for dtc in datatypes._PrimitiveDatatypes:
5206        name = dtc.__name__.rstrip('_')
5207        td = schema._addNamedComponent(SimpleTypeDefinition.CreatePrimitiveInstance(name, schema, dtc))
5208        assert td.isResolved()
5209        assert dtc.SimpleTypeDefinition() == td
5210        pts_std_map.setdefault(dtc, td)
5211    for dtc in datatypes._DerivedDatatypes:
5212        name = dtc.__name__.rstrip('_')
5213        parent_std = pts_std_map[dtc.XsdSuperType()]
5214        td = schema._addNamedComponent(SimpleTypeDefinition.CreateDerivedInstance(name, schema, parent_std, dtc))
5215        assert td.isResolved()
5216        assert dtc.SimpleTypeDefinition() == td
5217        pts_std_map.setdefault(dtc, td)
5218    for dtc in datatypes._ListDatatypes:
5219        list_name = dtc.__name__.rstrip('_')
5220        element_name = dtc._ItemType.__name__.rstrip('_')
5221        element_std = schema.targetNamespace().typeDefinitions().get(element_name)
5222        assert element_std is not None
5223        td = schema._addNamedComponent(SimpleTypeDefinition.CreateListInstance(list_name, schema, element_std, dtc))
5224        assert td.isResolved()
5225    global _PastAddBuiltInTypes
5226    _PastAddBuiltInTypes = True
5227
5228    return schema
5229
5230import sys
5231import pyxb.namespace.builtin
5232pyxb.namespace.builtin._InitializeBuiltinNamespaces(sys.modules[__name__])
5233
5234## Local Variables:
5235## fill-column:78
5236## End:
5237