package org.jboss.windup.rules.files; import static org.joox.JOOX.$; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; import org.jboss.windup.config.metadata.RuleMetadataType; import org.jboss.windup.config.parser.ElementHandler; import org.jboss.windup.config.parser.NamespaceElementHandler; import org.jboss.windup.config.parser.ParserContext; import org.jboss.windup.config.parser.xml.RuleProviderHandler; import org.jboss.windup.graph.GraphTypeManager; import org.jboss.windup.graph.model.WindupFrame; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.util.exception.WindupException; import org.jboss.windup.util.xml.XmlUtil; import org.ocpsoft.rewrite.config.Rule; import org.ocpsoft.rewrite.context.Context; import org.w3c.dom.Element; /** * Handles parsing the "file-mapping" element to add rules to the current ruleset. */ @NamespaceElementHandler(elementName = FileMappingHandler.ELEM_NAME, namespace = RuleProviderHandler.WINDUP_RULE_NAMESPACE) public class FileMappingHandler implements ElementHandler<Void> { protected static final String ELEM_NAME = "file-mapping"; private static final String FROM = "from"; private static final String TO = "to"; private static final String ON_PARSE_ERROR = "onParseError"; @Inject private GraphTypeManager typeManager; @Override @SuppressWarnings("unchecked") public Void processElement(ParserContext context, Element element) { String id = $(element).attr("id"); String from = $(element).attr(FROM); String to = $(element).attr(TO); String onParseError = $(element).attr(ON_PARSE_ERROR); if (StringUtils.isBlank(from)) { throw new WindupException("The '" + ELEM_NAME + "' element must have a non-empty '" + FROM + "' attribute"); } if (StringUtils.isBlank(to)) { throw new WindupException("The '" + ELEM_NAME + "' element must have a non-empty '" + TO + "' attribute"); } if (!StringUtils.isBlank(onParseError)) { final List<String> acceptableValues = Arrays.asList(new String[]{ATTR_PARSE_IGNORE, "warn", "warning"}); if(!acceptableValues.contains(onParseError)) throw new WindupException("The '<" + ELEM_NAME + ">' attribute '"+ON_PARSE_ERROR+"' must contain one of: " + StringUtils.join(acceptableValues, ", ")); } List<Class<? extends WindupFrame<?>>> types = new ArrayList<>(); List<String> typeNames = Arrays.asList(to.trim().split("\\s*,\\s*")); for (String name : typeNames) { List<Class<? extends WindupFrame<?>>> matchingTypes = new ArrayList<>(); for (Class<? extends WindupFrame<?>> modelType : typeManager.getRegisteredTypes()) { if (modelType.getName().equals(name) || modelType.getSimpleName().equals(name + ".class") || modelType.getSimpleName().equals(name + "Model") || modelType.getSimpleName().equals(name)) { matchingTypes.add(modelType); } } if (matchingTypes.isEmpty()) { throw new WindupException("A '" + ELEM_NAME + "' element specifies a file mapping type [" + name + "] that could not be found in any installed addons."); } if (matchingTypes.size() > 1) { throw new WindupException("A '" + ELEM_NAME + "' element specifies a file mapping type [" + name + "] that matched multiple file types. Please select one of matches and " + "update the configuration to use the fully qualified name: [" + matchingTypes.toString().replaceAll(",", "\n") + "]"); } types.addAll(matchingTypes); } FileMappingTo mappingTo = FileMapping.from(from).to(types.toArray(new Class[types.size()])).onParseError(FileModel.OnParseError.IGNORE); Rule rule = StringUtils.isNotBlank(id) ? mappingTo.withId(id) : mappingTo; if (rule instanceof Context) ((Context) rule).put(RuleMetadataType.RULE_XML, XmlUtil.nodeToString(element)); context.getBuilder().addRule(rule); return null; } private static final String ATTR_PARSE_IGNORE = "ignore"; }