001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.bind.v2.runtime.unmarshaller;
027:
028: import javax.xml.namespace.QName;
029:
030: import com.sun.xml.internal.bind.DatatypeConverterImpl;
031: import com.sun.xml.internal.bind.v2.WellKnownNamespace;
032: import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
033:
034: import org.xml.sax.Attributes;
035: import org.xml.sax.SAXException;
036:
037: /**
038: * Looks at @xsi:type and forwards to the right {@link Loader}.
039: *
040: * @author Kohsuke Kawaguchi
041: */
042: public class XsiTypeLoader extends Loader {
043:
044: /**
045: * Use this when no @xsi:type was found.
046: */
047: private final JaxBeanInfo defaultBeanInfo;
048:
049: public XsiTypeLoader(JaxBeanInfo defaultBeanInfo) {
050: super (true);
051: this .defaultBeanInfo = defaultBeanInfo;
052: }
053:
054: public void startElement(UnmarshallingContext.State state,
055: TagName ea) throws SAXException {
056: JaxBeanInfo beanInfo = parseXsiType(state, ea);
057: if (beanInfo == null)
058: beanInfo = defaultBeanInfo;
059:
060: Loader loader = beanInfo.getLoader(null, false);
061: state.loader = loader;
062: loader.startElement(state, ea);
063: }
064:
065: /*pacakge*/static JaxBeanInfo parseXsiType(
066: UnmarshallingContext.State state, TagName ea)
067: throws SAXException {
068: UnmarshallingContext context = state.getContext();
069: JaxBeanInfo beanInfo = null;
070:
071: // look for @xsi:type
072: Attributes atts = ea.atts;
073: int idx = atts.getIndex(WellKnownNamespace.XML_SCHEMA_INSTANCE,
074: "type");
075:
076: if (idx >= 0) {
077: // we'll consume the value only when it's a recognized value,
078: // so don't consume it just yet.
079: String value = atts.getValue(idx);
080:
081: QName type = DatatypeConverterImpl._parseQName(value,
082: context);
083: if (type == null) {
084: reportError(Messages.NOT_A_QNAME.format(value), true);
085: } else {
086: beanInfo = context.getJAXBContext().getGlobalType(type);
087: if (beanInfo == null) {
088: String nearest = context.getJAXBContext()
089: .getNearestTypeName(type);
090: if (nearest != null)
091: reportError(
092: Messages.UNRECOGNIZED_TYPE_NAME_MAYBE
093: .format(type, nearest), true);
094: else
095: reportError(Messages.UNRECOGNIZED_TYPE_NAME
096: .format(type), true);
097: }
098: // TODO: resurrect the following check
099: // else
100: // if(!target.isAssignableFrom(actual)) {
101: // reportError(context,
102: // Messages.UNSUBSTITUTABLE_TYPE.format(value,actual.getName(),target.getName()),
103: // true);
104: // actual = targetBeanInfo; // ditto
105: // }
106: }
107: }
108: return beanInfo;
109: }
110: }
|