net.geoprism.FileMerger.java Source code

Java tutorial

Introduction

Here is the source code for net.geoprism.FileMerger.java

Source

/**
 * Copyright (c) 2015 TerraFrame, Inc. All rights reserved.
 *
 * This file is part of Runway SDK(tm).
 *
 * Runway SDK(tm) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Runway SDK(tm) is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Runway SDK(tm).  If not, see <http://www.gnu.org/licenses/>.
 */
package net.geoprism;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;

/**
 * This class performs merge operations between files or directories. This is designed for use in the build system for custom resource merging.
 * 
 * @author rrowlands
 */
public class FileMerger {
    public static void main(String[] args) throws ParseException, IOException {
        CommandLineParser parser = new DefaultParser();
        Options options = new Options();
        options.addOption(Option.builder("b").hasArg().argName("baseFile").longOpt("baseFile")
                .desc("The path to the base properties file.").build());
        options.addOption(Option.builder("o").hasArg().argName("overrideFile").longOpt("overrideFile")
                .desc("The path to the override properties file.").build());
        options.addOption(Option.builder("e").hasArg().argName("exportFile").longOpt("exportFile")
                .desc("The path to the export properties file. A null value defaults to base.").build());
        options.addOption(Option.builder("B").hasArg().argName("baseDir").longOpt("baseDir")
                .desc("The path to the base directory.").build());
        options.addOption(Option.builder("O").hasArg().argName("overrideDir").longOpt("overrideDir")
                .desc("The path to the override directory.").build());
        options.addOption(Option.builder("E").hasArg().argName("exportDir").longOpt("exportDir")
                .desc("The path to the export directory. A null value defaults to base.").build());
        CommandLine line = parser.parse(options, args);

        String sBase = line.getOptionValue("b");
        String sOverride = line.getOptionValue("o");
        String sExport = line.getOptionValue("e");
        String sBaseDir = line.getOptionValue("B");
        String sOverrideDir = line.getOptionValue("O");
        String sExportDir = line.getOptionValue("E");

        if (sBase != null && sOverride != null) {
            if (sExport == null) {
                sExport = sBase;
            }

            File fBase = new File(sBase);
            File fOverride = new File(sOverride);
            File fExport = new File(sExport);
            if (!fBase.exists() || !fOverride.exists()) {
                throw new RuntimeException(
                        "The base [" + sBase + "] and the override [" + sOverride + "] paths must both exist.");
            }

            FileMerger merger = new FileMerger();
            merger.mergeProperties(fBase, fOverride, fExport);
        } else if (sBaseDir != null && sOverrideDir != null) {
            if (sExportDir == null) {
                sExportDir = sBaseDir;
            }

            File fBaseDir = new File(sBaseDir);
            File fOverrideDir = new File(sOverrideDir);
            File fExportDir = new File(sExportDir);
            if (!fBaseDir.exists() || !fOverrideDir.exists()) {
                throw new RuntimeException("The base [" + sBaseDir + "] and the override [" + sOverrideDir
                        + "] paths must both exist.");
            }

            FileMerger merger = new FileMerger();
            merger.mergeDirectories(fBaseDir, fOverrideDir, fExportDir);
        } else {
            throw new RuntimeException("Invalid arguments");
        }
    }

    public FileMerger() {

    }

    public void mergeDirectories(File base, File override, File export) throws IOException {
        if (!export.exists()) {
            export.mkdirs();
        }

        if (!export.equals(override)) {
            for (File overrideChild : override.listFiles()) {
                mergeFile(new File(base, overrideChild.getName()), overrideChild,
                        new File(export, overrideChild.getName()));
            }
        }
        if (!export.equals(base)) {
            for (File baseChild : base.listFiles()) {
                mergeFile(baseChild, new File(override, baseChild.getName()),
                        new File(export, baseChild.getName()));
            }
        }
    }

    public void mergeFile(File base, File override, File export) throws IOException {
        if (base == null || !base.exists()) {
            if (!override.equals(export)) {
                if (override.isDirectory()) {
                    mergeDirectories(base, override, export);
                } else {
                    FileUtils.copyFile(override, export);
                }
            }
        } else if (override == null || !override.exists()) {
            if (!base.equals(export)) {
                if (base.isDirectory()) {
                    mergeDirectories(base, override, export);
                } else {
                    FileUtils.copyFile(base, export);
                }
            }
        } else {
            if (override.isDirectory()) {
                mergeDirectories(base, override, export);
            } else if (override.getName().endsWith(".properties")) {
                mergeProperties(base, override, export);
            } else if (!override.equals(export)) {
                FileUtils.copyFile(override, export);
            }
        }
    }

    public void mergeProperties(File base, File override, File export) throws IOException {
        if (!export.exists()) {
            export.createNewFile();
        }
        if (!base.exists()) {
            if (override != export) {
                FileUtils.copyFile(override, export);
            }
            return;
        }

        Properties baseProps = new Properties();
        baseProps.load(new FileInputStream(base));

        Properties overrideProps = new Properties();
        overrideProps.load(new FileInputStream(override));

        Iterator<Object> i = overrideProps.keySet().iterator();
        while (i.hasNext()) {
            String key = (String) i.next();

            String value = overrideProps.getProperty(key);
            if (value.equals("$REMOVE$")) {
                baseProps.remove(key);
            } else {
                baseProps.setProperty(key, value);
            }
        }

        baseProps.store(new FileOutputStream(export), null);
    }
}