private static List<String> getAttributeView(ClassDescriptor cld) { List<String> view = new ArrayList<String>(); String basePath = cld.getUnqualifiedName() + "."; for (AttributeDescriptor att : cld.getAllAttributeDescriptors()) { if (!"id".equals(att.getName())) { view.add(basePath + att.getName()); } } return view; }
/** * Return a list of string paths that are defined as WebConfig to be shown in results. This will * include only attributes of the given class and not follow references. Optionally provide a * prefix to for creating a view for references/collections. * * @param type the class name to create a view for * @param model the model * @param webConfig we configuration * @param startingPath a path to prefix the class, can be null * @return the configured view paths for the class */ public static List<String> getDefaultViewForClass( String type, Model model, WebConfig webConfig, String startingPath) { String prefix = startingPath; List<String> view = new ArrayList<String>(); ClassDescriptor cld = model.getClassDescriptorByName(type); List<FieldConfig> fieldConfigs = getClassFieldConfigs(webConfig, cld); if (!StringUtils.isEmpty(prefix)) { try { // we can't add a subclass constraint, type must be same as the end of the prefix Path prefixPath = new Path(model, prefix); String prefixEndType = TypeUtil.unqualifiedName(prefixPath.getEndType().getName()); if (!prefixEndType.equals(type)) { throw new IllegalArgumentException( "Mismatch between end type of prefix: " + prefixEndType + " and type parameter: " + type); } } catch (PathException e) { LOG.error("Invalid path configured in webconfig for class: " + type); } } else { prefix = type; } for (FieldConfig fieldConfig : fieldConfigs) { String relPath = fieldConfig.getFieldExpr(); // only add attributes, don't follow references, following references can be problematic // when subclasses get involved. if (fieldConfig.getShowInResults()) { try { Path path = new Path(model, prefix + "." + relPath); // use type (e.g. Protein) not prefix (e.g. Gene.proteins) to do // attribute check Path checkIsOnlyAttribute = new Path(model, type + "." + relPath); if (checkIsOnlyAttribute.isOnlyAttribute()) { view.add(path.getNoConstraintsString()); } } catch (PathException e) { LOG.error("Invalid path configured in webconfig for class: " + type); } } } if (view.size() == 0) { for (AttributeDescriptor att : cld.getAllAttributeDescriptors()) { if (!"id".equals(att.getName())) { view.add(prefix + "." + att.getName()); } } } return view; }
/** * Return a List of Class objects corresponding to the fields returned by * getColumnFieldDescriptors(). * * @return the Class objects */ public List getColumnFieldClasses() { if (columnFieldClasses == null) { columnFieldClasses = new ArrayList(); for (int i = 0; i < columnFieldDescriptors.size(); i++) { AttributeDescriptor ad = (AttributeDescriptor) columnFieldDescriptors.get(i); if (ad == null) { columnFieldClasses.add(null); } else { String className = ad.getType(); columnFieldClasses.add(TypeUtil.instantiate(className)); } } } return columnFieldClasses; }
/** * Generates code for a single attribute. * * @param attr the AttributeDescriptor * @param field true if the class should have the associated field, or false if the field is in * the superclass * @return java code */ protected String generate(AttributeDescriptor attr, boolean field) { StringBuffer sb = new StringBuffer(); if (field) { sb.append( INDENT + "// Attr: " + attr.getClassDescriptor().getName() + "." + attr.getName() + ENDL) .append(INDENT + "protected ") .append(attr.getType()) .append(" ") .append(attr.getName()) .append(";" + ENDL); } sb.append(generateGetSet(attr, field)).append(ENDL); return sb.toString(); }
/** * Used for making a query for a reference or collection. Only used when a user clicks on [show * all] under an inline table on an Object's report page. The type of that object is * "startingPath", eg. Department. This path will be prepended to every path in the query. The * "type" is the type of the reference/collection, eg. Employee. * * <p>TODO use getDefaultViewForClass() instead * * @param objType class of object we are querying for eg. Manager * @param model the model * @param webConfig the webconfig * @param fieldType the type of the field this object is in, eg Employee * @return query, eg. Department.employees.name */ protected static PathQuery getQueryWithDefaultView( String objType, Model model, WebConfig webConfig, String fieldType) { String prefix = fieldType; PathQuery query = new PathQuery(model); ClassDescriptor cld = model.getClassDescriptorByName(objType); List<FieldConfig> fieldConfigs = getClassFieldConfigs(webConfig, cld); if (!StringUtils.isBlank(prefix)) { try { // if the type is different to the end of the prefix path, add a subclass constraint Path fieldPath = new Path(model, fieldType); String fieldEndType = TypeUtil.unqualifiedName(fieldPath.getEndType().getName()); if (!fieldEndType.equals(objType)) { query.addConstraint(Constraints.type(fieldType, objType)); } } catch (PathException e) { LOG.error("Invalid path configured in webconfig for class: " + objType); } } for (FieldConfig fieldConfig : fieldConfigs) { if (fieldConfig.getShowInResults()) { String path = prefix + "." + fieldConfig.getFieldExpr(); int from = prefix.length() + 1; while (path.indexOf('.', from) != -1) { int dotPos = path.indexOf('.', from); int nextDot = path.indexOf('.', dotPos + 1); String outerJoin = nextDot == -1 ? path.substring(0, dotPos) : path.substring(0, nextDot); query.setOuterJoinStatus(outerJoin, OuterJoinStatus.OUTER); from = dotPos + 1; } query.addView(path); } } if (query.getView().size() == 0) { for (AttributeDescriptor att : cld.getAllAttributeDescriptors()) { if (!"id".equals(att.getName())) { query.addView(prefix + "." + att.getName()); } } } return query; }
/** * Return a list of string paths that are defined as WebConfig to be shown in results. This will * include attributes of the given class and follow references. * * @param type the class name to create a view for * @param model the model * @param webConfig we configuration * @return the configured view paths for the class */ public static List<String> getDefaultViewForClass(String type, Model model, WebConfig webConfig) { List<String> view = new ArrayList<String>(); ClassDescriptor cld = model.getClassDescriptorByName(type); List<FieldConfig> fieldConfigs = FieldConfigHelper.getClassFieldConfigs(webConfig, cld); for (FieldConfig fieldConfig : fieldConfigs) { String relPath = fieldConfig.getFieldExpr(); // only add attributes, don't follow references, following references can be problematic // when subclasses get involved. if (fieldConfig.getShowInResults()) { try { Path path = new Path(model, type + "." + relPath); // add references if (path.isRootPath() || path.endIsReference()) { for (FieldConfig fc : FieldConfigHelper.getClassFieldConfigs(webConfig, path.getEndClassDescriptor())) { Path pathToAdd = new Path(model, path.toStringNoConstraints() + "." + fc.getFieldExpr()); if (pathToAdd.endIsAttribute() && (!view.contains(pathToAdd.getNoConstraintsString())) && (fc.getDisplayer() == null && fc.getShowInSummary())) { view.add(pathToAdd.getNoConstraintsString()); } } // add collections } else if (!path.endIsCollection()) { view.add(path.getNoConstraintsString()); } } catch (PathException e) { LOG.error("Invalid path configured in webconfig for class: " + type); } } } if (view.size() == 0) { for (AttributeDescriptor att : cld.getAllAttributeDescriptors()) { if (!"id".equals(att.getName())) { view.add(type + "." + att.getName()); } } } return view; }
/** * Generates the getFieldType method. * * @param cld the ClassDescriptor * @return a String with the method */ public String generateGetFieldType(ClassDescriptor cld) { StringBuffer sb = new StringBuffer(); sb.append(INDENT).append("public Class<?> getFieldType(final String fieldName) {\n"); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { sb.append(INDENT + INDENT) .append("if (\"" + field.getName() + "\".equals(fieldName)) {\n") .append(INDENT + INDENT + INDENT); if (field instanceof AttributeDescriptor) { AttributeDescriptor attribute = (AttributeDescriptor) field; if ("boolean".equals(attribute.getType())) { sb.append("return Boolean.TYPE;\n"); } else if ("short".equals(attribute.getType())) { sb.append("return Short.TYPE;\n"); } else if ("int".equals(attribute.getType())) { sb.append("return Integer.TYPE;\n"); } else if ("long".equals(attribute.getType())) { sb.append("return Long.TYPE;\n"); } else if ("float".equals(attribute.getType())) { sb.append("return Float.TYPE;\n"); } else if ("double".equals(attribute.getType())) { sb.append("return Double.TYPE;\n"); } else { sb.append("return " + attribute.getType() + ".class;\n"); } } else if (field.isReference()) { sb.append("return " + ((ReferenceDescriptor) field).getReferencedClassName() + ".class;\n"); } else { sb.append("return java.util.Set.class;\n"); } sb.append(INDENT + INDENT).append("}\n"); } sb.append(INDENT + INDENT) .append("if (!" + cld.getName() + ".class.equals(getClass())) {\n") .append(INDENT + INDENT + INDENT) .append("return TypeUtil.getFieldType(" + cld.getName() + ".class, fieldName);\n") .append(INDENT + INDENT) .append("}\n") .append(INDENT + INDENT) .append("throw new IllegalArgumentException(\"Unknown field \" + fieldName);\n") .append(INDENT) .append("}\n"); return sb.toString(); }
/** * Generates the setFieldValue method. * * @param cld the ClassDescriptor * @return a String with the method */ public String generateSetFieldValue(ClassDescriptor cld) { StringBuffer sb = new StringBuffer(); sb.append(INDENT) .append("public void setFieldValue(final String fieldName, final Object value) {\n") .append(INDENT + INDENT); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { sb.append("if (\"" + field.getName() + "\".equals(fieldName)) {\n"); String fieldName = field.getName(); if ("value".equals(fieldName)) { fieldName = "this.value"; } else if ("fieldName".equals(fieldName)) { fieldName = "this.fieldName"; } if (field instanceof AttributeDescriptor) { AttributeDescriptor attribute = (AttributeDescriptor) field; if ("boolean".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Boolean) value).booleanValue();\n"); } else if ("short".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Short) value).shortValue();\n"); } else if ("int".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Integer) value).intValue();\n"); } else if ("long".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Long) value).longValue();\n"); } else if ("float".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Float) value).floatValue();\n"); } else if ("double".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = ((Double) value).doubleValue();\n"); } else { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = (" + attribute.getType() + ") value;\n"); } } else if (field.isReference()) { sb.append(INDENT + INDENT + INDENT) .append(fieldName + " = (org.intermine.model.InterMineObject) value;\n"); } else { sb.append(INDENT + INDENT + INDENT).append(fieldName + " = (java.util.Set) value;\n"); } sb.append(INDENT + INDENT).append("} else "); } sb.append("{\n") .append(INDENT + INDENT + INDENT) .append("if (!" + cld.getName() + ".class.equals(getClass())) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("TypeUtil.setFieldValue(this, fieldName, value);\n") .append(INDENT + INDENT + INDENT + INDENT) .append("return;\n") .append(INDENT + INDENT + INDENT) .append("}\n") .append(INDENT + INDENT + INDENT) .append("throw new IllegalArgumentException(\"Unknown field \" + fieldName);\n") .append(INDENT + INDENT) .append("}\n") .append(INDENT) .append("}\n"); return sb.toString(); }
/** * Generates the getFieldValue method. * * @param cld the ClassDescriptor * @param proxy false to make the getFieldValue method, true to make the getFieldProxy method * @return a String with the method */ public String generateGetFieldValue(ClassDescriptor cld, boolean proxy) { StringBuffer sb = new StringBuffer(); sb.append(INDENT) .append( "public Object getField" + (proxy ? "Proxy" : "Value") + "(final String fieldName) throws IllegalAccessException {\n"); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { sb.append(INDENT + INDENT).append("if (\"" + field.getName() + "\".equals(fieldName)) {\n"); String fieldName = field.getName(); if ("fieldName".equals(fieldName)) { fieldName = "this.fieldName"; } if (field instanceof AttributeDescriptor) { AttributeDescriptor attribute = (AttributeDescriptor) field; if ("boolean".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append("return Boolean.valueOf(" + fieldName + ");\n"); } else if ("short".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT).append("return Short.valueOf(" + fieldName + ");\n"); } else if ("int".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT) .append("return Integer.valueOf(" + fieldName + ");\n"); } else if ("long".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT).append("return Long.valueOf(" + fieldName + ");\n"); } else if ("float".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT).append("return Float.valueOf(" + fieldName + ");\n"); } else if ("double".equals(attribute.getType())) { sb.append(INDENT + INDENT + INDENT).append("return Double.valueOf(" + fieldName + ");\n"); } else { sb.append(INDENT + INDENT + INDENT).append("return " + fieldName + ";\n"); } } else if (field.isReference()) { sb.append(INDENT + INDENT + INDENT); if (proxy) { sb.append("return " + fieldName + ";\n"); } else { sb.append("if (" + fieldName + " instanceof ProxyReference) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("return ((ProxyReference) " + fieldName + ").getObject();\n") .append(INDENT + INDENT + INDENT) .append("} else {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("return " + fieldName + ";\n") .append(INDENT + INDENT + INDENT) .append("}\n"); } } else { sb.append(INDENT + INDENT + INDENT).append("return " + fieldName + ";\n"); } sb.append(INDENT + INDENT).append("}\n"); } sb.append(INDENT + INDENT) .append("if (!" + cld.getName() + ".class.equals(getClass())) {\n") .append(INDENT + INDENT + INDENT) .append("return TypeUtil.getField" + (proxy ? "Proxy" : "Value") + "(this, fieldName);\n") .append(INDENT + INDENT) .append("}\n") .append(INDENT + INDENT) .append("throw new IllegalArgumentException(\"Unknown field \" + fieldName);\n") .append(INDENT) .append("}\n"); return sb.toString(); }
/** * Generates the setoBJECT method for deserialising objects. * * @param cld a ClassDescriptor * @return a String containing the method */ public String generateSetObject(ClassDescriptor cld) { StringBuffer sb = new StringBuffer(); sb.append(INDENT) .append("public void setoBJECT(String notXml, ObjectStore os) {\n") .append(INDENT + INDENT) .append("setoBJECT(NotXmlParser.SPLITTER.split(notXml), os);\n") .append(INDENT) .append("}\n") .append(INDENT) .append("public void setoBJECT(final String[] notXml, final ObjectStore os) {\n") .append(INDENT + INDENT) .append( "if (!" + cld.getName() + (cld.isInterface() ? "Shadow" : "") + ".class.equals(getClass())) {\n") .append(INDENT + INDENT + INDENT) .append( "throw new IllegalStateException(\"Class \" + getClass().getName() + \"" + " does not match code (" + cld.getName() + ")\");\n") .append(INDENT + INDENT) .append("}\n") .append(INDENT + INDENT) .append("for (int i = 2; i < notXml.length;) {\n") .append(INDENT + INDENT + INDENT) .append("int startI = i;\n"); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { String fieldName = field.getName(); if ("notXml".equals(fieldName)) { fieldName = "this.notXml"; } else if ("os".equals(fieldName)) { fieldName = "this.os"; } if (field instanceof AttributeDescriptor) { AttributeDescriptor attribute = (AttributeDescriptor) field; sb.append(INDENT + INDENT + INDENT) .append("if ((i < notXml.length) && \"a" + fieldName + "\".equals(notXml[i])) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("i++;\n") .append(INDENT + INDENT + INDENT + INDENT); if ("boolean".equals(attribute.getType())) { sb.append(fieldName + " = Boolean.parseBoolean(notXml[i]);\n"); } else if ("short".equals(attribute.getType())) { sb.append(fieldName + " = Short.parseShort(notXml[i]);\n"); } else if ("int".equals(attribute.getType())) { sb.append(fieldName + " = Integer.parseInt(notXml[i]);\n"); } else if ("long".equals(attribute.getType())) { sb.append(fieldName + " = Long.parseLong(notXml[i]);\n"); } else if ("float".equals(attribute.getType())) { sb.append(fieldName + " = Float.parseFloat(notXml[i]);\n"); } else if ("double".equals(attribute.getType())) { sb.append(fieldName + " = Double.parseDouble(notXml[i]);\n"); } else if ("java.lang.Boolean".equals(attribute.getType())) { sb.append(fieldName + " = Boolean.valueOf(notXml[i]);\n"); } else if ("java.lang.Short".equals(attribute.getType())) { sb.append(fieldName + " = Short.valueOf(notXml[i]);\n"); } else if ("java.lang.Integer".equals(attribute.getType())) { sb.append(fieldName + " = Integer.valueOf(notXml[i]);\n"); } else if ("java.lang.Long".equals(attribute.getType())) { sb.append(fieldName + " = Long.valueOf(notXml[i]);\n"); } else if ("java.lang.Float".equals(attribute.getType())) { sb.append(fieldName + " = Float.valueOf(notXml[i]);\n"); } else if ("java.lang.Double".equals(attribute.getType())) { sb.append(fieldName + " = Double.valueOf(notXml[i]);\n"); } else if ("java.util.Date".equals(attribute.getType())) { sb.append(fieldName + " = new java.util.Date(Long.parseLong(notXml[i]));\n"); } else if ("java.math.BigDecimal".equals(attribute.getType())) { sb.append(fieldName + " = new java.math.BigDecimal(notXml[i]);\n"); } else if ("org.intermine.objectstore.query.ClobAccess".equals(attribute.getType())) { sb.append( fieldName + " = org.intermine.objectstore.query.ClobAccess" + ".decodeDbDescription(os, notXml[i]);\n"); } else if ("java.lang.String".equals(attribute.getType())) { sb.append("StringBuilder string = null;\n") .append(INDENT + INDENT + INDENT + INDENT) .append( "while ((i + 1 < notXml.length) && (notXml[i + 1].charAt(0) == '" + ENCODED_DELIM + "')) {\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("if (string == null) string = new StringBuilder(notXml[i]);\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("i++;\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("string.append(\"" + DELIM + "\").append(notXml[i].substring(1));\n") .append(INDENT + INDENT + INDENT + INDENT) .append("}\n") .append(INDENT + INDENT + INDENT + INDENT) .append(fieldName + " = string == null ? notXml[i] : string.toString();\n"); } else { throw new IllegalArgumentException("Unknown type " + attribute.getType()); } sb.append(INDENT + INDENT + INDENT + INDENT) .append("i++;\n") .append(INDENT + INDENT + INDENT) .append("}\n"); } else if (field.isReference()) { ReferenceDescriptor reference = (ReferenceDescriptor) field; sb.append(INDENT + INDENT + INDENT) .append("if ((i < notXml.length) &&\"r" + fieldName + "\".equals(notXml[i])) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("i++;\n") .append(INDENT + INDENT + INDENT + INDENT) .append( fieldName + " = new ProxyReference(os, Integer.valueOf(notXml[i])" + ", " + reference.getReferencedClassName() + ".class);\n") .append(INDENT + INDENT + INDENT + INDENT) .append("i++;\n") .append(INDENT + INDENT + INDENT) .append("};\n"); } } sb.append(INDENT + INDENT + INDENT) .append("if (startI == i) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("throw new IllegalArgumentException(\"Unknown field \" + notXml[i]);\n") .append(INDENT + INDENT + INDENT) .append("}\n") .append(INDENT + INDENT) .append("}\n"); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { String fieldName = field.getName(); if ("notXml".equals(fieldName)) { fieldName = "this.notXml"; } else if ("os".equals(fieldName)) { fieldName = "this.os"; } if (field instanceof CollectionDescriptor) { CollectionDescriptor coll = (CollectionDescriptor) field; sb.append(INDENT + INDENT) .append( fieldName + " = new ProxyCollection<" + coll.getReferencedClassName() + ">(os, this, \"" + fieldName + "\", " + coll.getReferencedClassName() + ".class);\n"); } } sb.append(INDENT).append("}\n"); return sb.toString(); }
/** * Generates the getoBJECT method for producing NotXml. * * @param cld the ClassDescriptor * @return generated java code as a String */ protected String generateGetObject(ClassDescriptor cld) { StringBuffer sb = new StringBuffer(); sb.append(INDENT) .append("public StringConstructor getoBJECT() {\n") .append(INDENT + INDENT) .append( "if (!" + cld.getName() + (cld.isInterface() ? "Shadow" : "") + ".class.equals(getClass())) {\n") .append(INDENT + INDENT + INDENT) .append("return NotXmlRenderer.render(this);\n") .append(INDENT + INDENT) .append("}\n") .append(INDENT + INDENT) .append("StringConstructor sb = new StringConstructor();\n") .append(INDENT + INDENT) .append("sb.append(\"" + DELIM + cld.getName() + "\");\n"); for (FieldDescriptor field : cld.getAllFieldDescriptors()) { if (field instanceof AttributeDescriptor) { AttributeDescriptor attribute = (AttributeDescriptor) field; if (attribute.getType().startsWith("java.")) { sb.append(INDENT + INDENT) .append("if (" + attribute.getName() + " != null) {\n") .append(INDENT + INDENT + INDENT) .append("sb.append(\"" + DELIM + "a" + field.getName() + DELIM + "\")"); if ("java.util.Date".equals(attribute.getType())) { sb.append(".append(" + attribute.getName() + ".getTime());\n"); } else if ("java.lang.String".equals(attribute.getType())) { sb.append(";\n") .append(INDENT + INDENT + INDENT) .append("String string = " + attribute.getName() + ";\n") .append(INDENT + INDENT + INDENT) .append("while (string != null) {\n") .append(INDENT + INDENT + INDENT + INDENT) .append("int delimPosition = string.indexOf(\"" + DELIM + "\");\n") .append(INDENT + INDENT + INDENT + INDENT) .append("if (delimPosition == -1) {\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("sb.append(string);\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("string = null;\n") .append(INDENT + INDENT + INDENT + INDENT) .append("} else {\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("sb.append(string.substring(0, delimPosition + 3));\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("sb.append(\"" + ENCODED_DELIM + "\");\n") .append(INDENT + INDENT + INDENT + INDENT + INDENT) .append("string = string.substring(delimPosition + 3);\n") .append(INDENT + INDENT + INDENT + INDENT) .append("}\n") .append(INDENT + INDENT + INDENT) .append("}\n"); } else { sb.append(".append(" + attribute.getName() + ");\n"); } sb.append(INDENT + INDENT).append("}\n"); } else if ("org.intermine.objectstore.query.ClobAccess".equals(attribute.getType())) { sb.append(INDENT + INDENT) .append("if (" + attribute.getName() + " != null) {\n") .append(INDENT + INDENT + INDENT) .append("sb.append(\"" + DELIM + "a" + field.getName() + DELIM + "\" + ") .append(attribute.getName() + ".getDbDescription());\n") .append(INDENT + INDENT) .append("}\n"); } else { sb.append(INDENT) .append(INDENT) .append("sb.append(\"" + DELIM + "a" + field.getName() + DELIM + "\")") .append(".append(" + field.getName() + ");\n"); } } else if (field.isReference()) { sb.append(INDENT + INDENT) .append("if (" + field.getName() + " != null) {\n") .append(INDENT + INDENT + INDENT) .append("sb.append(\"" + DELIM + "r" + field.getName() + DELIM + "\")") .append(".append(" + field.getName() + ".getId());\n") .append(INDENT + INDENT) .append("}\n"); } } sb.append(INDENT + INDENT).append("return sb;\n").append(INDENT).append("}\n"); return sb.toString(); }