use of com.sun.tools.xjc.model.CEnumLeafInfo 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")));
}
}
use of com.sun.tools.xjc.model.CEnumLeafInfo 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);
}
Aggregations