001/**
002 * Copyright 2013-2015 John Ericksen
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.asciidoctor.asciidoclet;
017
018import com.google.common.base.Optional;
019import com.google.common.base.Splitter;
020import com.google.common.collect.ImmutableList;
021import com.sun.javadoc.DocErrorReporter;
022import com.sun.javadoc.RootDoc;
023
024import java.io.File;
025import java.nio.charset.Charset;
026import java.util.List;
027
028/**
029 * Provides an interface to the doclet options we are interested in.
030 */
031public class DocletOptions {
032
033    // Split on comma with optional whitespace
034    private static final Splitter COMMA_WS = Splitter.onPattern("\\s*,\\s*").omitEmptyStrings().trimResults();
035
036    public static final String ENCODING = "-encoding";
037    public static final String OVERVIEW = "-overview";
038    public static final String BASEDIR = "--base-dir";
039    public static final String STYLESHEET = "-stylesheetfile";
040    public static final String DESTDIR = "-d";
041    public static final String ATTRIBUTE = "-a";
042    public static final String ATTRIBUTE_LONG = "--attribute";
043    public static final String ATTRIBUTES_FILE = "--attributes-file";
044    public static final String GEM_PATH = "--gem-path";
045    public static final String REQUIRE = "-r";
046    public static final String REQUIRE_LONG = "--require";
047
048    public static final DocletOptions NONE = new DocletOptions(new String[][]{});
049
050    private final Optional<File> basedir;
051    private final Optional<File> overview;
052    private final Optional<File> stylesheet;
053    private final Optional<File> destdir;
054    private final Optional<File> attributesFile;
055    private final String gemPath;
056    private final List<String> requires;
057    private final Charset encoding;
058    private final List<String> attributes;
059
060    public DocletOptions(RootDoc rootDoc) {
061        this(rootDoc.options());
062    }
063
064    public DocletOptions(String[][] options) {
065        File basedir = null;
066        File overview = null;
067        File stylesheet = null;
068        File destdir = null;
069        File attrsFile = null;
070        String gemPath = null;
071        ImmutableList.Builder<String> requires = ImmutableList.builder();
072        Charset encoding = Charset.defaultCharset();
073        ImmutableList.Builder<String> attrs = ImmutableList.builder();
074        for (String[] option : options) {
075            if (option.length > 0) {
076                if (BASEDIR.equals(option[0])) {
077                    basedir = new File(option[1]);
078                }
079                else if (OVERVIEW.equals(option[0])) {
080                    overview = new File(option[1]);
081                }
082                else if (STYLESHEET.equals(option[0])) {
083                    stylesheet = new File(option[1]);
084                }
085                else if (DESTDIR.equals(option[0])) {
086                    destdir = new File(option[1]);
087                }
088                else if (ENCODING.equals(option[0])) {
089                    encoding = Charset.forName(option[1]);
090                }
091                else if (ATTRIBUTE.equals(option[0]) || ATTRIBUTE_LONG.equals(option[0])) {
092                    attrs.addAll(COMMA_WS.split(option[1]));
093                }
094                else if (ATTRIBUTES_FILE.equals(option[0])) {
095                    attrsFile = new File(option[1]);
096                }
097                else if (GEM_PATH.equals(option[0])) {
098                    gemPath = option[1];
099                }
100                else if (REQUIRE.equals(option[0]) || REQUIRE_LONG.equals(option[0])) {
101                    requires.addAll(COMMA_WS.split(option[1]));
102                }
103            }
104        }
105
106        this.basedir = Optional.fromNullable(basedir);
107        this.overview = Optional.fromNullable(overview);
108        this.stylesheet = Optional.fromNullable(stylesheet);
109        this.destdir = Optional.fromNullable(destdir);
110        this.encoding = encoding;
111        this.attributes = attrs.build();
112        this.attributesFile = Optional.fromNullable(attrsFile);
113        this.gemPath = gemPath;
114        this.requires = requires.build();
115    }
116
117    public Optional<File> overview() {
118        return overview;
119    }
120
121    public Optional<File> stylesheet() {
122        return stylesheet;
123    }
124
125    public Optional<File> baseDir() {
126        return basedir;
127    }
128
129    public Optional<File> destDir() {
130        return destdir;
131    }
132
133    public Charset encoding() {
134        return encoding;
135    }
136
137    public List<String> attributes() {
138        return attributes;
139    }
140
141    Optional<File> attributesFile() {
142        if (!attributesFile.isPresent()) {
143            return attributesFile;
144        }
145        File f = attributesFile.get();
146        if (!f.isAbsolute() && basedir.isPresent()) {
147            f = new File(basedir.get(), f.getPath());
148        }
149        return Optional.of(f);
150    }
151
152    public String gemPath() {
153        return gemPath;
154    }
155
156    public List<String> requires() {
157        return requires;
158    }
159
160    public static boolean validOptions(String[][] options, DocErrorReporter errorReporter, StandardAdapter standardDoclet) {
161        DocletOptions docletOptions = new DocletOptions(options);
162
163        if (!docletOptions.baseDir().isPresent()) {
164            errorReporter.printWarning(BASEDIR + " must be present for includes or file reference features to work properly.");
165        }
166
167        Optional<File> attrsFile = docletOptions.attributesFile();
168        if (attrsFile.isPresent() && !attrsFile.get().canRead()) {
169            errorReporter.printWarning("Cannot read attributes file " + attrsFile.get());
170        }
171
172        return standardDoclet.validOptions(options, errorReporter);
173    }
174
175    public static int optionLength(String option, StandardAdapter standardDoclet) {
176        if (BASEDIR.equals(option)) {
177            return 2;
178        }
179        if (ATTRIBUTE.equals(option) || ATTRIBUTE_LONG.equals(option)) {
180            return 2;
181        }
182        if (ATTRIBUTES_FILE.equals(option)) {
183            return 2;
184        }
185        if (GEM_PATH.equals(option)) {
186            return 2;
187        }
188        if (REQUIRE.equals(option) || REQUIRE_LONG.equals(option)) {
189            return 2;
190        }
191        return standardDoclet.optionLength(option);
192    }
193}