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 // Doclet 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 // Doclet 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 // Doclet.Option 126 public int getArgumentCount() { 127 return 1; 128 } 129 130 /** 131 * オプションの説明を返します。 132 * 133 * @return 設定されている場合はdescription、そうでない場合は空のString 134 */ 135 @Override // Doclet.Option 136 public String getDescription() { 137 return "an option with aliases"; 138 } 139 140 /** 141 * オプションの種類を返します。 142 * 143 * @return このオプションの種類 144 */ 145 @Override // Doclet.Option 146 public Option.Kind getKind() { 147 return Option.Kind.STANDARD; 148 } 149 150 /** 151 * オプションを識別するために使用される可能性のある名前のリストを返します。 152 * 153 * @return オプションの名前リスト 154 */ 155 @Override // Doclet.Option 156 public List<String> getNames() { 157 return someOption; 158 } 159 160 /** 161 * オプションのパラメータを返します。 162 * 163 * @return 設定されている場合はパラメータ、それ以外の場合は空のString 164 */ 165 @Override // Doclet.Option 166 public String getParameters() { 167 return "file"; 168 } 169 } 170 171 /** 172 * このドックレットでサポートされているJavaプログラミング言語のバージョンを返します。 173 * 174 * @return 通常は最新バージョン 175 */ 176 @Override // Doclet 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// * @return 切り抜かれた文字列 192// */ 193// protected String cut( final String org , final char stCh , final char edCh ) { 194// final int st = org.indexOf( stCh ); 195// final int ed = st > 0 ? org.indexOf( edCh , st ) : -1; 196// 197// return ed > 0 ? org.substring( st+1,ed ) : org ; 198// } 199 200// /** 201// * 指定の文字列から、開始文字と終了文字の間を切り抜いて返します。 202// * 開始文字か、終了文字のどちらかが存在しない場合は、オリジナルの文字列を返します。 203// * 204// * @param org オリジナルの文字列 205// * @param omit 先頭から削除する文字列 206// * @return 切り抜かれた文字列 207// */ 208// protected String cutTag( final String org , final String omit ) { 209// return org.substring( 1+omit.length() ).trim(); 210// } 211 212 /** 213 * BlockTagsのキーとリストのMapを作成して返します。 214 * キーと値を分離します。同じキーが複数存在しますので、それらは Listに入れて返します。 215 * docTreeは、null の場合もあるので、その場合は、空のMapを返します。 216 * 217 * @param docTree DocCommentTreeオブジェクト 218 * @return BlockTagsのキーとリストのMap 219 */ 220 protected Map<String,List<String>> blockTagsMap( final DocCommentTree docTree ) { 221 final Map<String,List<String>> rtnMap = new HashMap<>(); 222 223 if( docTree != null ) { 224 for( final DocTree dt : docTree.getBlockTags() ) { 225 final String tag = String.valueOf(dt).trim(); 226 final int ad = tag.indexOf( ' ' ); // 最初のスペースで分離 227 final String key = ad > 0 ? tag.substring( 1,ad ).trim() : tag ; // 最初の文字列は、@ なので。 228 final String val = ad > 0 ? tag.substring( ad+1 ).trim() : "" ; 229 230 rtnMap.computeIfAbsent(key, k -> new ArrayList<String>()).add( val ); 231 } 232 } 233 234 return rtnMap; 235 } 236 237 /** 238 * blockTagsMapで作成されたMapオブジェクトから、文字列を作成します。 239 * キーがMapに存在しない場合は、空文字列を返します。 240 * docTreeは、null の場合もあるので、その場合は、空のMapを返します。 241 * 242 * @param key blockTagのキー 243 * @param blcMap blockTagsMapで作成されたMapオブジェクト 244 * @param delimiter 複数タグを連結する場合の、区切り文字 245 * @return 指定のタグの文字列 246 */ 247 protected String getBlockTag( final String key,final Map<String,List<String>> blcMap,final String delimiter ) { 248 final List<String> blkList = blcMap.get( key ); 249 250 return blkList == null ? "" : String.join( delimiter,blkList ); 251 } 252 253 /** 254 * DocTreeリストから、最初の1文(改行か『。』まで)と本文の文字列を切り出します。 255 * 256 * title が、docTree.getFirstSentence(); でうまく取れていないようです。 257 * docTree.getFullBody() で取ってきた最初の1文と、残りの本文を切り出します。 258 * 259 * @og.rev 8.0.1.0 (2021/10/29) titleを改行か『。』までの文字列を切り出す。 260 * @og.rev 8.0.2.1 (2021/12/10) コメント分割で『。』と半角の『。』の両方対応しておく。 261 * @og.rev 8.0.2.1 (2021/12/10) DocTreeParam → AbstractDocTree に移動 262 * @og.rev 8.5.1.0 (2023/06/30) docTreeの変換がunicodeの為、正しく動作しなかった『。』変換対応 263 * 264 * @param docTree DocCommentTreeオブジェクト 265 * @return 最初の1文(改行か『。』まで)と本文の文字列を分割した配列 266 */ 267 protected String[] getTitleCmnt( final DocCommentTree docTree ) { 268 final String[] rtns = { "","" }; // 初期値 269 270 if( docTree == null ) { return rtns; } 271 final List<? extends DocTree> doc = docTree.getFullBody(); 272 if( doc.isEmpty() ) { return rtns; } 273// final String body = String.valueOf( doc.get(0) ); 274 275 final StringBuilder buf = new StringBuilder(); // 8.0.2.1 (2021/12/10) & で切れる? 276 doc.forEach( val -> buf.append(val) ); 277 final String body = buf.toString(); 278 279// int st = body.indexOf( '。' ); 280// int st = Math.max( body.indexOf( '。' ) , body.indexOf( '。' ) ); // 8.0.2.1 (2021/12/10) 281 int st = Math.max( body.indexOf( "u3002" ) , body.indexOf( "uff61" ) ); // 8.5.1.0 (2023/06/27) Modify 282 283 if( st < 0 ) { 284 st = body.indexOf( '\n' ); 285 } 286 287 if( st >= 0 ) { 288 st += 5; // 8.5.1.0 (2023/06/27) Add 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}