Search in sources :

Example 1 with CEnumConstant

use of com.sun.tools.xjc.model.CEnumConstant in project jaxb-ri by eclipse-ee4j.

the class BeanGenerator method generateEnumBody.

private void generateEnumBody(EnumOutline eo) {
    JDefinedClass type = eo.clazz;
    CEnumLeafInfo e = eo.target;
    XmlTypeWriter xtw = type.annotate2(XmlTypeWriter.class);
    writeTypeName(e.getTypeName(), xtw, eo._package().getMostUsedNamespaceURI());
    JCodeModel cModel = model.codeModel;
    // since constant values are never null, no point in using the boxed types.
    JType baseExposedType = e.base.toType(this, EXPOSED).unboxify();
    JType baseImplType = e.base.toType(this, Aspect.IMPLEMENTATION).unboxify();
    XmlEnumWriter xew = type.annotate2(XmlEnumWriter.class);
    xew.value(baseExposedType);
    boolean needsValue = e.needsValueField();
    // for each member <m>,
    // [RESULT]
    // <EnumName>(<deserializer of m>(<value>));
    // record generated field names to detect collision
    Set<String> enumFieldNames = new HashSet<>();
    for (CEnumConstant mem : e.members) {
        String constName = mem.getName();
        if (!JJavaName.isJavaIdentifier(constName)) {
            // didn't produce a name.
            getErrorReceiver().error(e.getLocator(), Messages.ERR_UNUSABLE_NAME.format(mem.getLexicalValue(), constName));
        }
        if (!enumFieldNames.add(constName)) {
            getErrorReceiver().error(e.getLocator(), Messages.ERR_NAME_COLLISION.format(constName));
        }
        // [RESULT]
        // <Const>(...)
        // ASSUMPTION: datatype is outline-independent
        JEnumConstant constRef = type.enumConstant(constName);
        if (needsValue) {
            constRef.arg(e.base.createConstant(this, new XmlString(mem.getLexicalValue())));
        }
        if (!mem.getLexicalValue().equals(constName)) {
            constRef.annotate2(XmlEnumValueWriter.class).value(mem.getLexicalValue());
        }
        // set javadoc
        if (mem.javadoc != null) {
            constRef.javadoc().append(mem.javadoc);
        }
        eo.constants.add(new EnumConstantOutline(mem, constRef) {
        });
    }
    if (needsValue) {
        // [RESULT]
        // final <valueType> value;
        JFieldVar $value = type.field(JMod.PRIVATE | JMod.FINAL, baseExposedType, "value");
        // [RESULT]
        // public <valuetype> value() { return value; }
        type.method(JMod.PUBLIC, baseExposedType, "value").body()._return($value);
        // [RESULT]
        // <constructor>(<valueType> v) {
        // this.value=v;
        // }
        {
            JMethod m = type.constructor(0);
            m.body().assign($value, m.param(baseImplType, "v"));
        }
        // [RESULT]
        // public static <Const> fromValue(<valueType> v) {
        // for( <Const> c : <Const>.values() ) {
        // if(c.value == v)   // or equals
        // return c;
        // }
        // throw new IllegalArgumentException(...);
        // }
        {
            JMethod m = type.method(JMod.PUBLIC | JMod.STATIC, type, "fromValue");
            JVar $v = m.param(baseExposedType, "v");
            JForEach fe = m.body().forEach(type, "c", type.staticInvoke("values"));
            JExpression eq;
            if (baseExposedType.isPrimitive()) {
                eq = fe.var().ref($value).eq($v);
            } else {
                eq = fe.var().ref($value).invoke("equals").arg($v);
            }
            fe.body()._if(eq)._then()._return(fe.var());
            JInvocation ex = JExpr._new(cModel.ref(IllegalArgumentException.class));
            JExpression strForm;
            if (baseExposedType.isPrimitive()) {
                strForm = cModel.ref(String.class).staticInvoke("valueOf").arg($v);
            } else if (baseExposedType == cModel.ref(String.class)) {
                strForm = $v;
            } else {
                strForm = $v.invoke("toString");
            }
            m.body()._throw(ex.arg(strForm));
        }
    } else {
        // [RESULT]
        // public String value() { return name(); }
        type.method(JMod.PUBLIC, String.class, "value").body()._return(JExpr.invoke("name"));
        // [RESULT]
        // public <Const> fromValue(String v) { return valueOf(v); }
        JMethod m = type.method(JMod.PUBLIC | JMod.STATIC, type, "fromValue");
        m.body()._return(JExpr.invoke("valueOf").arg(m.param(String.class, "v")));
    }
}
Also used : JDefinedClass(com.sun.codemodel.JDefinedClass) XmlTypeWriter(com.sun.tools.xjc.generator.annotation.spec.XmlTypeWriter) EnumConstantOutline(com.sun.tools.xjc.outline.EnumConstantOutline) XmlEnumValueWriter(com.sun.tools.xjc.generator.annotation.spec.XmlEnumValueWriter) XmlString(com.sun.xml.xsom.XmlString) CEnumLeafInfo(com.sun.tools.xjc.model.CEnumLeafInfo) JInvocation(com.sun.codemodel.JInvocation) XmlString(com.sun.xml.xsom.XmlString) JExpression(com.sun.codemodel.JExpression) JCodeModel(com.sun.codemodel.JCodeModel) CEnumConstant(com.sun.tools.xjc.model.CEnumConstant) XmlEnumWriter(com.sun.tools.xjc.generator.annotation.spec.XmlEnumWriter) JEnumConstant(com.sun.codemodel.JEnumConstant) JFieldVar(com.sun.codemodel.JFieldVar) JMethod(com.sun.codemodel.JMethod) JForEach(com.sun.codemodel.JForEach) JType(com.sun.codemodel.JType) HashSet(java.util.HashSet) JVar(com.sun.codemodel.JVar)

Example 2 with CEnumConstant

use of com.sun.tools.xjc.model.CEnumConstant in project jaxb-ri by eclipse-ee4j.

the class BIEnumeration method buildMemberList.

private static List<CEnumConstant> buildMemberList(Model model, Element dom) {
    List<CEnumConstant> r = new ArrayList<>();
    String members = DOMUtil.getAttribute(dom, "members");
    // TODO: error handling
    if (members == null)
        members = "";
    StringTokenizer tokens = new StringTokenizer(members);
    while (tokens.hasMoreTokens()) {
        String token = tokens.nextToken();
        r.add(new CEnumConstant(model.getNameConverter().toConstantName(token), null, token, null, /*TODO*/
        null, null));
    }
    return r;
}
Also used : StringTokenizer(java.util.StringTokenizer) ArrayList(java.util.ArrayList) CEnumConstant(com.sun.tools.xjc.model.CEnumConstant)

Example 3 with CEnumConstant

use of com.sun.tools.xjc.model.CEnumConstant in project jaxb-ri by eclipse-ee4j.

the class SimpleTypeBuilder method bindToTypeSafeEnum.

/**
 * 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 (// use the location of the simple type as the default
    loc == null)
        loc = type.getLocator();
    if (className == null) {
        // 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<pre>\n" + out.getBuffer() + "</pre>";
    }
    // build base type
    refererStack.push(type.getSimpleBaseType());
    TypeUse use = build(type.getSimpleBaseType());
    refererStack.pop();
    if (use.isCollection())
        // can't bind a list to enum constant
        return null;
    // for now just ignore that case
    CNonElement baseDt = use.getInfo();
    if (baseDt instanceof CClassInfo)
        // can't bind to an enum if the base is a class, since we don't have the value constrctor
        return null;
    // 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);
                }
                // recover from error
                return null;
            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);
}
Also used : XSVisitor(com.sun.xml.xsom.visitor.XSVisitor) CClassInfoParent(com.sun.tools.xjc.model.CClassInfoParent) BIConversion(com.sun.tools.xjc.reader.xmlschema.bindinfo.BIConversion) CEnumLeafInfo(com.sun.tools.xjc.model.CEnumLeafInfo) CEnumConstant(com.sun.tools.xjc.model.CEnumConstant) TypeUse(com.sun.tools.xjc.model.TypeUse) CClassInfo(com.sun.tools.xjc.model.CClassInfo) XSFacet(com.sun.xml.xsom.XSFacet) StringWriter(java.io.StringWriter) CNonElement(com.sun.tools.xjc.model.CNonElement) JavadocEscapeWriter(com.sun.codemodel.util.JavadocEscapeWriter) SchemaWriter(com.sun.xml.xsom.impl.util.SchemaWriter)

Example 4 with CEnumConstant

use of com.sun.tools.xjc.model.CEnumConstant in project jaxb-ri by eclipse-ee4j.

the class SimpleTypeBuilder method buildCEnumConstants.

/**
 * @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<String, BIEnumMember> members, XSFacet[] errorRef) {
    List<CEnumConstant> memberList = new ArrayList<>();
    int idx = 1;
    // to avoid duplicates. See issue #366
    Set<String> enums = new HashSet<>();
    for (XSFacet facet : type.getDeclaredFacets(XSFacet.FACET_ENUMERATION)) {
        String name = null;
        String mdoc = builder.getBindInfo(facet).getDocumentation();
        if (!enums.add(facet.getValue().value))
            // ignore the 2nd occasion
            continue;
        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;
            // unable to generate a name
            return null;
        }
        memberList.add(new CEnumConstant(name, mdoc, facet.getValue().value, facet, builder.getBindInfo(facet).toCustomizationList(), facet.getLocator()));
    }
    return memberList;
}
Also used : XSFacet(com.sun.xml.xsom.XSFacet) ArrayList(java.util.ArrayList) BIEnumMember(com.sun.tools.xjc.reader.xmlschema.bindinfo.BIEnumMember) CEnumConstant(com.sun.tools.xjc.model.CEnumConstant) HashSet(java.util.HashSet)

Aggregations

CEnumConstant (com.sun.tools.xjc.model.CEnumConstant)4 CEnumLeafInfo (com.sun.tools.xjc.model.CEnumLeafInfo)2 XSFacet (com.sun.xml.xsom.XSFacet)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 JCodeModel (com.sun.codemodel.JCodeModel)1 JDefinedClass (com.sun.codemodel.JDefinedClass)1 JEnumConstant (com.sun.codemodel.JEnumConstant)1 JExpression (com.sun.codemodel.JExpression)1 JFieldVar (com.sun.codemodel.JFieldVar)1 JForEach (com.sun.codemodel.JForEach)1 JInvocation (com.sun.codemodel.JInvocation)1 JMethod (com.sun.codemodel.JMethod)1 JType (com.sun.codemodel.JType)1 JVar (com.sun.codemodel.JVar)1 JavadocEscapeWriter (com.sun.codemodel.util.JavadocEscapeWriter)1 XmlEnumValueWriter (com.sun.tools.xjc.generator.annotation.spec.XmlEnumValueWriter)1 XmlEnumWriter (com.sun.tools.xjc.generator.annotation.spec.XmlEnumWriter)1 XmlTypeWriter (com.sun.tools.xjc.generator.annotation.spec.XmlTypeWriter)1 CClassInfo (com.sun.tools.xjc.model.CClassInfo)1