org.eclipse.smarthome.documentation.GenerateDocumentation.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.smarthome.documentation.GenerateDocumentation.java

Source

/*
 * Copyright (c) Alexander Kammerer 2015.
 *
 * All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 */

package org.eclipse.smarthome.documentation;

import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.eclipse.smarthome.documentation.data.*;
import org.eclipse.smarthome.documentation.models.Binding;
import org.eclipse.smarthome.documentation.schemas.config_description.v1_0.ConfigDescription;
import org.eclipse.smarthome.documentation.schemas.config_description.v1_0.ConfigDescriptions;
import org.eclipse.smarthome.documentation.schemas.thing_description.v1_0.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;

/**
 * Goal which touches a timestamp file.
 * <p/>
 * NOTE: CARE FOR THE NAMESPACE IN {@link ThingDescriptions} and {@link ConfigDescriptions}.
 */
@Mojo(name = "generate-docu", defaultPhase = LifecyclePhase.PACKAGE)
public class GenerateDocumentation extends AbstractMojo {

    /**
     * ESH-INF/ subdirectories.
     */
    private static final String THING_SUBDIR = "thing/";
    private static final String BINDING_SUBDIR = "binding/";
    private static final String CONFIG_SUBDIR = "config/";

    /**
     * URL for the download of the templates.
     */
    private static final String DOWNLOAD_DIR = "https://github.com/kummerer94/binding-docu-generator/raw/master/src/main/resources/templates/";

    /**
     * Data for the templates.
     */
    private ChannelList channels = new ChannelList();
    private ThingList things = new ThingList();
    private ChannelGroupList channelGroups = new ChannelGroupList();
    private BridgeList bridges = new BridgeList();
    private ConfigurationList configList = new ConfigurationList();
    private Binding binding;

    /**
     * The directory in which your binding xml files are.
     */
    @Parameter(defaultValue = "src/main/java/ESH-INF/")
    private String eshDir;

    /**
     * Your template files.
     */
    @Parameter(defaultValue = "src/main/resources/templates/")
    private String templates;

    /**
     * Name of your readme template file.
     */
    @Parameter(defaultValue = "readme.mustache")
    private String template;

    /**
     * The name of the generated docu file.
     */
    @Parameter(defaultValue = "generated-docu.md")
    private String readmeName;

    /**
     * Execute the mojo.
     *
     * @throws MojoExecutionException
     */
    public void execute() throws MojoExecutionException {
        prepare();
        scanDir();

        getLog().info(Paths.get("").toAbsolutePath().toString());

        try {
            // Compile mustache template
            MustacheFactory mf = new DefaultMustacheFactory();
            // Get template string
            Mustache mustache = mf.compile(templates + template);
            // Put everything into the scope
            HashMap<String, Object> scope = new HashMap<String, Object>();
            scope.put("binding", binding);
            scope.put("bridgeList", bridges);
            scope.put("thingList", things);
            scope.put("channelList", channels);
            scope.put("channelGroupList", channelGroups);
            scope.put("configList", configList);
            mustache.execute(new FileWriter(readmeName), scope).flush();
        } catch (Exception e) {
            getLog().error(e);
        }
    }

    /**
     * Scans the given eshDir for xml files.
     */
    private void scanDir() {
        // Scan the binding directory.
        File binding = new File(eshDir + BINDING_SUBDIR + "binding.xml");
        if (binding.exists()) {
            getLog().debug("Found binding xml: " + binding.getName());
            parseBindingDescription(binding);
        }

        // Scan the things directory.
        File things = new File(eshDir + THING_SUBDIR);
        if (things.exists() && things.isDirectory()) {
            File[] files = things.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file != null) {
                        if (file.getName().endsWith(".xml")) {
                            getLog().info("Found thing xml: " + file.getName());
                            parseThingDescriptions(file);
                        }
                    }
                }
            }
        }

        // Scan the config directory.
        File configs = new File(eshDir + CONFIG_SUBDIR);
        if (configs.exists() && configs.isDirectory()) {
            File[] files = configs.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file != null) {
                        if (file.getName().endsWith(".xml")) {
                            getLog().info("Found config xml: " + file.getName());
                            parseConfigDescriptions(file);
                        }
                    }
                }
            }
        }
    }

    /**
     * Handles the start up of the mojo.
     */
    private void prepare() {
        // Configure loggers
        BasicConfigurator.configure();

        // Prepare the templates
        prepareTemplateDir();
    }

    /**
     * Prepares the template directory.
     * <p/>
     * If needed downloads a set of template files.
     */
    private void prepareTemplateDir() {
        String[] downloads = { template.replace(".mustache", ""), "partials/bridgeConfig", "partials/bridges",
                "partials/channelGroupInfo", "partials/channelGroups", "partials/channelInfo", "partials/channels",
                "partials/config", "partials/configDescriptions", "partials/parameterRow",
                "partials/paramProperties", "partials/thingConfig", "partials/things" };
        // Download all files.
        for (String url : downloads) {
            try {
                // Copy file from URL.
                String downloadUrl = DOWNLOAD_DIR + url + ".mustache";
                String fileName = templates + url + ".mustache";
                if (downloadNeeded(fileName)) {
                    getLog().debug("Downloading " + fileName + " from " + downloadUrl);
                    FileUtils.copyURLToFile(new URL(downloadUrl), new File(fileName));
                }
            } catch (MalformedURLException e) {
                getLog().error(e);
            } catch (IOException e) {
                getLog().error(e);
            }
        }
    }

    /**
     * Are the template files already present?
     *
     * @param fileName The url.
     * @return Is the download needed?
     */
    public boolean downloadNeeded(String fileName) {
        return !new File(fileName).exists();
    }

    /**
     * Parses the xml with the available channels.
     *
     * @param file XML file.
     */
    private void parseThingDescriptions(File file) {
        try {
            JAXBContext jc = JAXBContext.newInstance(ThingDescriptions.class);

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            ThingDescriptions thingDesc = (ThingDescriptions) unmarshaller.unmarshal(file);

            // Go through all the available types
            List<Object> objs = thingDesc.getThingTypeOrBridgeTypeOrChannelType();
            for (Object obj : objs) {
                if (obj instanceof ChannelType) {
                    channels.put(obj);
                } else if (obj instanceof BridgeType) {
                    bridges.put(obj);
                } else if (obj instanceof ChannelGroupType) {
                    channelGroups.put(obj);
                } else if (obj instanceof ThingType) {
                    things.put(obj);
                } else {
                    getLog().debug("Unsupported class. " + obj.getClass().toString());
                }
            }
        } catch (Exception e) {
            getLog().error(e);
        }
    }

    /**
     * Parses the xml with the available configuration.
     *
     * @param file XML file.
     */
    private void parseConfigDescriptions(File file) {
        try {
            JAXBContext jc = JAXBContext.newInstance(ConfigDescriptions.class);

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            ConfigDescriptions configDesc = (ConfigDescriptions) unmarshaller.unmarshal(file);
            for (ConfigDescription c : configDesc.getConfigDescription()) {
                configList.put(c);
            }
        } catch (Exception e) {
            getLog().error(e);
        }
    }

    /**
     * Parses the xml with the available binding.
     *
     * @param file XML file.
     */
    private void parseBindingDescription(File file) {
        try {
            JAXBContext jc = JAXBContext
                    .newInstance(org.eclipse.smarthome.documentation.schemas.binding.v1_0.Binding.class);

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            binding = new Binding((org.eclipse.smarthome.documentation.schemas.binding.v1_0.Binding) unmarshaller
                    .unmarshal(file));
        } catch (Exception e) {
            getLog().error(e);
        }
    }
}