ddt.dtool.dub.DubManifestParser.java Source code

Java tutorial

Introduction

Here is the source code for ddt.dtool.dub.DubManifestParser.java

Source

/*******************************************************************************
 * Copyright (c) 2013, 2013 Bruno Medeiros and other Contributors.
 * 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
 *
 * Contributors:
 *     Bruno Medeiros - initial API and implementation
 *******************************************************************************/
package ddt.dtool.dub;

import static ddt.melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static ddt.melnorme.utilbox.misc.MiscUtil.createPath;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import ddt.melnorme.utilbox.misc.ArrayUtil;
import ddt.melnorme.utilbox.misc.MiscUtil;
import ddt.melnorme.utilbox.misc.PathUtil.InvalidPathExceptionX;

import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;

import ddt.dtool.dub.DubBundle.BundleFile;
import ddt.dtool.dub.DubBundle.DubBundleException;
import ddt.dtool.dub.DubBundle.DubDependecyRef;
import ddt.dtool.util.JsonReaderExt;

/**
 * Parse a Dub bundle in a filesystem location into an in-memory description of the bundle.
 */
public class DubManifestParser extends CommonDubParser {

    public static final String ERROR_BUNDLE_NAME_UNDEFINED = "Bundle name not defined.";

    public static DubBundle parseDubBundleFromLocation(BundlePath bundlePath) {
        assertNotNull(bundlePath);
        return new DubManifestParser().parseDubBundle(bundlePath);
    }

    protected String source;

    protected String bundleName = null;
    protected String pathString = null;

    protected String version = null;
    protected String[] sourceFolders = null;
    protected List<BundleFile> bundleFiles = null;
    protected DubDependecyRef[] dependencies = null;
    protected String targetName = null;
    protected String targetPath = null;

    protected DubManifestParser() {
    }

    protected DubBundle parseDubBundle(BundlePath bundlePath) {
        assertNotNull(bundlePath);
        try {
            parseFromLocation(bundlePath);
        } catch (DubBundleException e) {
            dubError = e;
        }
        return createBundle(bundlePath, true);
    }

    protected void parseFromLocation(BundlePath bundlePath) throws DubBundleException {
        File jsonLocation = bundlePath.getManifestFilePath().toFile();

        try {
            source = readStringFromFile(jsonLocation);
        } catch (IOException e) {
            throw new DubBundleException(e);
        }
        parseFromSource(source);
    }

    public DubBundle createBundle(BundlePath bundlePath, boolean searchImplicitSourceFolders) {
        if (bundleName == null) {
            bundleName = "<undefined>";

            putError(ERROR_BUNDLE_NAME_UNDEFINED);
        }

        if (bundlePath == null) {
            if (pathString == null) {
                putError("Missing path entry.");
            } else {
                bundlePath = BundlePath.create(pathString);
                if (bundlePath == null) {
                    putError("Invalid path: " + pathString);
                }
            }
        }
        Path[] effectiveSourceFolders;
        if (sourceFolders != null) {
            effectiveSourceFolders = createPaths(sourceFolders);
        } else if (searchImplicitSourceFolders && bundlePath != null) {
            effectiveSourceFolders = searchImplicitSrcFolders(bundlePath.getPath());
        } else {
            effectiveSourceFolders = null;
        }

        return new DubBundle(bundlePath, bundleName, dubError, version, sourceFolders, effectiveSourceFolders,
                bundleFiles, dependencies, targetName, targetPath);
    }

    protected Path[] createPaths(String[] paths) {
        if (paths == null)
            return null;

        ArrayList<Path> pathArray = new ArrayList<>();
        for (String pathString : paths) {
            try {
                pathArray.add(createPath(pathString));
            } catch (InvalidPathExceptionX e) {
                putError("Invalid source/import path: " + pathString);
            }
        }

        return ArrayUtil.createFrom(pathArray, Path.class);
    }

    protected Path[] searchImplicitSrcFolders(Path location) {
        if (location == null) {
            return new Path[0];
        }
        File locationDir = location.toFile();
        if (!locationDir.isDirectory()) {
            putError("location is not a directory");
            return new Path[0];
        }

        final ArrayList<Path> implicitFolders = new ArrayList<>();
        locationDir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                if (dir.isDirectory() && (name.equals("src") || name.equals("source"))) {
                    implicitFolders.add(MiscUtil.createValidPath(name));
                }
                return false;
            }
        });

        return ArrayUtil.createFrom(implicitFolders, Path.class);
    }

    @Override
    protected void readData(JsonReaderExt jsonParser) throws IOException {
        readBundle(jsonParser);
    }

    protected DubManifestParser readBundle(JsonReaderExt jsonReader) throws IOException {
        jsonReader.consumeExpected(JsonToken.BEGIN_OBJECT);

        while (jsonReader.hasNext()) {
            JsonToken tokenType = jsonReader.peek();

            if (tokenType == JsonToken.NAME) {
                String propertyName = jsonReader.nextName();

                if (propertyName.equals("name")) {
                    bundleName = jsonReader.consumeStringValue();
                } else if (propertyName.equals("version")) {
                    version = jsonReader.consumeStringValue();
                } else if (propertyName.equals("path")) {
                    pathString = jsonReader.consumeStringValue();
                } else if (propertyName.equals("importPaths")) {
                    sourceFolders = parseSourcePaths(jsonReader);
                } else if (propertyName.equals("dependencies")) {
                    dependencies = parseDependencies(jsonReader);
                } else if (propertyName.equals("files")) {
                    bundleFiles = parseFiles(jsonReader);
                } else if (propertyName.equals("targetName")) {
                    targetName = jsonReader.consumeStringValue();
                } else if (propertyName.equals("targetPath")) {
                    targetPath = jsonReader.consumeStringValue();
                } else {
                    jsonReader.skipValue();
                }
            } else {
                jsonReader.errorUnexpected(tokenType);
            }
        }

        jsonReader.consumeExpected(JsonToken.END_OBJECT);
        return this;
    }

    protected String[] parseSourcePaths(JsonReaderExt jsonReader) throws IOException {
        ArrayList<String> stringArray = jsonReader.consumeStringArray(true);
        return ArrayUtil.createFrom(stringArray, String.class);
    }

    protected ArrayList<BundleFile> parseFiles(JsonReaderExt jsonReader) throws IOException {
        jsonReader.consumeExpected(JsonToken.BEGIN_ARRAY);

        ArrayList<BundleFile> bundleFiles = new ArrayList<>();

        while (jsonReader.hasNext()) {
            BundleFile bundleFile = parseFile(jsonReader);
            bundleFiles.add(bundleFile);
        }

        jsonReader.consumeExpected(JsonToken.END_ARRAY);
        return bundleFiles;
    }

    protected BundleFile parseFile(JsonReaderExt jsonReader) throws IOException {
        jsonReader.consumeExpected(JsonToken.BEGIN_OBJECT);
        String path = null;
        boolean importOnly = false;

        while (jsonReader.hasNext()) {
            String propName = jsonReader.consumeExpectedPropName();

            switch (propName) {
            case "path":
                path = jsonReader.consumeStringValue();
                break;
            case "type":
                //TODO

            default:
                jsonReader.skipValue();
            }
        }
        jsonReader.consumeExpected(JsonToken.END_OBJECT);
        if (path == null) {
            path = "<missing_path>";
            putError("missing path property for files entry.");
        }
        return new DubBundle.BundleFile(path, importOnly);
    }

    protected DubDependecyRef[] parseDependencies(JsonReaderExt jsonParser) throws IOException {
        return new BundleDependenciesSegmentParser(jsonParser).parse();
    }

    protected class BundleDependenciesSegmentParser {

        protected JsonReaderExt jsonReader;

        public BundleDependenciesSegmentParser(JsonReaderExt jsonParser) {
            this.jsonReader = jsonParser;
        }

        public DubDependecyRef[] parse() throws IOException {
            if (jsonReader.peek() == JsonToken.BEGIN_OBJECT)
                return parseRawDeps();

            return parseResolvedDeps();
        }

        public DubDependecyRef[] parseRawDeps() throws IOException, MalformedJsonException {
            jsonReader.consumeExpected(JsonToken.BEGIN_OBJECT);

            ArrayList<DubDependecyRef> deps = new ArrayList<>();

            while (jsonReader.hasNext()) {
                String depName = jsonReader.consumeExpectedPropName();
                jsonReader.skipValue(); // Ignore value for now, TODO

                deps.add(new DubDependecyRef(depName, null));
            }
            jsonReader.consumeExpected(JsonToken.END_OBJECT);
            return ArrayUtil.createFrom(deps, DubDependecyRef.class);
        }

        public DubDependecyRef[] parseResolvedDeps() throws IOException, MalformedJsonException {
            jsonReader.consumeExpected(JsonToken.BEGIN_ARRAY);

            ArrayList<DubDependecyRef> deps = new ArrayList<>();

            while (jsonReader.hasNext()) {
                String depName = jsonReader.nextString();
                deps.add(new DubDependecyRef(depName, null));
            }
            jsonReader.consumeExpected(JsonToken.END_ARRAY);
            return ArrayUtil.createFrom(deps, DubDependecyRef.class);
        }
    }

}