001/* 002 * Copyright (c) 2009 The openGion Project. 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, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.taglet; // 7.4.4.0 (2021/06/30) openGionV8事前準備(taglet2→taglet) 017 018// import jdk.javadoc.doclet.DocletEnvironment ; 019import jdk.javadoc.doclet.Doclet ; 020import jdk.javadoc.doclet.Reporter ; 021// import javax.lang.model.element.Element ; 022// import javax.lang.model.element.Modifier ; 023// import javax.lang.model.element.TypeElement; 024// import javax.lang.model.element.ElementKind ; 025// import javax.lang.model.element.VariableElement; 026import javax.lang.model.SourceVersion ; 027// import javax.lang.model.util.ElementFilter ; 028// import javax.lang.model.util.Elements ; 029import javax.tools.Diagnostic.Kind ; 030import com.sun.source.doctree.DocCommentTree ; 031// import com.sun.source.util.DocTrees ; 032import com.sun.source.doctree.DocTree ; 033 034import java.util.Locale ; 035// import java.util.Set; 036import java.util.List; 037// import java.util.HashSet; 038import java.util.Arrays; 039import java.util.ArrayList; 040 041import java.util.Map; 042import java.util.HashMap; 043 044// import java.io.IOException; 045// import java.io.File; 046// import java.io.PrintWriter; 047 048// import org.opengion.fukurou.util.FileUtil; 049// import org.opengion.fukurou.util.StringUtil; 050 051/** 052 * ソースコメントから、パラメータ情報を取り出す Doclet クラスです。 053 * og.paramLevel タグと og.cryptography タグを切り出します。 054 * これらは、システムパラメータとしてGE12テーブルに設定される値をクラスより抽出する 055 * のに使用します。 056 * 057 * @version 7.3 058 * @author Kazuhiko Hasegawa 059 * @since JDK11.0, 060 */ 061public abstract class AbstractDocTree implements Doclet { 062 /** エンコード {@value} */ 063 public static final String ENCODE = "UTF-8"; 064 065 /** 情報の出力 */ 066 protected Reporter reporter; // JavaDocの情報、警告、エラー情報の出力 067 068 /** 空DocTreeリスト */ 069 protected static final List<DocTree> EMPTY_LIST = List.of(); // ゼロ要素を含む変更不可能なリスト 070 071 /** 072 * デフォルトコンストラクター 073 * 074 * @og.rev 7.3.0.0 (2021/01/06) PMD refactoring. Each class should declare at least one constructor. 075 */ 076 public AbstractDocTree() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 077 078 /** 079 * 指定されたロケールとエラー・レポータでこのドックレットを初期化します。 080 * 081 * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応 082 * 083 * @param locale 使用されるロケール 084 * @param reporter 使用するレポータ 085 */ 086 @Override 087 public void init(final Locale locale, final Reporter reporter) { 088 reporter.print(Kind.NOTE, getName() + " Start!: "); // NOTE:情報 WARNING:警告 ERROR:エラー 089 this.reporter = reporter; 090 } 091 092 /** 093 * ドックレットを識別する名前を返します。 094 * 095 * @return 名前 096 */ 097 @Override 098 public String getName() { 099 return getClass().getSimpleName(); 100 } 101 102 /** 103 * Doclet.Option を継承し、共通メソッドを実装したabstractクラス 104 * 105 * 単純に、メソッドのOverrideで共通化しているだけです。 106 */ 107 protected static abstract class AbstractOption implements Option { 108 private final List<String> someOption ; 109 110 /** 111 * コンストラクター。 112 * 113 * @param prm 引数に対応するキーの可変引数 114 */ 115 AbstractOption( final String... prm ) { 116 super(); 117 someOption = Arrays.asList( prm ); 118 } 119 120 /** 121 * このオプションが消費する引数の数を返します。 122 * 123 * @return 消費された引数の数 124 */ 125 @Override 126 public int getArgumentCount() { 127 return 1; 128 } 129 130 /** 131 * オプションの説明を返します。 132 * 133 * @return 設定されている場合はdescription、そうでない場合は空のString 134 */ 135 @Override 136 public String getDescription() { 137 return "an option with aliases"; 138 } 139 140 /** 141 * オプションの種類を返します。 142 * 143 * @return このオプションの種類 144 */ 145 @Override 146 public Option.Kind getKind() { 147 return Option.Kind.STANDARD; 148 } 149 150 /** 151 * オプションを識別するために使用される可能性のある名前のリストを返します。 152 * 153 * @return オプションの名前リスト 154 */ 155 @Override 156 public List<String> getNames() { 157 return someOption; 158 } 159 160 /** 161 * オプションのパラメータを返します。 162 * 163 * @return 設定されている場合はパラメータ、それ以外の場合は空のString 164 */ 165 @Override 166 public String getParameters() { 167 return "file"; 168 } 169 } 170 171 /** 172 * このドックレットでサポートされているJavaプログラミング言語のバージョンを返します。 173 * 174 * @return 通常は最新バージョン 175 */ 176 @Override 177 public SourceVersion getSupportedSourceVersion() { 178 // support the latest release 179 return SourceVersion.latest(); 180 } 181 182 /* ************************************************************************************ */ 183 184// /** 185// * 指定の文字列から、開始文字と終了文字の間を切り抜いて返します。 186// * 開始文字か、終了文字のどちらかが存在しない場合は、オリジナルの文字列を返します。 187// * 188// * @param org オリジナルの文字列 189// * @param stCh 開始文字 190// * @param edCh 終了文字 191// * 192// * @return 切り抜かれた文字列 193// */ 194// protected String cut( final String org , final char stCh , final char edCh ) { 195// final int st = org.indexOf( stCh ); 196// final int ed = st > 0 ? org.indexOf( edCh , st ) : -1; 197// 198// return ed > 0 ? org.substring( st+1,ed ) : org ; 199// } 200 201// /** 202// * 指定の文字列から、開始文字と終了文字の間を切り抜いて返します。 203// * 開始文字か、終了文字のどちらかが存在しない場合は、オリジナルの文字列を返します。 204// * 205// * @param org オリジナルの文字列 206// * @param omit 先頭から削除する文字列 207// * 208// * @return 切り抜かれた文字列 209// */ 210// protected String cutTag( final String org , final String omit ) { 211// return org.substring( 1+omit.length() ).trim(); 212// } 213 214 /** 215 * BlockTagsのキーとリストのMapを作成して返します。 216 * キーと値を分離します。同じキーが複数存在しますので、それらは Listに入れて返します。 217 * docTreeは、null の場合もあるので、その場合は、空のMapを返します。 218 * 219 * @param docTree DocCommentTreeオブジェクト 220 * 221 * @return BlockTagsのキーとリストのMap 222 */ 223 protected Map<String,List<String>> blockTagsMap( final DocCommentTree docTree ) { 224 final Map<String,List<String>> rtnMap = new HashMap<>(); 225 226 if( docTree != null ) { 227 for( final DocTree dt : docTree.getBlockTags() ) { 228 final String tag = String.valueOf(dt).trim(); 229 final int ad = tag.indexOf( ' ' ); // 最初のスペースで分離 230 final String key = ad > 0 ? tag.substring( 1,ad ).trim() : tag ; // 最初の文字列は、@ なので。 231 final String val = ad > 0 ? tag.substring( ad+1 ).trim() : "" ; 232 233 rtnMap.computeIfAbsent(key, k -> new ArrayList<String>()).add( val ); 234 } 235 } 236 237 return rtnMap; 238 } 239 240 /** 241 * blockTagsMapで作成されたMapオブジェクトから、文字列を作成します。 242 * キーがMapに存在しない場合は、空文字列を返します。 243 * docTreeは、null の場合もあるので、その場合は、空のMapを返します。 244 * 245 * @param key blockTagのキー 246 * @param blcMap blockTagsMapで作成されたMapオブジェクト 247 * @param delimiter 複数タグを連結する場合の、区切り文字 248 * 249 * @return 指定のタグの文字列 250 */ 251 protected String getBlockTag( final String key,final Map<String,List<String>> blcMap,final String delimiter ) { 252 final List<String> blkList = blcMap.get( key ); 253 254 return blkList == null ? "" : String.join( delimiter,blkList ); 255 } 256 257 /** 258 * DocTreeリストから、最初の1文(改行か『。』まで)と本文の文字列を切り出します。 259 * 260 * title が、docTree.getFirstSentence(); でうまく取れていないようです。 261 * docTree.getFullBody() で取ってきた最初の1文と、残りの本文を切り出します。 262 * 263 * @og.rev 8.0.1.0 (2021/10/29) titleを改行か『。』までの文字列を切り出す。 264 * @og.rev 8.0.2.1 (2021/12/10) コメント分割で『。』と半角の『。』の両方対応しておく。 265 * @og.rev 8.0.2.1 (2021/12/10) DocTreeParam → AbstractDocTree に移動 266 * 267 * @param docTree DocCommentTreeオブジェクト 268 * @return 最初の1文(改行か『。』まで)と本文の文字列を分割した配列 269 */ 270 protected String[] getTitleCmnt( final DocCommentTree docTree ) { 271 final String[] rtns = { "","" }; // 初期値 272 273 if( docTree == null ) { return rtns; } 274 final List<? extends DocTree> doc = docTree.getFullBody(); 275 if( doc.isEmpty() ) { return rtns; } 276// final String body = String.valueOf( doc.get(0) ); 277 278 final StringBuilder buf = new StringBuilder(); // 8.0.2.1 (2021/12/10) & で切れる? 279 doc.forEach( val -> buf.append(val) ); 280 final String body = buf.toString(); 281 282// int st = body.indexOf( '。' ); 283 int st = Math.max( body.indexOf( '。' ) , body.indexOf( '。' ) ); // 8.0.2.1 (2021/12/10) 284 if( st < 0 ) { 285 st = body.indexOf( '\n' ); 286 } 287 288 if( st >= 0 ) { 289 rtns[0] = body.substring( 0,st ).trim(); // 一応、スペースは削除する。 290 rtns[1] = body.substring( st ).trim(); // 291 if( rtns[1].isEmpty() ) { rtns[1] = rtns[0]; } 292 } 293 else { 294 rtns[0] = body.trim(); 295 rtns[1] = rtns[0]; // 8.0.2.1 (2021/12/10) 同じ値をセットする。 296 } 297 298 return rtns ; 299 } 300}