Adding simple setters for primitives

This commit is contained in:
jamesagnew 2014-02-25 08:43:55 -05:00
parent 2640ed9feb
commit e38740ac20
8 changed files with 199 additions and 44 deletions

View File

@ -0,0 +1,24 @@
package ca.uhn.fhir.model.api.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marker annotation for a primitive setter method that can be used to
* indicate a "simple setter" method on a resource or composite type
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value= {ElementType.CONSTRUCTOR})
public @interface SimpleSetter {
// nothing for now
@Retention(RetentionPolicy.RUNTIME)
@Target(value= {ElementType.PARAMETER})
public @interface Parameter {
String name();
}
}

View File

@ -1,12 +1,16 @@
<Profile xmlns="http://hl7.org/fhir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://hl7.org/fhir ./fhir-single.xsd">
<identifier value="urn:uhn:fhir:profile:sail" />
<identifier value="urn:uhn:fhir:profile:cgta" />
<version value="0.1" />
<name value="SAIL Object Profile" />
<status value="draft" />
<structure>
<type value="Patient" />
<element>
<path value="Patient.identifier"/>
</element>
</structure>

View File

@ -8,6 +8,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@ -21,11 +23,13 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.starter.model.BaseElement;
import ca.uhn.fhir.starter.model.Child;
import ca.uhn.fhir.starter.model.Extension;
import ca.uhn.fhir.starter.model.Resource;
import ca.uhn.fhir.starter.model.ResourceBlock;
import ca.uhn.fhir.starter.model.SimpleSetter.Parameter;
import ca.uhn.fhir.starter.util.XMLUtils;
public abstract class BaseParser {
@ -102,12 +106,61 @@ public abstract class BaseParser {
}
parent.getChildren().add(elem);
/*
* Find simple setters
*/
if (elem instanceof Child) {
scanForSimpleSetters(elem);
}
}
write(resource);
}
private void scanForSimpleSetters(Child theElem) {
Class<?> childDt;
if (theElem.getReferenceTypesForMultiple().size() == 1) {
try {
childDt = Class.forName("ca.uhn.fhir.model.primitive." + theElem.getReferenceTypesForMultiple().get(0));
} catch (ClassNotFoundException e) {
return;
}
} else {
return;
}
for (Constructor<?> nextConstructor : childDt.getConstructors()) {
SimpleSetter simpleSetter = nextConstructor.getAnnotation(SimpleSetter.class);
if (simpleSetter == null) {
continue;
}
ca.uhn.fhir.starter.model.SimpleSetter ss = new ca.uhn.fhir.starter.model.SimpleSetter();
ss.setDatatype(childDt.getSimpleName());
theElem.getSimpleSetters().add(ss);
Annotation[][] paramAnn = nextConstructor.getParameterAnnotations();
Class<?>[] paramTypes = nextConstructor.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
Parameter p = new Parameter();
p.setDatatype(paramTypes[0].getSimpleName());
p.setParameter(findAnnotation(childDt, paramAnn[i], SimpleSetter.Parameter.class).name());
ss.getParameters().add(p);
}
}
}
private ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter findAnnotation(Class<?> theBase, Annotation[] theAnnotations, Class<ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter> theClass) {
for (Annotation next : theAnnotations) {
if (theClass.equals(next.annotationType())) {
return (ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter) next;
}
}
throw new IllegalArgumentException(theBase.getCanonicalName() + " has @" + SimpleSetter.class.getCanonicalName() + " constructor with no/invalid parameter annotation");
}
public void setDirectory(String theDirectory) {
myDirectory = theDirectory;
}
@ -165,6 +218,7 @@ public abstract class BaseParser {
VelocityEngine v = new VelocityEngine();
v.setProperty("resource.loader", "cp");
v.setProperty("cp.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
v.setProperty("runtime.references.strict", Boolean.TRUE);
InputStream templateIs = ResourceParser.class.getResourceAsStream(getTemplate());
InputStreamReader templateReader = new InputStreamReader(templateIs);

View File

@ -1,10 +1,5 @@
package ca.uhn.fhir.starter;
import java.util.ArrayList;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.starter.model.Extension;
public class ResourceParser extends BaseParser {
private String myResourceName;

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.starter.model;
import static org.apache.commons.lang.StringUtils.*;
import java.util.ArrayList;
import java.util.List;
@ -48,7 +50,7 @@ public abstract class BaseElement {
}
public String getDefinition() {
return myDefinition;
return defaultString(myDefinition, "");
}
public String getElementName() {

View File

@ -8,8 +8,10 @@ import ca.uhn.fhir.model.api.ResourceReference;
public class Child extends BaseElement {
public boolean isBlock() {
return false;
private List<SimpleSetter> mySimpleStters = new ArrayList<SimpleSetter>();
public String getAnnotationType() {
return getSingleType();
}
public String getCardMaxForChildAnnotation() {
@ -20,16 +22,21 @@ public class Child extends BaseElement {
}
}
public List<String> getReferenceTypesForMultiple() {
ArrayList<String> retVal = new ArrayList<String>();
for (String next : getType()) {
retVal.add(next + "Dt");
/**
* Strips off "[x]"
*/
public String getElementNameSimplified() {
String elementName = getElementName();
if (elementName.endsWith("[x]")) {
elementName = elementName.substring(0, elementName.length() - 3);
}
return retVal;
return elementName;
}
public String getAnnotationType() {
return getSingleType();
public String getMethodName() {
String elementName = getElementNameSimplified();
elementName = elementName.substring(0, 1).toUpperCase() + elementName.substring(1);
return elementName;
}
public String getReferenceType() {
@ -53,6 +60,35 @@ public class Child extends BaseElement {
return retVal;
}
public String getReferenceTypeForConstructor() {
return getReferenceType().replaceAll("^List<", "ArrayList<");
}
public List<String> getReferenceTypesForMultiple() {
ArrayList<String> retVal = new ArrayList<String>();
for (String next : getType()) {
retVal.add(next + "Dt");
}
return retVal;
}
public List<SimpleSetter> getSimpleSetters() {
return mySimpleStters;
}
public String getVariableName() {
String elementName = getMethodName();
return "my" + elementName;
}
public boolean isBlock() {
return false;
}
public boolean isRepeatable() {
return "1".equals(getCardMax()) == false;
}
protected String getSingleType() {
String retVal;
String elemName = this.getType().get(0);
@ -65,30 +101,4 @@ public class Child extends BaseElement {
return retVal;
}
public boolean isRepeatable() {
return "1".equals(getCardMax()) == false;
}
public String getVariableName() {
String elementName = getMethodName();
return "my" + elementName;
}
public String getMethodName() {
String elementName = getElementNameSimplified();
elementName = elementName.substring(0, 1).toUpperCase() + elementName.substring(1);
return elementName;
}
/**
* Strips off "[x]"
*/
public String getElementNameSimplified() {
String elementName = getElementName();
if (elementName.endsWith("[x]")) {
elementName = elementName.substring(0, elementName.length() - 3);
}
return elementName;
}
}

View File

@ -0,0 +1,46 @@
package ca.uhn.fhir.starter.model;
import java.util.ArrayList;
import java.util.List;
public class SimpleSetter {
private List<Parameter> myParameters = new ArrayList<Parameter>();
private String myDatatype;
public String getDatatype() {
return myDatatype;
}
public void setDatatype(String theDatatype) {
myDatatype = theDatatype;
}
public List<Parameter> getParameters() {
return myParameters;
}
public static class Parameter {
private String myDatatype;
private String myParameter;
public String getDatatype() {
return myDatatype;
}
public String getParameter() {
return myParameter;
}
public void setDatatype(String theDatatype) {
myDatatype = theDatatype;
}
public void setParameter(String theParameter) {
myParameter = theParameter;
}
}
}

View File

@ -35,7 +35,8 @@
#macro ( childAccessors $childElements )
#foreach ( $child in $children )
/**
* Gets the value(s) for ${child.elementName} (${child.shortName})
* Gets the value(s) for <b>${child.elementName}</b>, creating it if it does
* not exist (${child.shortName}). Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
@ -43,11 +44,16 @@
* </p>
*/
public ${child.referenceType} get${child.methodName}() {
#if ( $!child.hasMultipleTypes )
if (${child.variableName} == null) {
${child.variableName} = new ${child.referenceTypeForConstructor}();
}
#end
return ${child.variableName};
}
/**
* Sets the value(s) for ${child.elementName} (${child.shortName})
* Sets the value(s) for <b>${child.elementName}</b> (${child.shortName})
*
* <p>
* <b>Definition:</b>
@ -58,6 +64,20 @@
${child.variableName} = theValue;
}
#foreach ( $ss in $child.simpleSetters )
/**
* Sets the value(s) for <b>${child.elementName}</b> (${child.shortName})
*
* <p>
* <b>Definition:</b>
* ${child.definition}
* </p>
*/
public void set${child.methodName}(#{foreach}($param in $ss.parameters) ${param.datatype} ${param.parameter}#{if}( $foreach.hasNext ), #{end}#{end}) {
${child.variableName} = new ${ss.datatype}(#{foreach}($param in $ss.parameters) ${param.parameter}#{if}( $foreach.hasNext ), #{end}#{end});
}
#end
#end
#end