maven/src/mdo/transformer.vm

190 lines
7.6 KiB
Plaintext

#*
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}Transformer" )
#
#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.ObjectStreamException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.maven.api.annotations.Generated;
import org.apache.maven.api.xml.XmlNode;
#foreach ( $class in $model.allClasses )
import ${packageModelV4}.${class.name};
#end
import org.apache.maven.internal.xml.XmlNodeImpl;
@Generated
public class ${className} {
private final Function<String, String> transformer;
public ${className}(Function<String, String> transformer) {
this.transformer = transformer;
}
/**
* Transforms the given model
*/
public ${root.name} visit(${root.name} target) {
Objects.requireNonNull(target, "target cannot be null");
return transform${root.name}(target);
}
/**
* The transformation function.
*/
protected String transform(String value) {
return transformer.apply(value);
}
#foreach ( $class in $model.allClasses )
#if ( $class.name != "InputSource" && $class.name != "InputLocation" )
#set ( $ancestors = $Helper.ancestors( $class ) )
#set ( $allFields = $Helper.xmlFields( $class ) )
protected ${class.name} transform${class.name}(${class.name} target) {
if (target == null) {
return null;
}
Supplier<${class.name}.Builder> creator = () -> ${class.name}.newBuilder(target);
${class.name}.Builder builder = null;
#foreach ( $field in $allFields )
builder = (${class.name}.Builder) transform${field.modelClass.name}_${Helper.capitalise($field.name)}(creator, builder, target);
#end
return builder != null ? builder.build() : target;
}
#foreach ( $field in $allFields )
#set ( $capField = ${Helper.capitalise($field.name)} )
protected ${class.name}.Builder transform${class.name}_${capField}(Supplier<? extends ${class.name}.Builder> creator, ${class.name}.Builder builder, ${class.name} target) {
#if ( $field.type == "String" )
String oldVal = target.get${capField}();
String newVal = transform(oldVal);
return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
#elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" )
List<String> oldVal = target.get${capField}();
List<String> newVal = transform(oldVal, this::transform);
return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
#elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" )
Map<String, String> props = target.get${capField}();
Map<String, String> newProps = null;
for (Map.Entry<String, String> entry : props.entrySet()) {
String newVal = transform(entry.getValue());
if (newVal != null && newVal != entry.getValue()) {
if (newProps == null) {
newProps = new HashMap<>();
newProps.putAll(props);
builder = builder != null ? builder : creator.get();
builder.${field.name}(newProps);
}
newProps.put(entry.getKey(), newVal);
}
}
return builder;
#elseif ( $field.to && $field.multiplicity == "1" )
${field.to} oldVal = target.get${capField}();
${field.to} newVal = transform${field.to}(oldVal);
return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
#elseif ( $field.to && $field.multiplicity == "*" )
List<${field.to}> oldVal = target.get${capField}();
List<${field.to}> newVal = transform(oldVal, this::transform${field.to});
return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
#elseif ( $field.type == "DOM" )
XmlNode oldVal = target.get${capField}();
XmlNode newVal = transform(oldVal);
return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
#elseif ( $field.type == "boolean" || $field.type == "int" || $field.type == "java.nio.file.Path" )
// nothing to do, the transformer only handles strings
return builder;
#else
// TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
#end
}
#end
#end
#end
protected <T> List<T> transform(List<T> list, Function<T, T> transformer) {
List<T> newList = list;
for (int i = 0; i < list.size(); i++) {
T oldVal = list.get(i);
T newVal = transformer.apply(oldVal);
if (newVal != oldVal) {
if (newList == list) {
newList = new ArrayList<>(list);
}
newList.set(i, newVal);
}
}
return newList;
}
protected <T> Map<String, T> transform(Map<String, T> map, Function<T, T> transformer) {
Map<String, T> newMap = map;
for (String key : map.keySet()) {
T oldVal = map.get(key);
T newVal = transformer.apply(oldVal);
if (newVal != oldVal) {
if (newMap == map) {
newMap = new HashMap<>(map);
}
newMap.put(key, newVal);
}
}
return newMap;
}
protected XmlNode transform(XmlNode node) {
if (node != null) {
String oldValue = node.getValue();
String newValue = transform(oldValue);
Map<String, String> oldAttrs = node.getAttributes();
Map<String, String> newAttrs = transform(oldAttrs, this::transform);
List<XmlNode> oldChildren = node.getChildren();
List<XmlNode> newChildren = transform(oldChildren, this::transform);
if (oldValue != newValue || oldAttrs != newAttrs || oldChildren != newChildren) {
return new XmlNodeImpl(node.getPrefix(), node.getNamespaceUri(), node.getName(),
newValue, newAttrs, newChildren, node.getInputLocation());
}
}
return node;
}
}