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}