1/*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.xsom.impl.parser;
27
28import com.sun.xml.internal.xsom.XSAttGroupDecl;
29import com.sun.xml.internal.xsom.XSAttributeDecl;
30import com.sun.xml.internal.xsom.XSComplexType;
31import com.sun.xml.internal.xsom.XSDeclaration;
32import com.sun.xml.internal.xsom.XSElementDecl;
33import com.sun.xml.internal.xsom.XSIdentityConstraint;
34import com.sun.xml.internal.xsom.XSModelGroupDecl;
35import com.sun.xml.internal.xsom.XSSchemaSet;
36import com.sun.xml.internal.xsom.XSSimpleType;
37import com.sun.xml.internal.xsom.XSTerm;
38import com.sun.xml.internal.xsom.XSType;
39import com.sun.xml.internal.xsom.impl.Ref;
40import com.sun.xml.internal.xsom.impl.SchemaImpl;
41import com.sun.xml.internal.xsom.impl.UName;
42import org.xml.sax.Locator;
43import org.xml.sax.SAXException;
44
45/**
46 * Reference by name.
47 *
48 * UName will be later resolved to a target object,
49 * after all the schemas are parsed.
50 */
51public abstract class DelayedRef implements Patch {
52    DelayedRef( PatcherManager _manager, Locator _source, SchemaImpl _schema, UName _name ) {
53
54        this.schema = _schema.getRoot();
55        this.manager = _manager;
56        this.name = _name;
57        this.source = _source;
58
59        if(name==null)  throw new InternalError();
60
61        manager.addPatcher(this);
62    }
63
64    /**
65     * Patch implementation. Makes sure that the name resolves
66     * to a schema component.
67     */
68    public void run() throws SAXException {
69        if(ref==null)    // redefinition can set ref without actually resolving the reference
70            resolve();
71        manager = null;     // avoid keeping the reference too long
72        name = null;
73        source = null;
74    }
75
76
77    protected final XSSchemaSet schema;
78    private PatcherManager manager;
79    private UName name;
80    /** location in the source file where this reference was made. */
81    private Locator source;
82
83    protected abstract Object resolveReference( UName name );
84    protected abstract String getErrorProperty();
85
86    private Object ref=null;
87    protected final Object _get() {
88        if(ref==null)   throw new InternalError("unresolved reference");
89        return ref;
90    }
91
92    private void resolve() throws SAXException {
93        ref = resolveReference(name);
94        if(ref==null)
95            manager.reportError(
96                Messages.format(getErrorProperty(),name.getQualifiedName()),
97                source );
98    }
99
100    /**
101     * If this reference refers to the given declaration,
102     * resolve the reference now. This is used to implement redefinition.
103     */
104    public void redefine(XSDeclaration d) {
105        if( !d.getTargetNamespace().equals(name.getNamespaceURI())
106        ||  !d.getName().equals(name.getName()) )
107            return;
108
109        ref = d;
110        manager = null;
111        name = null;
112        source = null;
113    }
114
115
116    public static class Type extends DelayedRef implements Ref.Type {
117        public Type( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
118            super(manager,loc,schema,name);
119        }
120        protected Object resolveReference( UName name ) {
121            Object o = super.schema.getSimpleType(
122                name.getNamespaceURI(), name.getName() );
123            if(o!=null)     return o;
124
125            return super.schema.getComplexType(
126                name.getNamespaceURI(),
127                name.getName());
128        }
129        protected String getErrorProperty() {
130            return Messages.ERR_UNDEFINED_TYPE;
131        }
132
133        public XSType getType() { return (XSType)super._get(); }
134    }
135
136    public static class SimpleType extends DelayedRef implements Ref.SimpleType {
137        public SimpleType( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
138            super(manager,loc,schema,name);
139        }
140        public XSSimpleType getType() { return (XSSimpleType)_get(); }
141
142        protected Object resolveReference( UName name ) {
143            return super.schema.getSimpleType(
144                name.getNamespaceURI(),
145                name.getName());
146        }
147
148        protected String getErrorProperty() {
149            return Messages.ERR_UNDEFINED_SIMPLETYPE;
150        }
151    }
152
153    public static class ComplexType extends DelayedRef implements Ref.ComplexType {
154        public ComplexType( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
155            super(manager,loc,schema,name);
156        }
157        protected Object resolveReference( UName name ) {
158            return super.schema.getComplexType(
159                name.getNamespaceURI(),
160                name.getName());
161        }
162
163        protected String getErrorProperty() {
164            return Messages.ERR_UNDEFINED_COMPLEXTYPE;
165        }
166
167        public XSComplexType getType() { return (XSComplexType)super._get(); }
168    }
169
170    public static class Element extends DelayedRef implements Ref.Element {
171        public Element( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
172            super(manager,loc,schema,name);
173        }
174        protected Object resolveReference( UName name ) {
175            return super.schema.getElementDecl(
176                name.getNamespaceURI(),
177                name.getName());
178        }
179
180        protected String getErrorProperty() {
181            return Messages.ERR_UNDEFINED_ELEMENT;
182        }
183
184        public XSElementDecl get() { return (XSElementDecl)super._get(); }
185        public XSTerm getTerm() { return get(); }
186    }
187
188    public static class ModelGroup extends DelayedRef implements Ref.Term {
189        public ModelGroup( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
190            super(manager,loc,schema,name);
191        }
192        protected Object resolveReference( UName name ) {
193            return super.schema.getModelGroupDecl(
194                name.getNamespaceURI(),
195                name.getName());
196        }
197
198        protected String getErrorProperty() {
199            return Messages.ERR_UNDEFINED_MODELGROUP;
200        }
201
202        public XSModelGroupDecl get() { return (XSModelGroupDecl)super._get(); }
203        public XSTerm getTerm() { return get(); }
204    }
205
206    public static class AttGroup extends DelayedRef implements Ref.AttGroup {
207        public AttGroup( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
208            super(manager,loc,schema,name);
209        }
210        protected Object resolveReference( UName name ) {
211            return super.schema.getAttGroupDecl(
212                name.getNamespaceURI(),
213                name.getName());
214        }
215
216        protected String getErrorProperty() {
217            return Messages.ERR_UNDEFINED_ATTRIBUTEGROUP;
218        }
219
220        public XSAttGroupDecl get() { return (XSAttGroupDecl)super._get(); }
221    }
222
223    public static class Attribute extends DelayedRef implements Ref.Attribute {
224        public Attribute( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
225            super(manager,loc,schema,name);
226        }
227        protected Object resolveReference( UName name ) {
228            return super.schema.getAttributeDecl(
229                name.getNamespaceURI(),
230                name.getName());
231        }
232
233        protected String getErrorProperty() {
234            return Messages.ERR_UNDEFINED_ATTRIBUTE;
235        }
236
237        public XSAttributeDecl getAttribute() { return (XSAttributeDecl)super._get(); }
238    }
239
240    public static class IdentityConstraint extends DelayedRef implements Ref.IdentityConstraint {
241        public IdentityConstraint( PatcherManager manager, Locator loc, SchemaImpl schema, UName name ) {
242            super(manager,loc,schema,name);
243        }
244        protected Object resolveReference( UName name ) {
245            return super.schema.getIdentityConstraint(
246                name.getNamespaceURI(),
247                name.getName());
248        }
249
250        protected String getErrorProperty() {
251            return Messages.ERR_UNDEFINED_IDENTITY_CONSTRAINT;
252        }
253
254        public XSIdentityConstraint get() { return (XSIdentityConstraint)super._get(); }
255    }
256}
257