/* * Copyright 2015 Workday, Inc. * * This software is available under the MIT license. * Please see the LICENSE.txt file in this project. */ package com.workday.autoparse.xml.codegen; import com.squareup.javawriter.JavaWriter; import com.workday.autoparse.xml.parser.ParseException; import com.workday.autoparse.xml.parser.XmlElementParser; import com.workday.autoparse.xml.parser.XmlStreamReader; import com.workday.autoparse.xml.utils.CollectionUtils; import com.workday.autoparse.xml.utils.StringUtils; import com.workday.meta.MetaTypes; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Map; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic; /** * Writes the {@code parseAttributes} method in an {@link XmlElementParser}. * * @author nathan.taylor * @since 2013-10-14 */ class ParseAttributesMethodWriter { private final AttributesAndElements attributesAndElements; private final ProcessingEnvironment processingEnv; private final MetaTypes metaTypes; public ParseAttributesMethodWriter(AttributesAndElements attributesAndElements, ProcessingEnvironment processingEnv, MetaTypes metaTypes) { this.attributesAndElements = attributesAndElements; this.processingEnv = processingEnv; this.metaTypes = metaTypes; } public void writeParseAttributesMethod(TypeElement classElement, JavaWriter writer) throws IOException { List<String> parameters = new ArrayList<String>(4); parameters.add(classElement.getSimpleName().toString()); parameters.add("object"); parameters.add(XmlStreamReader.class.getSimpleName()); parameters.add("reader"); writer.beginMethod("void", "parseAttributes", EnumSet.of(Modifier.PRIVATE), parameters, CollectionUtils.newArrayList(ParseException.class.getSimpleName())); writer.emitStatement("Attributes attributes = new Attributes(reader)"); for (Map.Entry<List<String>, Element> entry : attributesAndElements.getAttributes() .entrySet()) { List<String> names = entry.getKey(); Element attributeElement = entry.getValue(); writeAttributeAssignment(names, attributeElement, writer); } Element textContent = attributesAndElements.getTextContentElement(); writer.emitField("String", "contentString", EnumSet.noneOf(Modifier.class), "attributes.getContentString()"); writer.beginControlFlow("if (contentString != null)"); if (textContent instanceof ExecutableElement) { writer.emitStatement("object.%s(contentString)", textContent.getSimpleName()); } else if (textContent instanceof VariableElement) { writer.emitStatement("object.%s = contentString", textContent.getSimpleName()); } writer.endControlFlow(); writer.endMethod(); } private void writeAttributeAssignment(List<String> names, Element attributeElement, JavaWriter writer) throws IOException { String ifPattern = "if (attributes.hasAttribute(\"%s\"))"; String initializationPattern = getAttributeInitializationPattern(attributeElement); String assignmentPattern; if (attributeElement instanceof ExecutableElement) { assignmentPattern = String.format(Locale.US, "object.%s(%s)", attributeElement.getSimpleName(), initializationPattern); } else { assignmentPattern = String.format(Locale.US, "object.%s = %s", attributeElement.getSimpleName(), initializationPattern); } String name = names.get(0); writer.beginControlFlow(String.format(ifPattern, name)); writer.emitStatement(assignmentPattern, name); for (int i = 1; i < names.size(); i++) { name = names.get(i); writer.nextControlFlow(String.format("else " + ifPattern, name)); writer.emitStatement(assignmentPattern, name); } writer.endControlFlow(); } private String getAttributeInitializationPattern(Element element) { String method = null; TypeMirror type; if (element instanceof ExecutableElement) { type = ((ExecutableElement) element).getParameters().get(0).asType(); } else { type = element.asType(); } String stringMethod = "attributes.getStringAttributeWithName(\"%s\")"; if (metaTypes.isBoxable(type)) { String primitiveName = StringUtils.capitalize(metaTypes.asPrimitive(type).toString()); method = "attributes.get" + primitiveName + "AttributeWithName(\"%s\")"; } else if (metaTypes.isString(type)) { method = stringMethod; } else if (metaTypes.isSameType(type, BigDecimal.class) || metaTypes.isSameType(type, BigInteger.class)) { method = "new " + type.toString() + "(" + stringMethod + ")"; } else { processingEnv.getMessager() .printMessage(Diagnostic.Kind.ERROR, String.format("%s is not a supported attribute type", type), element); } return method; } }