Java tutorial
/* * Copyright 2013-2014 smartics, Kronseder & Reiner GmbH * * Licensed 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. */ package de.smartics.maven.plugin.jboss.modules.parser; import de.smartics.maven.plugin.jboss.modules.descriptor.*; import de.smartics.maven.plugin.jboss.modules.descriptor.DependenciesDescriptor.Builder; import de.smartics.maven.plugin.jboss.modules.xml.ModuleXmlBuilder; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.Namespace; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import java.util.ArrayList; import java.util.List; /** * The worker to do the parsing on a given document. It provides internal state * so that this has not to be passed around. */ final class ModulesDescriptorBuilderV2 { // ********************************* Fields ********************************* // --- constants ------------------------------------------------------------ /** * The name space of the documents parsed by this parser. */ static final Namespace NS = Namespace.getNamespace("http://smartics.de/ns/jboss-modules-descriptor/2"); // --- members -------------------------------------------------------------- /** * The document to be parsed. */ private final Document document; /** * The descriptor to be filled. */ private final ModulesDescriptor modulesDescriptor; /** * The module descriptor currently under work. */ private ModuleDescriptor.Builder builder; // ****************************** Initializer ******************************* // ****************************** Constructors ****************************** /** * Default constructor. * * @param documentId the identifier of the document to be parsed. Used for * error reporting mainly. * @throws NullPointerException if {@code documentId} is <code>null</code>. * @throws IllegalArgumentException if {@code documentId} is blank. */ ModulesDescriptorBuilderV2(final String documentId, final Document document) throws NullPointerException, IllegalArgumentException { assert document != null : "Document must not be 'null'."; this.document = document; this.modulesDescriptor = new ModulesDescriptor(documentId); } // ****************************** Inner Classes ***************************** // ********************************* Methods ******************************** // --- init ----------------------------------------------------------------- // --- get&set -------------------------------------------------------------- // --- business ------------------------------------------------------------- /** * Starts the parsing of the document. * * @return the parsed information. */ public ModulesDescriptor build() { final Element rootElement = document.getRootElement(); final List<Element> moduleElements = rootElement.getChildren("module", NS); for (final Element moduleElement : moduleElements) { parseModule(moduleElement); } return modulesDescriptor; } private void parseModule(final Element moduleElement) { builder = new ModuleDescriptor.Builder(); final String moduleName = moduleElement.getAttributeValue("name"); final String slot = moduleElement.getAttributeValue("slot"); builder.withName(moduleName); builder.withSlot(slot); parseDirectives(moduleElement); parseMatch(moduleElement); parseApplyToDependencies(moduleElement); parseApplyToModule(moduleElement); final ModuleDescriptor descriptor = builder.build(); modulesDescriptor.addDescriptor(descriptor); } private void parseDirectives(final Element directivesElement) { if (directivesElement == null) { return; } final Directives.Builder builder = new Directives.Builder(); final String skip = directivesElement.getAttributeValue("skip"); builder.withSkip(skip); final String inheritSlot = directivesElement.getAttributeValue("inherit-slot"); builder.withInheritSlot(inheritSlot); final Directives directives = builder.build(); this.builder.with(directives); } private void parseMatch(final Element matchElement) { if (matchElement == null) { return; } final ArtifactMatcher.Builder builder = new ArtifactMatcher.Builder(); new AbstractArtifactClusionAdderV2("includes", "include") { @Override public void add(final ArtifactClusion clusion) { builder.addInclude(clusion); } }.addClusions(matchElement); new AbstractArtifactClusionAdderV2("excludes", "exclude") { @Override public void add(final ArtifactClusion clusion) { builder.addExclude(clusion); } }.addClusions(matchElement); final ArtifactMatcher matcher = builder.build(); this.builder.with(matcher); } private void parseApplyToDependencies(final Element applyToDependenciesElement) { if (applyToDependenciesElement == null) { return; } final ApplyToDependencies.Builder builder = new ApplyToDependencies.Builder(); final List<Element> dependenciesElements = applyToDependenciesElement.getChildren("apply-to-dependencies", NS); for (final Element dependenciesElement : dependenciesElements) { final Builder dependencyBuilder = new Builder(); parseMatcher(dependencyBuilder, dependenciesElement); parseApply(dependencyBuilder, dependenciesElement); final DependenciesDescriptor dependencies = dependencyBuilder.build(); builder.add(dependencies); } final ApplyToDependencies applyToDependencies = builder.build(); this.builder.with(applyToDependencies); } private void parseMatcher(final Builder dependencyBuilder, final Element dependenciesElement) { if (dependenciesElement == null) { return; } final ModuleMatcher.Builder builder = new ModuleMatcher.Builder(); new AbstractModuleClusionAdderV2("includes", "include") { @Override public void add(final ModuleClusion clusion) { builder.addInclude(clusion); } }.addClusions(dependenciesElement); new AbstractModuleClusionAdderV2("excludes", "exclude") { @Override public void add(final ModuleClusion clusion) { builder.addExclude(clusion); } }.addClusions(dependenciesElement); final ModuleMatcher matcher = builder.build(); dependencyBuilder.with(matcher); } private void parseApply(final Builder builder, final Element dependenciesElement) { if (dependenciesElement == null) { return; } final String slot = dependenciesElement.getAttributeValue("slot"); final String skip = dependenciesElement.getAttributeValue("skip"); final String export = dependenciesElement.getAttributeValue("export"); final String services = dependenciesElement.getAttributeValue("services"); final String optional = dependenciesElement.getAttributeValue("optional"); builder.withSlot(slot); builder.withSkip(skip); builder.withExport(export); builder.withServices(services); builder.withOptional(optional); final XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat()); final Element importElement = dependenciesElement.getChild("imports", NS); if (importElement != null) { adjustNamespaces(importElement); final String imports = outputter.outputString(importElement); builder.withImportsXml(imports); } final Element exportElement = dependenciesElement.getChild("exports", NS); if (exportElement != null) { adjustNamespaces(exportElement); final String exports = outputter.outputString(exportElement); builder.withExportsXml(exports); } } private void adjustNamespaces(final Element element) { element.setNamespace(null); final List<Namespace> namespaces = new ArrayList<Namespace>(element.getAdditionalNamespaces()); for (final Namespace namespace : namespaces) { element.removeNamespaceDeclaration(namespace); } element.setNamespace(ModuleXmlBuilder.NS); for (final Element child : element.getChildren()) { adjustNamespaces(child); } } private void parseApplyToModule(final Element applyToModuleElement) { if (applyToModuleElement == null) { return; } final ApplyToModule.Builder mBuilder = new ApplyToModule.Builder(); adjustNamespaces(applyToModuleElement); final XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat()); for (final Element child : applyToModuleElement.getChildren()) { handleChild(mBuilder, outputter, child); } builder.with(mBuilder.build()); } private void handleChild(final ApplyToModule.Builder mBuilder, final XMLOutputter outputter, final Element child) { final String elementName = child.getName(); if ("dependencies".equals(elementName)) { handleDependencies(mBuilder, outputter, child); } else if ("properties".equals(elementName)) { for (final Element propertyElement : child.getChildren("property", ModuleXmlBuilder.NS)) { final String name = propertyElement.getAttributeValue("name"); final String fragment = outputter.outputString(propertyElement); mBuilder.addPropertyXml(name, fragment); } } else if ("exports".equals(elementName)) { final String fragment = outputter.outputString(child); mBuilder.withExportsXml(fragment); } else if ("main-class".equals(elementName)) { final String fragment = outputter.outputString(child); mBuilder.withMainClassXml(fragment); } else if ("resource-root".equals(elementName)) { final String fragment = outputter.outputString(child); mBuilder.addResourceRootXml(fragment); } else { // TODO warn or add to end? } } private void handleDependencies(final ApplyToModule.Builder mBuilder, final XMLOutputter outputter, final Element child) { int nonModuleCounter = 0; for (final Element childElement : child.getChildren()) { final String childElementName = childElement.getName(); final String name; if ("module".equals(childElementName)) { name = childElement.getAttributeValue("name"); } else { // i.e. system, maybe others. nonModuleCounter++; name = "non-module@" + nonModuleCounter; } final String fragment = outputter.outputString(childElement); mBuilder.addDependencyXml(name, fragment); } } // --- object basics -------------------------------------------------------- }