OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / fukurou / taglet / DocTreeSpecific.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.fukurou.taglet;            // 7.4.4.0 (2021/06/30) openGionV8事前準備(taglet2→taglet)
17
18 import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
19
20 import jdk.javadoc.doclet.DocletEnvironment      ;
21 // import jdk.javadoc.doclet.Doclet  ;
22 // import jdk.javadoc.doclet.Reporter ;
23 import javax.lang.model.element.Element ;
24 import javax.lang.model.element.Modifier ;
25 import javax.lang.model.element.TypeElement;
26 import javax.lang.model.element.ElementKind     ;
27 import javax.lang.model.element.VariableElement;
28 import javax.lang.model.element.ExecutableElement;
29 // import javax.lang.model.SourceVersion ;
30 import javax.lang.model.type.TypeMirror;
31 import javax.lang.model.type.TypeKind;
32 import javax.lang.model.util.ElementFilter ;
33 import javax.lang.model.util.Elements ;
34 import javax.lang.model.util.Types ;
35 import javax.tools.Diagnostic.Kind ;
36 import com.sun.source.doctree.DocCommentTree ;
37 import com.sun.source.util.DocTrees  ;
38 // import com.sun.source.util.DocSourcePositions ;
39 import com.sun.source.doctree.DocTree  ;
40
41 // import java.util.Locale ;
42 import java.util.Set;
43 import java.util.List;
44 import java.util.HashSet;
45 import java.util.Arrays;
46 // import java.util.stream.Stream;                                                                              // 6.4.3.4 (2016/03/11)
47 // import java.util.stream.Collectors;                                                                  // 6.4.3.4 (2016/03/11)
48 // import java.util.regex.Pattern;                                                                              // 6.3.9.1 (2015/11/27) final化に伴う整理
49
50 // import java.io.IOException;
51 // import java.io.File;
52 // import java.io.PrintWriter;
53 import java.util.stream.Stream;                                                                         // 6.4.3.4 (2016/03/11)
54 import java.util.stream.Collectors;                                                                     // 6.4.3.4 (2016/03/11)
55 import java.util.Map;
56
57 // import org.opengion.fukurou.util.FileUtil;
58 // import org.opengion.fukurou.util.StringUtil;
59
60 /**
61  * ソースコメントから、パラメータ情報を取り出す Doclet クラスです。
62  * og.paramLevel タグと og.cryptography タグを切り出します。
63  * これらは、システムパラメータとしてGE12テーブルに設定される値をクラスより抽出する
64  * のに使用します。
65  *
66  * @version  7.3
67  * @author      Kazuhiko Hasegawa
68  * @since        JDK11.0,
69  */
70 public class DocTreeSpecific extends AbstractDocTree {
71         private static final String  SELECT_PACKAGE     = "org.opengion" ;
72         private static final boolean USE_PRIVATE        = false ;
73
74         private static final String     OG_FOR_SMPL             = "og.formSample";
75         private static final String     OG_REV                  = "og.rev";
76         private static final String     OG_GROUP                = "og.group";
77         private static final String     DOC_VERSION             = "version";
78         private static final String     DOC_AUTHOR              = "author";
79         private static final String     DOC_SINCE               = "since";
80
81 //      private static final String OG_TAG_NAME         = "og.tag";                             // 6.1.2.0 (2015/01/24) チェック用
82 //      private static final String     DOC_PARAM               = "param";                              // 5.1.9.0 (2010/08/01) チェック用
83 //      private static final String     DOC_RETURN              = "return";                             // 5.1.9.0 (2010/08/01) チェック用
84
85         private static final String     CONSTRUCTOR             = "コンストラクタ" ;
86         private static final String     METHOD                  = "メソッド" ;
87
88         private String  version         ;
89         private String  outfile         ;
90         private int             debugLevel      ;               // 0:なし 1:最小チェック 2:日本語化 3:体裁 4:Verチェック 5:taglibラベル
91
92         private final Set<String> mtdClsSet = new HashSet<>();
93
94         // 5.1.9.0 (2010/08/01) ソースチェック用(半角文字+空白文字のみ)
95 //      private static final Pattern PTN = Pattern.compile("[\\w\\s]+");                // 6.3.9.1 (2015/11/27)
96
97 //      private DocTrees docUtil;
98 //      private Elements eleUtil ;
99         private Types    typUtil ;
100
101         /**
102          * デフォルトコンストラクター
103          *
104          * @og.rev 7.3.0.0 (2021/01/06) PMD refactoring. Each class should declare at least one constructor.
105          */
106         public DocTreeSpecific() { super(); }           // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
107
108         /**
109          * Doclet のエントリポイントメソッドです(昔の startメソッド)。
110          *
111          * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
112          *
113          * @param docEnv ドックレットを1回呼び出す操作環境
114          *
115          * @return 正常実行時 true
116          */
117         @Override
118         public boolean run( final DocletEnvironment docEnv ) {
119                 try( DocTreeWriter writer = new DocTreeWriter( outfile,ENCODE ) ) {
120                         writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE , "\" ?>" );
121                         writer.printTag( "<javadoc>" );
122                         writer.printTag( "  <version>",version,"</version>" );
123                         writer.printTag( "  <description></description>" );
124                         writeContents( docEnv,writer );
125                         writer.printTag( "</javadoc>" );
126                 }
127                 catch( final Throwable th ) {
128                         reporter.print(Kind.ERROR, th.getMessage());
129                 }
130
131                 return true;
132         }
133
134         /**
135          * DocletEnvironmentよりコンテンツを作成します。
136          *
137          * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
138          * @og.rev 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
139          * @og.rev 8.0.2.1 (2021/12/10) コメント分割で『。』と半角の『。』の両方対応しておく。
140          *
141          * @param docEnv        ドックレットの最上位
142          * @param writer        DocTreeWriterオブジェクト
143          */
144         private void writeContents( final DocletEnvironment docEnv, final DocTreeWriter writer ) {
145 //              docUtil = docEnv.getDocTrees();
146                 final DocTrees docUtil = docEnv.getDocTrees();
147                 final Elements eleUtil = docEnv.getElementUtils();
148                 typUtil = docEnv.getTypeUtils();
149
150                 final StringBuilder modiBuf = new StringBuilder();                      // 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
151                 final StringBuilder buf     = new StringBuilder();                      // 8.0.0.0 (2021/07/31) Avoid instantiating new objects inside loops
152
153                 // クラス単位にループする。
154                 for( final TypeElement typEle : ElementFilter.typesIn(docEnv.getIncludedElements())) {
155                         final String fullName   = String.valueOf( typEle.getQualifiedName() ) ;
156                         writer.setClassName( fullName );
157
158                         final String className = String.valueOf( typEle.getSimpleName() );
159
160 //                      final StringBuilder modiBuf = new StringBuilder();
161                         modiBuf.setLength( 0 ) ;                                                                // 8.0.0.0 (2021/07/31)
162                         typEle.getModifiers().forEach( modi -> modiBuf.append( modi ).append( ' ' ) );
163                         final ElementKind eleKind = typEle.getKind();
164                         if( ElementKind.CLASS.equals( eleKind ) ) { modiBuf.append( "class" ); }
165                         final String modifiers = modiBuf.toString().trim();
166
167                         final TypeMirror superType      = typEle.getSuperclass();
168                         final String superClass = TypeKind.NONE.equals( superType.getKind() ) ? "" : superType.toString();
169
170                         final String intFase = Stream.of( typEle.getInterfaces() )
171                                                                                 .map( typ -> String.valueOf(typ) )
172                                                                                 .collect( Collectors.joining( "," ) );
173
174                         final DocCommentTree docTree = docUtil.getDocCommentTree(typEle);               // ドキュメンテーション・コメントが見つからない場合、null が返る。
175
176 //                      final List<? extends DocTree> desc      = docTree == null ? EMPTY_LIST : docTree.getFirstSentence();
177 //                      final List<? extends DocTree> cmnt      = docTree == null ? EMPTY_LIST : docTree.getFullBody();
178                         final String[] cmnts = getTitleCmnt( docTree );                                                 // 8.0.2.1 (2021/12/10)
179
180                         final Map<String,List<String>> blkTagMap = blockTagsMap(docTree);
181                         final String smplTags   = getBlockTag( OG_FOR_SMPL, blkTagMap, ""   );
182                         final String revTags    = getBlockTag( OG_REV     , blkTagMap, "\n" );
183                         final String createVer  = getBlockTag( DOC_VERSION, blkTagMap, ""   );
184                         final String author             = getBlockTag( DOC_AUTHOR , blkTagMap, ""   );
185                         final String since              = getBlockTag( DOC_SINCE  , blkTagMap, ""   );
186                         final String grpTags    = getBlockTag( OG_GROUP   , blkTagMap, ","  );
187
188                         // 5.7.1.1 (2013/12/13) タグのインデントを止める。
189                         writer.printTag( "<classDoc>" );
190                         writer.printTag( "  <fullName>"         ,fullName               ,"</fullName>"          );
191                         writer.printTag( "  <modifiers>"        ,modifiers              ,"</modifiers>"         );
192                         writer.printTag( "  <className>"        ,className              ,"</className>"         );
193                         writer.printTag( "  <superClass>"       ,superClass             ,"</superClass>"        );
194                         writer.printTag( "  <interface>"        ,intFase                ,"</interface>"         );
195                         writer.printTag( "  <createVer>"        ,createVer              ,"</createVer>"         );
196                         writer.printTag( "  <author>"           ,author                 ,"</author>"            );
197                         writer.printTag( "  <since>"            ,since                  ,"</since>"                     );
198 //                      writer.printTag( "  <description>"      ,desc                   ,"</description>"       );
199                         writer.printTag( "  <description>"      ,cmnts[0]               ,"</description>"       );              // 8.0.2.1 (2021/12/10)
200 //                      writer.printTag( "  <contents>"         ,cmnt                   ,"</contents>"          );
201                         writer.printTag( "  <contents>"         ,cmnts[1]               ,"</contents>"          );              // 8.0.2.1 (2021/12/10)
202                         writer.printTag( "  <classGroup>"       ,grpTags                ,"</classGroup>"        );
203                         writer.printTag( "  <formSample>"       ,smplTags               ,"</formSample>"        );
204                         writer.printTag( "  <history>"          ,revTags                ,"</history>"           );
205
206                         // 5.1.9.0 (2010/08/01) ソースチェック用(コメントや概要が無い場合。スーパークラスは省く)
207 //                      if( debugLevel >= 2 && ( cmnt.isEmpty() || desc.isEmpty() ) && superClass.isEmpty() ) {
208                         if( debugLevel >= 2 && ( cmnts[0].isEmpty() || cmnts[1].isEmpty() ) && superClass.isEmpty() ) { // 8.0.2.1 (2021/12/10)
209         //                      final DocSourcePositions srcPos = docUtil.getSourcePositions();
210         //                      System.err.println( "警告2:コメントC=\t" + srcPos );
211                                 System.err.println( "②警告2:コメントC=\t" + typEle );
212                         }
213
214                         int extendFlag = 0;             // 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend
215
216                         // 6.4.3.0 (2016/02/05) PMDチェックのDocletでのフォロー。
217         //              checkPMD( typEle );
218
219                         // 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメントの比較チェック
220                         // while 以下で、fullName と classDoc を順番に上にさかのぼっているので、先にチェックします。
221         //              checkTag2( typEle );
222
223                         mtdClsSet.clear();
224                         TypeElement loopEle = typEle;
225                         String superName = fullName;
226                         while( loopEle != null ) {
227                                 writer.setClassName( superName );
228
229                                 // 対象クラスの スーパークラスを取得しておく(メソッド内で使うのと、上位に上がってく時に使う)
230                                 final TypeMirror spType = loopEle.getSuperclass();
231
232                                 // AbstractObjectPool<java.sql.Connection> の様な型を削除します。
233 //                              final StringBuilder buf = new StringBuilder().append(spType);
234                                 buf.setLength( 0 ) ;                                                            // 8.0.0.0 (2021/07/31)
235                                 buf.append(spType) ;                                                            // 8.0.0.0 (2021/07/31)
236
237                                 int st = buf.indexOf("<");
238                                 int ed = buf.indexOf(">",st);
239                                 while( st > 0 ) {
240                                         buf.delete(st,ed+1);
241                                         st = buf.indexOf("<");
242                                         ed = buf.indexOf(">",st);
243                                 }
244                                 superName = buf.toString();
245                 //              superName = String.valueOf( spType );
246
247                                 final String extClass   = ( extendFlag == 0 ) ? "" : superName ;
248
249                                 // コンストラクタのみフィルタリングして取得する
250                                 for( final ExecutableElement exEle : ElementFilter.constructorsIn(loopEle.getEnclosedElements()) ) {
251                                         final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ドキュメンテーション・コメントが見つからない場合、null が返る。
252                                         if( dct != null && isAction( exEle,extendFlag ) ) {
253                 //                              checkTag( exEle,dct );                                                                                  // 5.5.4.1 (2012/07/06) チェックを分離
254                                                 menberTag( exEle,dct,CONSTRUCTOR,writer,extendFlag,extClass );
255                                         }
256                                 }
257
258                                 // メソッドのみフィルタリングして取得する
259                                 for( final ExecutableElement exEle : ElementFilter.methodsIn(loopEle.getEnclosedElements())) {
260                                         final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ドキュメンテーション・コメントが見つからない場合、null が返る。
261                                         if( dct != null && isAction( exEle,extendFlag ) ) {
262                 //                              checkTag( exEle,dct );
263                                                 menberTag( exEle,dct,METHOD,writer,extendFlag,extClass );
264                                         }
265                                 }
266
267                                 // 対象クラス(オリジナル)から、上に上がっていく。
268                                 if( superName.startsWith( SELECT_PACKAGE ) ) {
269                                         extendFlag = 1;
270                                 }
271                                 else {
272                                         break;
273                                 }
274
275                                 loopEle = eleUtil.getTypeElement(superName);
276                         }
277                         writer.printTag( "</classDoc>" );
278                 }
279         }
280
281         /**
282          * メンバークラスのXML化を行うかどうか[true/false]を判定します。
283          *
284          * 以下の条件に合致する場合は、処理を行いません。(false を返します。)
285          *
286          * 1.同一クラスを処理中にEXTENDで継承元をさかのぼる場合、すでに同じシグネチャのメソッドが
287          *     存在している。
288          * 2.USE_PRIVATE が true の時の private メソッド
289          * 3.extendFlag が 0以上(1,2)の時の private メソッド
290          * 4.メソッド名におかしな記号(&lt;など)が含まれている場合
291          *
292          * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
293          *
294          * @param       menber ExecutableMemberDocオブジェクト
295          * @param       extendFlag      継承状態 [0:オリジナル/1:org.opengion関連Extend/2:Java関連Extend]
296          *
297          * @return      XML化を行うかどうか[true/false]
298          */
299         private boolean isAction( final ExecutableElement menber,final int extendFlag ) {
300 //              final String menberName = String.valueOf( menber.getSimpleName() ) ;
301                 final boolean isPrivate   = menber.getModifiers().contains( Modifier.PRIVATE );
302                 final boolean isTypeParam = ! menber.getTypeParameters().isEmpty();
303                 final boolean rtn = ! mtdClsSet.add( String.valueOf( menber ) )         // 5.5.4.1 (2012/07/06) メソッドの重複処理判定は、クラス名も含めて行う
304                                                 ||      USE_PRIVATE    && isPrivate
305                                                 ||      extendFlag > 0 && isPrivate
306                                                 ||      isTypeParam;                                                                    // PMD Useless parentheses.
307
308                 return ! rtn ;
309         }
310
311 //      /**
312 //       * param,return 等の整合性をチェックします。
313 //       *
314 //       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
315 //       *
316 //       * @param exEle ExecutableElementオブジェクト
317 //       * @param menber DocCommentTreeオブジェクト
318 //       */
319 //      private void checkTag( final ExecutableElement exEle , final DocCommentTree menber ) {
320 //              // 未実装
321 //      }
322
323 //      /**
324 //       * PMDで、チェックしている処理のうち、Docletでフォローできる分をチェックします。
325 //       *
326 //       * ※ このチェックは、警告レベル5 のみ集約していますので、呼出元で、制限します。
327 //       *
328 //       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
329 //       *
330 //       * @param typEle TypeElementオブジェクト
331 //       */
332 //      private void checkTag2( final TypeElement typEle ) {
333 //              String cnstVar = null ;         // 初期値
334 //              String seriUID = null ;
335 //              final String src = "\tsrc/" + String.valueOf(typEle).replace('.','/') + ".java:100" ;                   // 行が判らないので、100行目 決め打ち
336 //
337 //              // フィールドのみフィルタリングして取得する
338 //              for( final VariableElement varEle : ElementFilter.fieldsIn(typEle.getEnclosedElements())) {             // フィールドだけに絞る
339 //                      final String key = String.valueOf(varEle);
340 //                      if( "VERSION".equals( key ) ) {
341 //                              cnstVar = String.valueOf( varEle.getConstantValue() );
342 //                      }
343 //                      else if( "serialVersionUID".equals( key ) ) {
344 //                              seriUID = String.valueOf( varEle.getConstantValue() ) + "L";                    // 旧JavaDocと違い、"L" まで取ってこれないみたい
345 //                      }
346 //              }
347 //
348 //              if( cnstVar == null ) { return; }                               // VERSION が未定義のクラスは処理しない
349 //
350 //              String maxRev = cnstVar ;                                               // 5.7.1.1 (2013/12/13) 初期値
351 //              boolean isChange = false;                                               // max が入れ替わったら、true
352 //
353 //              // メソッドのみフィルタリングして取得する
354 //              for( final ExecutableElement exEle : ElementFilter.methodsIn(typEle.getEnclosedElements())) {
355 //                      final DocCommentTree dct = docUtil.getDocCommentTree(exEle);            // ドキュメンテーション・コメントが見つからない場合、null が返る。
356 //                      final Map<String,List<String>> blkTagMap = blockTagsMap(dct);
357 //                      final List<String> revTags = blkTagMap.get("og.rev");
358 //
359 //                      if( revTags != null ) {
360 //                              for( final String tag :revTags ) {                                                              // 複数存在しているはず
361 //                                      final int idx = tag.indexOf( ' ' );                                                     // 最初のスペース
362 //                                      if( idx > 0 ) {
363 //                                              final String rev = tag.substring( 0,idx ).trim();
364 //                                              if( maxRev.compareTo( rev ) < 0 ) {                                             // revTags の og.rev が大きい場合
365 //                                                      maxRev = rev ;
366 //                                                      isChange = true;
367 //                                              }
368 //                                      }
369 //                              }
370 //                      }
371 //              }
372 //
373 //              // VERSION 文字列 の定義があり、かつ、max の入れ替えが発生した場合のみ、警告4:VERSIONが古い
374 //              if( isChange ) {                        // 5.7.1.1 (2013/12/13) 入れ替えが発生した場合
375 //                      System.err.println( "警告4:VERSIONが古い=\t" + cnstVar + " ⇒ " + maxRev + src );
376 //              }
377 //
378 //              // serialVersionUID の定義がある。
379 //              if( seriUID != null ) {
380 //                      final StringBuilder buf = new StringBuilder();
381 //                      // maxRev は、最大の Revか、初期のVERSION文字列 例:5.6.6.0 (2013/07/05)
382 //                      for( int i=0; i<maxRev.length(); i++ ) {        //
383 //                              final char ch = maxRev.charAt( i );
384 //                              if( ch >= '0' && ch <= '9' ) { buf.append( ch ); }      // 数字だけ取り出す。 例:566020130705
385 //                      }
386 //                      buf.append( 'L' );      // 強制的に、L を追加する。
387 //                      final String maxSeriUID = buf.toString() ;
388 //
389 //                      // 5.7.1.1 (2013/12/13) 値の取出し。Long型を表す "L" も含まれている。
390 //                      if( !maxSeriUID.equals( seriUID ) ) {   // 一致しない
391 //                              System.err.println( "警告4:serialVersionUIDが古い=\t" + seriUID + " ⇒ " + maxSeriUID + src );
392 //                      }
393 //              }
394 //      }
395
396 //      /**
397 //       * PMDで、チェックしている処理のうち、Docletでフォローできる分をチェックします。
398 //       *
399 //       * ※ このチェックは、警告レベル5 のみ集約していますので、呼出元で、制限します。
400 //       *
401 //       * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
402 //       *
403 //       * @param typEle TypeElementオブジェクト
404 //       */
405 //      private void checkPMD( final TypeElement typEle ) {
406 //              // 未実装
407 //      }
408
409         /**
410          * メンバークラス(コンストラクタ、メソッド)をXML化します。
411          *
412          * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応
413          * @og.rev 8.0.2.1 (2021/12/10) コメント分割で『。』と半角の『。』の両方対応しておく。
414          *
415          * @param       menber          ExecutableElementオブジェクト
416          * @param       docTree         DocCommentTreeオブジェクト
417          * @param       menberType      メンバータイプ(コンストラクタ、メソッド)
418          * @param       writer          Tagを書き出すWriterオブジェクト
419          * @param       extendFlag      継承状態 [0:オリジナル/1::org.opengion関連Extend/2:Java関連Extend]
420          * @param       extClass        継承クラス(オリジナルの場合は、空文字列)
421          */
422         private void menberTag( final ExecutableElement menber,
423                                                         final DocCommentTree docTree ,
424                                                         final String menberType,
425                                                         final DocTreeWriter writer,
426                                                         final int extendFlag ,
427                                                         final String extClass ) {
428
429                 final String modifiers ;
430
431                 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
432                 menber.getModifiers().forEach( modi -> buf.append( modi ).append( ' ' ) );
433                 if( ElementKind.METHOD.equals( menber.getKind() ) ) {           // メソッドの処理。コンストラクタの場合は、返り値がないので処理しない。
434                         buf.append( menber.getReturnType() );
435                 }
436                 modifiers = buf.toString();
437
438                 final String menberName = String.valueOf( menber.getSimpleName() );                     // コンストラクタの場合は、<init> が返る。
439
440                 final StringBuilder sigBuf = new StringBuilder().append( menberName ).append( '(' ) ;
441                 boolean flag = false;
442                 for( final VariableElement valEle : menber.getParameters() ) {
443                         flag = true;
444                         final Element ele = typUtil.asElement( valEle.asType() );               // 型が対応する要素を持たない場合はnullを返します。
445                         final String key = ele == null                                                                  // 配列や、プリミティブ型の場合は、null になっている。
446                                                                         ? String.valueOf( valEle.asType() )
447                                                                         : String.valueOf( ele.getSimpleName() );
448
449                         sigBuf.append( key ).append( ' ' )
450                                         .append( valEle.getSimpleName() ).append( ',' );
451                 }
452
453                 if( flag ) { sigBuf.deleteCharAt( sigBuf.length()-1 ); }
454                 sigBuf.append( ')' );
455                 final String signature = sigBuf.toString();
456 //              final String signature = String.valueOf( menber );
457
458 //              final List<? extends DocTree> desc      = docTree == null ? EMPTY_LIST : docTree.getFirstSentence();
459 //              final List<? extends DocTree> cmnt      = docTree == null ? EMPTY_LIST : docTree.getFullBody();
460                 final String[] cmnts = getTitleCmnt( docTree );                                                 // 8.0.2.1 (2021/12/10)
461
462                 final Map<String,List<String>> blkTagMap = blockTagsMap(docTree);
463                 final String revTags = getBlockTag( OG_REV, blkTagMap, "\n" );
464
465                 // tags は、OG_REV 以外のすべてで、かつ、キーワードも含む。
466                 final StringBuilder tagBuf = new StringBuilder();
467                 if( docTree != null ) {
468                         for( final DocTree dt : docTree.getBlockTags() ) {
469                                 final String tag = String.valueOf(dt).trim();
470                                 if( !tag.contains( OG_REV ) ) { tagBuf.append( tag ).append( '\n' ); }
471                         }
472                 }
473                 final String tags = tagBuf.toString().trim();
474
475 //              final StringBuilder tagBuf = new StringBuilder();
476 //              final StringBuilder revBuf = new StringBuilder();
477 //              if( docTree != null ) {
478 //                      for( final DocTree dt : docTree.getBlockTags() ) {
479 //                              final String tag = String.valueOf(dt).trim();
480 //                              if( tag.contains( OG_REV ) ) { revBuf.append( cutTag( tag,OG_REV ) ).append( '\n' ); }
481 //                              else { tagBuf.append( tag ).append( '\n' ); }
482 //                      }
483 //              }
484 //              final String revTags = revBuf.toString().trim();
485 //              final String tags    = tagBuf.toString().trim();
486
487                 final String    extend  = String.valueOf( extendFlag );
488
489         //      final DocSourcePositions srcPos = docUtil.getSourcePositions();
490         //      final String    position = String.valueOf( srcPos.getStartPosition( null,docTree,null ) );
491                 final String    position = "";
492
493                 writer.printTag( "  <menber>" );
494                 writer.printTag( "    <type>"           ,menberType     ,"</type>"                      );
495                 writer.printTag( "    <name>"           ,menberName     ,"</name>"                      );
496                 writer.printTag( "    <modifiers>"      ,modifiers      ,"</modifiers>"         );
497                 writer.printTag( "    <signature>"      ,signature      ,"</signature>"         );
498                 writer.printTag( "    <position>"       ,position       ,"</position>"          );
499                 writer.printTag( "    <extendClass>",extClass   ,"</extendClass>"       );
500                 writer.printTag( "    <extendFlag>"     ,extend         ,"</extendFlag>"        );
501 //              writer.printTag( "    <description>",desc               ,"</description>"       );
502                 writer.printTag( "    <description>",cmnts[0]   ,"</description>"       );              // 8.0.2.1 (2021/12/10)
503 //              writer.printTag( "    <contents>"       ,cmnt           ,"</contents>"          );
504                 writer.printTag( "    <contents>"       ,cmnts[1]       ,"</contents>"          );              // 8.0.2.1 (2021/12/10)
505                 writer.printTag( "    <tagText>"        ,tags           ,"</tagText>"           );
506                 writer.printTag( "    <history>"        ,revTags        ,"</history>"           );
507                 writer.printTag( "  </menber>");
508         }
509
510         /**
511          * サポートされているすべてのオプションを返します。
512          *
513          * @return サポートされているすべてのオプションを含むセット、存在しない場合は空のセット
514          */
515         @Override
516         public Set<? extends Option> getSupportedOptions() {
517                 final Option[] options = {
518                         new AbstractOption( "-outfile", "-version", "-debugLevel" ) {
519
520                                 /**
521                                  * 必要に応じてオプションと引数を処理します。
522                                  *
523                                  * @param  opt オプション名
524                                  * @param  arguments 引数をカプセル化したリスト
525                                  * @return 操作が成功した場合はtrue、そうでない場合はfalse
526                                  */
527                                 @Override
528                                 public boolean process(final String opt, final List<String> arguments) {
529                                         if( "-outfile".equalsIgnoreCase(opt) ) {
530                                                 outfile = arguments.get(0);
531                                         }
532                                         else if( "-version".equalsIgnoreCase(opt) ) {
533                                                 version = arguments.get(0);
534                                         }
535                                         else if( "-debugLevel".equalsIgnoreCase(opt) ) {
536                                                 debugLevel = Integer.parseInt( arguments.get(0) );
537                                         }
538                                         return true;
539                                 }
540                         }
541                 };
542                 return new HashSet<>(Arrays.asList(options));
543         }
544 }