alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SimpleTypeBuilder.java)

This example Java source code file (SimpleTypeBuilder.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

biconversion, biginteger, bindinfo, cenumconstant, hashset, list, map, math, sax, set, string, text, typeuse, util, xsattributedecl, xsfacet, xsrestrictionsimpletype, xssimpletype

The SimpleTypeBuilder.java Java example source code

/*
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.internal.xjc.reader.xmlschema;

import java.io.StringWriter;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.activation.MimeTypeParseException;
import javax.xml.bind.DatatypeConverter;

import com.sun.codemodel.internal.JJavaName;
import com.sun.codemodel.internal.util.JavadocEscapeWriter;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CClassRef;
import com.sun.tools.internal.xjc.model.CEnumConstant;
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
import com.sun.tools.internal.xjc.model.CNonElement;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnum;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnumMember;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.EnumMemberMode;
import com.sun.tools.internal.xjc.util.MimeTypeRange;

import static com.sun.xml.internal.bind.v2.WellKnownNamespace.XML_MIME_URI;

import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapterMarker;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSListSimpleType;
import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSUnionSimpleType;
import com.sun.xml.internal.xsom.XSVariety;
import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
import com.sun.xml.internal.xsom.visitor.XSSimpleTypeFunction;
import com.sun.xml.internal.xsom.visitor.XSVisitor;

import org.xml.sax.Locator;

/**
 * Builds {@link TypeUse} from simple types.
 *
 * <p>
 * This code consists of two main portions. The {@link #compose(XSSimpleType)} method
 * and {@link #composer} forms an outer cycle, which gradually ascends the type
 * inheritance chain until it finds the suitable binding. When it does this
 * {@link #initiatingType} is set to the type which started binding, so that we can refer
 * to the actual constraint facets and such that are applicable on the type.
 *
 * <p>
 * For each intermediate type in the chain, the {@link #find(XSSimpleType)} method
 * is used to find the binding on that type, sine the outer loop is doing the ascending,
 * this method only sees if the current type has some binding available.
 *
 * <p>
 * There is at least one ugly code that you need to aware of
 * when you are modifying the code. See the documentation
 * about <a href="package.html#stref_cust">
 * "simple type customization at the point of reference."</a>
 *
 *
 * @author
 *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
 */
public final class SimpleTypeBuilder extends BindingComponent {

    protected final BGMBuilder builder = Ring.get(BGMBuilder.class);

    private final Model model = Ring.get(Model.class);

    /**
     * The component that is refering to the simple type
     * which we are building. This is ugly but necessary
     * to support the customization of simple types at
     * its point of reference. See my comment at the header
     * of this class for details.
     *
     * UGLY: Implemented as a Stack of XSComponent to fix a bug
     */
    public final Stack<XSComponent> refererStack = new Stack();

    /**
     * Records what xmime:expectedContentTypes annotations we honored and processed,
     * so that we can later check if the user had these annotations in the places
     * where we didn't anticipate them.
     */
    private final Set<XSComponent> acknowledgedXmimeContentTypes = new HashSet();

    /**
     * The type that was originally passed to this {@link SimpleTypeBuilder#build(XSSimpleType)}.
     * Never null.
     */
    private XSSimpleType initiatingType;

    /** {@link TypeUse}s for the built-in types. Read-only. */
    public static final Map<String,TypeUse> builtinConversions = new HashMap();


    /**
     * Entry point from outside. Builds a BGM type expression
     * from a simple type schema component.
     *
     * @param type
     *      the simple type to be bound.
     */
    public TypeUse build( XSSimpleType type ) {
        XSSimpleType oldi = initiatingType;
        this.initiatingType = type;

        TypeUse e = checkRefererCustomization(type);
        if(e==null)
            e = compose(type);

        initiatingType = oldi;

        return e;
    }

    /**
     * A version of the {@link #build(XSSimpleType)} method
     * used to bind the definition of a class generated from
     * the given simple type.
     */
    public TypeUse buildDef( XSSimpleType type ) {
        XSSimpleType oldi = initiatingType;
        this.initiatingType = type;

        TypeUse e = type.apply(composer);

        initiatingType = oldi;

        return e;
    }


    /**
     * Returns a javaType customization specified to the referer, if present.
     * @return can be null.
     */
    private BIConversion getRefererCustomization() {
        BindInfo info = builder.getBindInfo(getReferer());
        BIProperty prop = info.get(BIProperty.class);
        if(prop==null)  return null;
        return prop.getConv();
    }

    public XSComponent getReferer() {
        return refererStack.peek();
    }

    /**
     * Checks if the referer has a conversion customization or not.
     * If it does, use it to bind this simple type. Otherwise
     * return null;
     */
    private TypeUse checkRefererCustomization( XSSimpleType type ) {

        // assertion check. referer must be set properly
        // before the build method is called.
        // since the handling of the simple type point-of-reference
        // customization is very error prone, it deserves a strict
        // assertion check.
        // UGLY CODE WARNING
        XSComponent top = getReferer();

        if( top instanceof XSElementDecl ) {
            // if the parent is element type, its content type must be us.
            XSElementDecl eref = (XSElementDecl)top;
            assert eref.getType()==type;

            // for elements, you can't use <property>,
            // so we allow javaType to appear directly.
            BindInfo info = builder.getBindInfo(top);
            BIConversion conv = info.get(BIConversion.class);
            if(conv!=null) {
                conv.markAsAcknowledged();
                // the conversion is given.
                return conv.getTypeUse(type);
            }
            detectJavaTypeCustomization();
        } else
        if( top instanceof XSAttributeDecl ) {
            XSAttributeDecl aref = (XSAttributeDecl)top;
            assert aref.getType()==type;
            detectJavaTypeCustomization();
        } else
        if( top instanceof XSComplexType ) {
            XSComplexType tref = (XSComplexType)top;
            assert tref.getBaseType()==type || tref.getContentType()==type;
            detectJavaTypeCustomization();
        } else
        if( top == type ) {
            // this means the simple type is built by itself and
            // not because it's referenced by something.
        } else
            // unexpected referer type.
            assert false;

        // now we are certain that the referer is OK.
        // see if it has a conversion customization.
        BIConversion conv = getRefererCustomization();
        if(conv!=null) {
            conv.markAsAcknowledged();
            // the conversion is given.
            return conv.getTypeUse(type);
        } else
            // not found
            return null;
    }

    /**
     * Detect "javaType" customizations placed directly on simple types, rather
     * than being enclosed by "property" and "baseType" customizations (see
     * sec 6.8.1 of the spec).
     *
     * Report an error if any exist.
     */
    private void detectJavaTypeCustomization() {
        BindInfo info = builder.getBindInfo(getReferer());
        BIConversion conv = info.get(BIConversion.class);

        if( conv != null ) {
            // ack this conversion to prevent further error messages
            conv.markAsAcknowledged();

            // report the error
            getErrorReporter().error( conv.getLocation(),
                    Messages.ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE );
        }
    }

    /**
     * Recursively decend the type inheritance chain to find a binding.
     */
    TypeUse compose( XSSimpleType t ) {
        TypeUse e = find(t);
        if(e!=null)     return e;
        return t.apply(composer);
    }

    public final XSSimpleTypeFunction<TypeUse> composer = new XSSimpleTypeFunction() {

        public TypeUse listSimpleType(XSListSimpleType type) {
            // bind item type individually and then compose them into a list
            // facets on the list shouldn't be taken account when binding item types,
            // so weed to call build(), not compose().
            XSSimpleType itemType = type.getItemType();
            refererStack.push(itemType);
            TypeUse tu = TypeUseFactory.makeCollection(build(type.getItemType()));
            refererStack.pop();
            return tu;
        }

        public TypeUse unionSimpleType(XSUnionSimpleType type) {
            boolean isCollection = false;
            for( int i=0; i<type.getMemberSize(); i++ )
                if(type.getMember(i).getVariety()==XSVariety.LIST || type.getMember(i).getVariety()==XSVariety.UNION) {
                    isCollection = true;
                    break;
                }

            TypeUse r = CBuiltinLeafInfo.STRING;
            if(isCollection)
                r = TypeUseFactory.makeCollection(r);
            return r;
        }

        public TypeUse restrictionSimpleType(XSRestrictionSimpleType type) {
            // just process the base type.
            return compose(type.getSimpleBaseType());
        }
    };


    /**
     * Checks if there's any binding available on the given type.
     *
     * @return
     *      null if not (which causes the {@link #compose(XSSimpleType)} method
     *      to do ascending.
     */
    private TypeUse find( XSSimpleType type ) {
        TypeUse r;
        boolean noAutoEnum = false;

        // check for user specified conversion
        BindInfo info = builder.getBindInfo(type);
        BIConversion conv = info.get(BIConversion.class);

        if( conv!=null ) {
            // a conversion was found
            conv.markAsAcknowledged();
            return conv.getTypeUse(type);
        }

        // look for enum customization, which is another user specified conversion
        BIEnum en = info.get(BIEnum.class);
        if( en!=null ) {
            en.markAsAcknowledged();

            if(!en.isMapped()) {
                noAutoEnum = true;
            } else {
                // if an enum customization is specified, make sure
                // the type is OK
                if( !canBeMappedToTypeSafeEnum(type) ) {
                    getErrorReporter().error( en.getLocation(),
                        Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM );
                    getErrorReporter().error( type.getLocator(),
                        Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION );
                    // recover by ignoring this customization
                    return null;
                }

                // reference?
                if(en.ref!=null) {
                    if(!JJavaName.isFullyQualifiedClassName(en.ref)) {
                        Ring.get(ErrorReceiver.class).error( en.getLocation(),
                            Messages.format(Messages.ERR_INCORRECT_CLASS_NAME, en.ref) );
                        // recover by ignoring @ref
                        return null;
                    }

                    return new CClassRef(model, type, en, info.toCustomizationList() );
                }

                // list and union cannot be mapped to a type-safe enum,
                // so in this stage we can safely cast it to XSRestrictionSimpleType
                return bindToTypeSafeEnum( (XSRestrictionSimpleType)type,
                        en.className, en.javadoc, en.members,
                        getEnumMemberMode().getModeWithEnum(),
                        en.getLocation() );
            }
        }


        // if the type is built in, look for the default binding
        if(type.getTargetNamespace().equals(WellKnownNamespace.XML_SCHEMA)) {
            String name = type.getName();
            if(name!=null) {
                r = lookupBuiltin(name);
                if(r!=null)
                    return r;
            }
        }

        // also check for swaRef
        if(type.getTargetNamespace().equals(WellKnownNamespace.SWA_URI)) {
            String name = type.getName();
            if(name!=null && name.equals("swaRef"))
                return CBuiltinLeafInfo.STRING.makeAdapted(SwaRefAdapterMarker.class,false);
        }


        // see if this type should be mapped to a type-safe enumeration by default.
        // if so, built a EnumXDucer from it and return it.
        if(type.isRestriction() && !noAutoEnum) {
            XSRestrictionSimpleType rst = type.asRestriction();
            if(shouldBeMappedToTypeSafeEnumByDefault(rst)) {
                r = bindToTypeSafeEnum(rst,null,null, Collections.<String, BIEnumMember>emptyMap(),
                            getEnumMemberMode(),null);
                if(r!=null)
                    return r;
            }
        }

        return (CNonElement)getClassSelector()._bindToClass(type,null,false);
    }

    private static Set<XSRestrictionSimpleType> reportedEnumMemberSizeWarnings;

    /**
     * Returns true if a type-safe enum should be created from
     * the given simple type by default without an explicit <jaxb:enum> customization.
     */
    private boolean shouldBeMappedToTypeSafeEnumByDefault( XSRestrictionSimpleType type ) {

        // if not, there will be a problem wrt the class name of this type safe enum type.
        if( type.isLocal() )    return false;

        // if redefined, we should map the new definition, not the old one.
        if( type.getRedefinedBy()!=null )   return false;

        List<XSFacet> facets = type.getDeclaredFacets(XSFacet.FACET_ENUMERATION);
        if( facets.isEmpty() )
            // if the type itself doesn't have the enumeration facet,
            // it won't be mapped to a type-safe enum.
            return false;

        if(facets.size() > builder.getGlobalBinding().getDefaultEnumMemberSizeCap()) {
            // if there are too many facets, it's not very useful
            // produce warning when simple type is not mapped to enum
            // see issue https://jaxb.dev.java.net/issues/show_bug.cgi?id=711

            if(reportedEnumMemberSizeWarnings == null)
                reportedEnumMemberSizeWarnings = new HashSet<XSRestrictionSimpleType>();

            if(!reportedEnumMemberSizeWarnings.contains(type)) {
                getErrorReporter().warning(type.getLocator(), Messages.WARN_ENUM_MEMBER_SIZE_CAP,
                        type.getName(), facets.size(), builder.getGlobalBinding().getDefaultEnumMemberSizeCap());

                reportedEnumMemberSizeWarnings.add(type);
            }

            return false;
        }

        if( !canBeMappedToTypeSafeEnum(type) )
            // we simply can't map this to an enumeration
            return false;

        // check for collisions among constant names. if a collision will happen,
        // don't try to bind it to an enum.

        // return true only when this type is derived from one of the "enum base type".
        for( XSSimpleType t = type; t!=null; t=t.getSimpleBaseType() )
            if( t.isGlobal() && builder.getGlobalBinding().canBeMappedToTypeSafeEnum(t) )
                return true;

        return false;
    }


    private static final Set<String> builtinTypeSafeEnumCapableTypes;

    static {
        Set<String> s = new HashSet();

        // see a bullet of 6.5.1 of the spec.
        String[] typeNames = new String[] {
            "string", "boolean", "float", "decimal", "double", "anyURI"
        };
        s.addAll(Arrays.asList(typeNames));

        builtinTypeSafeEnumCapableTypes = Collections.unmodifiableSet(s);
    }


    /**
     * Returns true if the given simple type can be mapped to a
     * type-safe enum class.
     *
     * <p>
     * JAXB spec places a restrictrion as to what type can be
     * mapped to a type-safe enum. This method enforces this
     * constraint.
     */
    public static boolean canBeMappedToTypeSafeEnum( XSSimpleType type ) {
        do {
            if( WellKnownNamespace.XML_SCHEMA.equals(type.getTargetNamespace()) ) {
                // type must be derived from one of these types
                String localName = type.getName();
                if( localName!=null ) {
                    if( localName.equals("anySimpleType") )
                        return false;   // catch all case
                    if( localName.equals("ID") || localName.equals("IDREF") )
                        return false;   // not ID/IDREF

                    // other allowed list
                    if( builtinTypeSafeEnumCapableTypes.contains(localName) )
                        return true;
                }
            }

            type = type.getSimpleBaseType();
        } while( type!=null );

        return false;
    }



    /**
     * Builds a type-safe enum conversion from a simple type
     * with enumeration facets.
     *
     * @param className
     *      The class name of the type-safe enum. Or null to
     *      create a default name.
     * @param javadoc
     *      Additional javadoc that will be added at the beginning of the
     *      class, or null if none is necessary.
     * @param members
     *      A map from enumeration values (as String) to BIEnumMember objects.
     *      if some of the value names need to be overrided.
     *      Cannot be null, but the map may not contain entries
     *      for all enumeration values.
     * @param loc
     *      The source location where the above customizations are
     *      specified, or null if none is available.
     */
    private TypeUse bindToTypeSafeEnum( XSRestrictionSimpleType type,
                                        String className, String javadoc, Map<String,BIEnumMember> members,
                                        EnumMemberMode mode, Locator loc ) {

        if( loc==null )  // use the location of the simple type as the default
            loc = type.getLocator();

        if( className==null ) {
            // infer the class name. For this to be possible,
            // the simple type must be a global one.
            if( !type.isGlobal() ) {
                getErrorReporter().error( loc, Messages.ERR_NO_ENUM_NAME_AVAILABLE );
                // recover by returning a meaningless conversion
                return CBuiltinLeafInfo.STRING;
            }
            className = type.getName();
        }

        // we apply name conversion in any case
        className = builder.deriveName(className,type);

        {// compute Javadoc
            StringWriter out = new StringWriter();
            SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out));
            type.visit((XSVisitor)sw);

            if(javadoc!=null)   javadoc += "\n\n";
            else                javadoc = "";

            javadoc += Messages.format( Messages.JAVADOC_HEADING, type.getName() )
                +"\n<p>\n
\n"+out.getBuffer()+"
"; } // build base type refererStack.push(type.getSimpleBaseType()); TypeUse use = build(type.getSimpleBaseType()); refererStack.pop(); if(use.isCollection()) return null; // can't bind a list to enum constant CNonElement baseDt = use.getInfo(); // for now just ignore that case if(baseDt instanceof CClassInfo) return null; // can't bind to an enum if the base is a class, since we don't have the value constrctor // if the member names collide, re-generate numbered constant names. XSFacet[] errorRef = new XSFacet[1]; List<CEnumConstant> memberList = buildCEnumConstants(type, false, members, errorRef); if(memberList==null || checkMemberNameCollision(memberList)!=null) { switch(mode) { case SKIP: // abort return null; case ERROR: // error if(memberList==null) { getErrorReporter().error( errorRef[0].getLocator(), Messages.ERR_CANNOT_GENERATE_ENUM_NAME, errorRef[0].getValue() ); } else { CEnumConstant[] collision = checkMemberNameCollision(memberList); getErrorReporter().error( collision[0].getLocator(), Messages.ERR_ENUM_MEMBER_NAME_COLLISION, collision[0].getName() ); getErrorReporter().error( collision[1].getLocator(), Messages.ERR_ENUM_MEMBER_NAME_COLLISION_RELATED ); } return null; // recover from error case GENERATE: // generate memberList = buildCEnumConstants(type,true,members,null); break; } } if(memberList.isEmpty()) { getErrorReporter().error( loc, Messages.ERR_NO_ENUM_FACET ); return null; } // use the name of the simple type as the name of the class. CClassInfoParent scope; if(type.isGlobal()) scope = new CClassInfoParent.Package(getClassSelector().getPackage(type.getTargetNamespace())); else scope = getClassSelector().getClassScope(); CEnumLeafInfo xducer = new CEnumLeafInfo( model, BGMBuilder.getName(type), scope, className, baseDt, memberList, type, builder.getBindInfo(type).toCustomizationList(), loc ); xducer.javadoc = javadoc; BIConversion conv = new BIConversion.Static( type.getLocator(),xducer); conv.markAsAcknowledged(); // attach this new conversion object to this simple type // so that successive look up will use the same object. builder.getOrCreateBindInfo(type).addDecl(conv); return conv.getTypeUse(type); } /** * * @param errorRef * if constant names couldn't be generated, return a reference to that enum facet. * @return * null if unable to generate names for some of the constants. */ private List<CEnumConstant> buildCEnumConstants(XSRestrictionSimpleType type, boolean needsToGenerateMemberName, Map members, XSFacet[] errorRef) { List<CEnumConstant> memberList = new ArrayList(); int idx=1; Set<String> enums = new HashSet(); // to avoid duplicates. See issue #366 for( XSFacet facet : type.getDeclaredFacets(XSFacet.FACET_ENUMERATION)) { String name=null; String mdoc=builder.getBindInfo(facet).getDocumentation(); if(!enums.add(facet.getValue().value)) continue; // ignore the 2nd occasion if( needsToGenerateMemberName ) { // generate names for all member names. // this will even override names specified by the user. that's crazy. name = "VALUE_"+(idx++); } else { String facetValue = facet.getValue().value; BIEnumMember mem = members.get(facetValue); if( mem==null ) // look at the one attached to the facet object mem = builder.getBindInfo(facet).get(BIEnumMember.class); if (mem!=null) { name = mem.name; if (mdoc == null) { mdoc = mem.javadoc; } } if(name==null) { StringBuilder sb = new StringBuilder(); for( int i=0; i<facetValue.length(); i++) { char ch = facetValue.charAt(i); if(Character.isJavaIdentifierPart(ch)) sb.append(ch); else sb.append('_'); } name = model.getNameConverter().toConstantName(sb.toString()); } } if(!JJavaName.isJavaIdentifier(name)) { if(errorRef!=null) errorRef[0] = facet; return null; // unable to generate a name } memberList.add(new CEnumConstant(name,mdoc,facet.getValue().value,facet,builder.getBindInfo(facet).toCustomizationList(),facet.getLocator())); } return memberList; } /** * Returns non-null if {@link CEnumConstant}s have name collisions among them. * * @return * if there's a collision, return two {@link CEnumConstant}s that collided. * otherwise return null. */ private CEnumConstant[] checkMemberNameCollision( List<CEnumConstant> memberList ) { Map<String,CEnumConstant> names = new HashMap(); for (CEnumConstant c : memberList) { CEnumConstant old = names.put(c.getName(),c); if(old!=null) // collision detected return new CEnumConstant[]{old,c}; } return null; } private EnumMemberMode getEnumMemberMode() { return builder.getGlobalBinding().getEnumMemberMode(); } private TypeUse lookupBuiltin( String typeLocalName ) { if(typeLocalName.equals("integer") || typeLocalName.equals("long")) { /* attempt an optimization so that we can improve the binding for types like this: <simpleType> <restriciton baseType="integer"> <maxInclusive value="100" /> </ </ ... to int, not BigInteger. */ BigInteger xe = readFacet(XSFacet.FACET_MAXEXCLUSIVE,-1); BigInteger xi = readFacet(XSFacet.FACET_MAXINCLUSIVE,0); BigInteger max = min(xe,xi); // most restrictive one takes precedence if(max!=null) { BigInteger ne = readFacet(XSFacet.FACET_MINEXCLUSIVE,+1); BigInteger ni = readFacet(XSFacet.FACET_MININCLUSIVE,0); BigInteger min = max(ne,ni); if(min!=null) { if(min.compareTo(INT_MIN )>=0 && max.compareTo(INT_MAX )<=0) typeLocalName = "int"; else if(min.compareTo(LONG_MIN)>=0 && max.compareTo(LONG_MAX)<=0) typeLocalName = "long"; } } } else if(typeLocalName.equals("boolean") && isRestrictedTo0And1()) { // this is seen in the SOAP schema and too common to ignore return CBuiltinLeafInfo.BOOLEAN_ZERO_OR_ONE; } else if(typeLocalName.equals("base64Binary")) { return lookupBinaryTypeBinding(); } else if(typeLocalName.equals("anySimpleType")) { if(getReferer() instanceof XSAttributeDecl || getReferer() instanceof XSSimpleType) return CBuiltinLeafInfo.STRING; else return CBuiltinLeafInfo.ANYTYPE; } return builtinConversions.get(typeLocalName); } /** * Decides the way xs:base64Binary binds. * * This method checks the expected media type. */ private TypeUse lookupBinaryTypeBinding() { XSComponent referer = getReferer(); String emt = referer.getForeignAttribute(XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES); if(emt!=null) { acknowledgedXmimeContentTypes.add(referer); try { // see http://www.xml.com/lpt/a/2004/07/21/dive.html List<MimeTypeRange> types = MimeTypeRange.parseRanges(emt); MimeTypeRange mt = MimeTypeRange.merge(types); // see spec table I-1 in appendix I section 2.1.1 for bindings if(mt.majorType.equalsIgnoreCase("image")) return CBuiltinLeafInfo.IMAGE.makeMimeTyped(mt.toMimeType()); if(( mt.majorType.equalsIgnoreCase("application") || mt.majorType.equalsIgnoreCase("text")) && isXml(mt.subType)) return CBuiltinLeafInfo.XML_SOURCE.makeMimeTyped(mt.toMimeType()); if((mt.majorType.equalsIgnoreCase("text") && (mt.subType.equalsIgnoreCase("plain")) )) { return CBuiltinLeafInfo.STRING.makeMimeTyped(mt.toMimeType()); } return CBuiltinLeafInfo.DATA_HANDLER.makeMimeTyped(mt.toMimeType()); } catch (ParseException e) { getErrorReporter().error( referer.getLocator(), Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) ); // recover by using the default } catch (MimeTypeParseException e) { getErrorReporter().error( referer.getLocator(), Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) ); } } // default return CBuiltinLeafInfo.BASE64_BYTE_ARRAY; } public boolean isAcknowledgedXmimeContentTypes(XSComponent c) { return acknowledgedXmimeContentTypes.contains(c); } /** * Returns true if the specified sub-type is an XML type. */ private boolean isXml(String subType) { return subType.equals("xml") || subType.endsWith("+xml"); } /** * Returns true if the {@link #initiatingType} is restricted * to '0' and '1'. This logic is not complete, but it at least * finds the such definition in SOAP @mustUnderstand. */ private boolean isRestrictedTo0And1() { XSFacet pattern = initiatingType.getFacet(XSFacet.FACET_PATTERN); if(pattern!=null) { String v = pattern.getValue().value; if(v.equals("0|1") || v.equals("1|0") || v.equals("\\d")) return true; } XSFacet enumf = initiatingType.getFacet(XSFacet.FACET_ENUMERATION); if(enumf!=null) { String v = enumf.getValue().value; if(v.equals("0") || v.equals("1")) return true; } return false; } private BigInteger readFacet(String facetName,int offset) { XSFacet me = initiatingType.getFacet(facetName); if(me==null) return null; BigInteger bi = DatatypeConverter.parseInteger(me.getValue().value); if(offset!=0) bi = bi.add(BigInteger.valueOf(offset)); return bi; } private BigInteger min(BigInteger a, BigInteger b) { if(a==null) return b; if(b==null) return a; return a.min(b); } private BigInteger max(BigInteger a, BigInteger b) { if(a==null) return b; if(b==null) return a; return a.max(b); } private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE); private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE); static { // list of datatypes which have built-in conversions. // note that although xs:token and xs:normalizedString are not // specified in the spec, they need to be here because they // have different whitespace normalization semantics. Map<String,TypeUse> m = builtinConversions; // TODO: this is so dumb m.put("string", CBuiltinLeafInfo.STRING); m.put("anyURI", CBuiltinLeafInfo.STRING); m.put("boolean", CBuiltinLeafInfo.BOOLEAN); // we'll also look at the expected media type, so don't just add this to the map // m.put("base64Binary", CBuiltinLeafInfo.BASE64_BYTE_ARRAY); m.put("hexBinary", CBuiltinLeafInfo.HEXBIN_BYTE_ARRAY); m.put("float", CBuiltinLeafInfo.FLOAT); m.put("decimal", CBuiltinLeafInfo.BIG_DECIMAL); m.put("integer", CBuiltinLeafInfo.BIG_INTEGER); m.put("long", CBuiltinLeafInfo.LONG); m.put("unsignedInt", CBuiltinLeafInfo.LONG); m.put("int", CBuiltinLeafInfo.INT); m.put("unsignedShort", CBuiltinLeafInfo.INT); m.put("short", CBuiltinLeafInfo.SHORT); m.put("unsignedByte", CBuiltinLeafInfo.SHORT); m.put("byte", CBuiltinLeafInfo.BYTE); m.put("double", CBuiltinLeafInfo.DOUBLE); m.put("QName", CBuiltinLeafInfo.QNAME); m.put("NOTATION", CBuiltinLeafInfo.QNAME); m.put("dateTime", CBuiltinLeafInfo.CALENDAR); m.put("date", CBuiltinLeafInfo.CALENDAR); m.put("time", CBuiltinLeafInfo.CALENDAR); m.put("gYearMonth", CBuiltinLeafInfo.CALENDAR); m.put("gYear", CBuiltinLeafInfo.CALENDAR); m.put("gMonthDay", CBuiltinLeafInfo.CALENDAR); m.put("gDay", CBuiltinLeafInfo.CALENDAR); m.put("gMonth", CBuiltinLeafInfo.CALENDAR); m.put("duration", CBuiltinLeafInfo.DURATION); m.put("token", CBuiltinLeafInfo.TOKEN); m.put("normalizedString",CBuiltinLeafInfo.NORMALIZED_STRING); m.put("ID", CBuiltinLeafInfo.ID); m.put("IDREF", CBuiltinLeafInfo.IDREF); // TODO: handling dateTime, time, and date type // String[] names = { // "date", "dateTime", "time", "hexBinary" }; } }

Other Java examples (source code examples)

Here is a short list of links related to this Java SimpleTypeBuilder.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.