blob: b95ea612838f6f62035802b5345b77d398aed3e0 [file] [log] [blame]
#*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*#
#parse ( "common.vm" )
#
#set ( $package = "${packageToolV4}" )
#set ( $className = "${model.name}Xpp3Reader" )
#
#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
#set ( $rootXml = $Helper.xmlClassMetadata( $root ) )
#set ( $rootTag = $rootXml.tagName )
#set ( $rootUcapName = $Helper.capitalise( $root.name ) )
#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) )
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.api.annotations.Generated;
import org.apache.maven.internal.xml.XmlNodeBuilder;
#foreach ( $class in $model.allClasses )
import ${packageModelV4}.${class.name};
#end
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Generated
public class ${className} {
private boolean addDefaultEntities = true;
private final ContentTransformer contentTransformer;
public ${className}() {
this((s, f) -> s);
}
public ${className}(ContentTransformer contentTransformer) {
this.contentTransformer = contentTransformer;
}
/**
* Method checkFieldWithDuplicate.
*
* @param parser a parser object.
* @param parsed a parsed object.
* @param alias a alias object.
* @param tagName a tagName object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return boolean
*/
private boolean checkFieldWithDuplicate(XmlPullParser parser, String tagName, String alias, Set<String> parsed)
throws XmlPullParserException {
if (!(parser.getName().equals(tagName) || parser.getName().equals(alias))) {
return false;
}
if (!parsed.add(tagName)) {
throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
}
return true;
} //-- boolean checkFieldWithDuplicate(XmlPullParser, String, String, Set<String>)
/**
* Method checkUnknownAttribute.
*
* @param parser a parser object.
* @param strict a strict object.
* @param tagName a tagName object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @throws IOException IOException if any.
*/
private void checkUnknownAttribute(XmlPullParser parser, String attribute, String tagName, boolean strict)
throws XmlPullParserException, IOException {
// strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too
if (strict) {
throw new XmlPullParserException("Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null);
}
} //-- void checkUnknownAttribute(XmlPullParser, String, String, boolean)
/**
* Method checkUnknownElement.
*
* @param parser a parser object.
* @param strict a strict object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @throws IOException IOException if any.
*/
private void checkUnknownElement(XmlPullParser parser, boolean strict)
throws XmlPullParserException, IOException {
if (strict) {
throw new XmlPullParserException("Unrecognised tag: '" + parser.getName() + "'", parser, null);
}
for (int unrecognizedTagCount = 1; unrecognizedTagCount > 0;) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
unrecognizedTagCount++;
} else if (eventType == XmlPullParser.END_TAG) {
unrecognizedTagCount--;
}
}
} //-- void checkUnknownElement(XmlPullParser, boolean)
/**
* Returns the state of the "add default entities" flag.
*
* @return boolean
*/
public boolean getAddDefaultEntities() {
return addDefaultEntities;
} //-- boolean getAddDefaultEntities()
/**
* Method getBooleanValue.
*
* @param s a s object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return boolean
*/
private boolean getBooleanValue(String s, String attribute, XmlPullParser parser)
throws XmlPullParserException {
return getBooleanValue(s, attribute, parser, false);
} //-- boolean getBooleanValue(String, String, XmlPullParser)
/**
* Method getBooleanValue.
*
* @param s a s object.
* @param defaultValue a defaultValue object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return boolean
*/
private boolean getBooleanValue(String s, String attribute, XmlPullParser parser, boolean defaultValue)
throws XmlPullParserException {
if (s != null && s.length() != 0) {
return Boolean.valueOf(s).booleanValue();
}
return defaultValue;
} //-- boolean getBooleanValue(String, String, XmlPullParser, String)
/**
* Method getByteValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return byte
*/
private byte getByteValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s != null) {
try {
return Byte.valueOf(s).byteValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a byte", parser, nfe);
}
}
}
return 0;
} //-- byte getByteValue(String, String, XmlPullParser, boolean)
/**
* Method getCharacterValue.
*
* @param s a s object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return char
*/
private char getCharacterValue(String s, String attribute, XmlPullParser parser)
throws XmlPullParserException {
if (s != null) {
return s.charAt(0);
}
return 0;
} //-- char getCharacterValue(String, String, XmlPullParser)
/**
* Method getDateValue.
*
* @param s a s object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return Date
*/
private Date getDateValue(String s, String attribute, XmlPullParser parser)
throws XmlPullParserException {
return getDateValue(s, attribute, null, parser);
} //-- Date getDateValue(String, String, XmlPullParser)
/**
* Method getDateValue.
*
* @param s a s object.
* @param parser a parser object.
* @param dateFormat a dateFormat object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return Date
*/
private Date getDateValue(String s, String attribute, String dateFormat, XmlPullParser parser)
throws XmlPullParserException {
if (s != null) {
String effectiveDateFormat = dateFormat;
if (dateFormat == null) {
effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
}
if ("long".equals(effectiveDateFormat)) {
try {
return new java.util.Date(Long.parseLong(s));
} catch (NumberFormatException e) {
throw new XmlPullParserException(e.getMessage(), parser, e);
}
} else {
try {
DateFormat dateParser = new java.text.SimpleDateFormat(effectiveDateFormat, java.util.Locale.US);
return dateParser.parse(s);
} catch (java.text.ParseException e) {
throw new XmlPullParserException(e.getMessage(), parser, e);
}
}
}
return null;
} //-- Date getDateValue(String, String, String, XmlPullParser)
/**
* Method getDoubleValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return double
*/
private double getDoubleValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s != null) {
try {
return Double.valueOf(s).doubleValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
}
}
}
return 0;
} //-- double getDoubleValue(String, String, XmlPullParser, boolean)
/**
* Method getFloatValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return float
*/
private float getFloatValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s != null) {
try {
return Float.valueOf(s).floatValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
}
}
}
return 0;
} //-- float getFloatValue(String, String, XmlPullParser, boolean)
/**
* Method getIntegerValue.
*
* @param s a s object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return int
*/
private int getIntegerValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
return getIntegerValue(s, attribute, parser, strict, 0);
} //-- int getBooleanValue(String, String, XmlPullParser)
/**
* Method getIntegerValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return int
*/
private int getIntegerValue(String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue)
throws XmlPullParserException {
if (s != null) {
try {
return Integer.valueOf(s).intValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be an integer", parser, nfe);
}
}
}
return defaultValue;
} //-- int getIntegerValue(String, String, XmlPullParser, boolean, int)
/**
* Method getLongValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return long
*/
private long getLongValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s != null) {
try {
return Long.valueOf(s).longValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a long integer", parser, nfe);
}
}
}
return 0;
} //-- long getLongValue(String, String, XmlPullParser, boolean)
/**
* Method getRequiredAttributeValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return String
*/
private String getRequiredAttributeValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s == null) {
if (strict) {
throw new XmlPullParserException("Missing required value for attribute '" + attribute + "'", parser, null);
}
}
return s;
} //-- String getRequiredAttributeValue(String, String, XmlPullParser, boolean)
/**
* Method getShortValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return short
*/
private short getShortValue(String s, String attribute, XmlPullParser parser, boolean strict)
throws XmlPullParserException {
if (s != null) {
try {
return Short.valueOf(s).shortValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a short integer", parser, nfe);
}
}
}
return 0;
} //-- short getShortValue(String, String, XmlPullParser, boolean)
/**
* Method getTrimmedValue.
*
* @param s a s object.
* @return String
*/
private String getTrimmedValue(String s) {
if (s != null) {
s = s.trim();
}
return s;
} //-- String getTrimmedValue(String)
/**
* Method interpolatedTrimmed.
*
* @param value a value object.
* @param context a context object.
* @return String
*/
private String interpolatedTrimmed(String value, String context) {
return getTrimmedValue(contentTransformer.transform(value, context));
} //-- String interpolatedTrimmed(String, String)
/**
* Method nextTag.
*
* @param parser a parser object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return int
*/
private int nextTag(XmlPullParser parser) throws IOException, XmlPullParserException {
int eventType = parser.next();
if (eventType == XmlPullParser.TEXT) {
eventType = parser.next();
}
if (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG) {
throw new XmlPullParserException("expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null);
}
return eventType;
} //-- int nextTag(XmlPullParser)
/**
* @see ReaderFactory#newXmlReader
*
* @param reader a reader object.
* @param strict a strict object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return ${root.name}
*/
public ${root.name} read(Reader reader, boolean strict) throws IOException, XmlPullParserException {
XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser();
parser.setInput(reader);
return read(parser, strict);
} //-- ${root.name} read(Reader, boolean)
/**
* @see ReaderFactory#newXmlReader
*
* @param reader a reader object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return ${root.name}
*/
public ${root.name} read(Reader reader) throws IOException, XmlPullParserException {
return read(reader, true);
} //-- ${root.name} read(Reader)
/**
* Method read.
*
* @param in a in object.
* @param strict a strict object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return ${root.name}
*/
public ${root.name} read(InputStream in, boolean strict) throws IOException, XmlPullParserException {
return read(ReaderFactory.newXmlReader(in), strict);
} //-- ${root.name} read(InputStream, boolean)
/**
* Method read.
*
* @param in a in object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return ${root.name}
*/
public ${root.name} read(InputStream in) throws IOException, XmlPullParserException {
return read(ReaderFactory.newXmlReader(in));
} //-- ${root.name} read(InputStream)
/**
* Method read.
*
* @param parser a parser object.
* @param strict a strict object.
* @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
* @return ${root.name}
*/
public ${root.name} read(XmlPullParser parser, boolean strict) throws IOException, XmlPullParserException {
$rootUcapName $rootLcapName = null;
int eventType = parser.getEventType();
boolean parsed = false;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (strict && ! "${rootTag}".equals(parser.getName())) {
throw new XmlPullParserException("Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null);
} else if (parsed) {
// fallback, already expected a XmlPullParserException due to invalid XML
throw new XmlPullParserException("Duplicated tag: '${rootTag}'", parser, null);
}
$rootLcapName = parse${rootUcapName}(parser, strict);
parsed = true;
}
eventType = parser.next();
}
if (parsed) {
return $rootLcapName;
}
throw new XmlPullParserException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null);
} //-- ${root.name} read(XmlPullParser, boolean)
#foreach ( $class in $model.allClasses )
#if ( $class.name != "InputSource" && $class.name != "InputLocation" )
#set ( $classUcapName = $Helper.capitalise( $class.name ) )
#set ( $classLcapName = $Helper.uncapitalise( $class.name ) )
#set ( $ancestors = $Helper.ancestors( $class ) )
#set ( $allFields = [] )
#foreach ( $cl in $ancestors )
#set ( $dummy = $allFields.addAll( $cl.getFields($version) ) )
#end
private ${classUcapName} parse${classUcapName}(XmlPullParser parser, boolean strict)
throws IOException, XmlPullParserException {
String tagName = parser.getName();
${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true);
for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
String name = parser.getAttributeName(i);
String value = parser.getAttributeValue(i);
if (name.indexOf(':') >= 0) {
// just ignore attributes with non-default namespace (for example: xmlns:xsi)
#if ( $class == $root )
} else if ("xmlns".equals(name)) {
// ignore xmlns attribute in root class, which is a reserved attribute name
#end
}
#foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).attribute )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#set ( $fieldCapName = $Helper.capitalise( $field.name ) )
else if ("$fieldTagName".equals(name)) {
#if ( $field.type == "String" )
${classLcapName}.${field.name}(interpolatedTrimmed(value, "$fieldTagName"));
#elseif ( $field.type == "boolean" || $field.type == "Boolean" )
${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(value, "$fieldTagName"), "$fieldTagName", parser, ${field.defaultValue}));
#else
// TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
#end
}
#end
#end
else {
checkUnknownAttribute(parser, name, tagName, strict);
}
}
Set<String> parsed = new HashSet<>();
#foreach ( $field in $allFields )
#if ( $Helper.isFlatItems( $field ) )
List<$field.to> ${field.name} = new ArrayList<>();
#end
#end
while ((strict ? parser.nextTag() : nextTag(parser)) == XmlPullParser.START_TAG) {
String childName = checkDuplicate(parser.getName(), parser, parsed);
switch (childName) {
#set( $ift = "if" )
#foreach ( $field in $allFields )
#if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name )
#end
#if ( $Helper.isFlatItems( $field ) )
#set ( $fieldTagName = $Helper.singular( $fieldTagName ) )
#end
#set ( $fieldCapName = $Helper.capitalise( $field.name ) )
case "${fieldTagName}": {
#if ( $field.type == "String" )
${classLcapName}.${field.name}(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"));
break;
#elseif ( $field.type == "boolean" || $field.type == "Boolean" )
${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"), "${fieldTagName}", parser, ${field.defaultValue}));
break;
#elseif ( $field.type == "int" )
${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"), "${fieldTagName}", parser, strict, ${field.defaultValue}));
break;
#elseif ( $field.type == "DOM" )
${classLcapName}.${field.name}(XmlNodeBuilder.build(parser, true));
break;
#elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" )
List<String> ${field.name} = new ArrayList<>();
while (parser.nextTag() == XmlPullParser.START_TAG) {
if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
${field.name}.add(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"));
} else {
checkUnknownElement(parser, strict);
}
}
${classLcapName}.${field.name}(${field.name});
break;
#elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" )
Map<String, String> ${field.name} = new LinkedHashMap<>();
while (parser.nextTag() == XmlPullParser.START_TAG) {
String key = parser.getName();
String value = parser.nextText().trim();
${field.name}.put(key, value);
}
${classLcapName}.${field.name}(${field.name});
break;
#elseif ( $field.to && $field.multiplicity == "1" )
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict));
break;
#elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) )
${field.name}.add(parse${field.toClass.name}(parser, strict));
break;
#elseif ( $field.to && $field.multiplicity == "*" )
List<$field.to> ${field.name} = new ArrayList<>();
while (parser.nextTag() == XmlPullParser.START_TAG) {
if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
${field.name}.add(parse${field.toClass.name}(parser, strict));
} else {
checkUnknownElement(parser, strict);
}
}
${classLcapName}.${field.name}(${field.name});
break;
#else
// TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
break;
#end
}
#set( $ift = "else if" )
#end
#end
default: {
checkUnknownElement(parser, strict);
break;
}
}
}
#foreach ( $field in $allFields )
#if ( $Helper.isFlatItems( $field ) )
${classLcapName}.${field.name}(${field.name});
#end
#end
#if ( $class == $root )
${classLcapName}.modelEncoding(parser.getInputEncoding());
#end
return ${classLcapName}.build();
}
#end
#end
private String checkDuplicate(String tagName, XmlPullParser parser, Set<String> parsed) throws XmlPullParserException {
#set( $aliases = { } )
#set( $flats = { } )
#foreach( $class in $model.allClasses )
#foreach ( $field in $class.getFields($version) )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name )
#end
#if ( $field.alias )
#set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) )
#end
#if ( $Helper.isFlatItems( $field ) )
#set ( $fieldTagName = $Helper.singular($fieldTagName) )
#set ( $dummy = $flats.put( $fieldTagName, "" ) )
#end
#end
#end
#if ( ! ${aliases.isEmpty()} )
switch (tagName) {
#foreach( $entry in $aliases.entrySet() )
case "${entry.key}":
tagName = "${entry.value}";
#end
}
#end
#if ( ! ${flats.isEmpty()} )
switch (tagName) {
#foreach( $entry in $flats.entrySet() )
case "${entry.key}":
#end
break;
default:
if (!parsed.add(tagName)) {
throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
}
}
#end
return tagName;
}
/**
* Sets the state of the "add default entities" flag.
*
* @param addDefaultEntities a addDefaultEntities object.
*/
public void setAddDefaultEntities(boolean addDefaultEntities) {
this.addDefaultEntities = addDefaultEntities;
} //-- void setAddDefaultEntities(boolean)
public static interface ContentTransformer {
/**
* Interpolate the value read from the xpp3 document
* @param source The source value
* @param fieldName A description of the field being interpolated. The implementation may use this to
* log stuff.
* @return The interpolated value.
*/
String transform(String source, String fieldName);
}
}