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 018import jdk.javadoc.doclet.DocletEnvironment ; 019// import jdk.javadoc.doclet.Doclet ; 020// import jdk.javadoc.doclet.Reporter ; 021// import javax.lang.model.element.Element ; 022import javax.lang.model.element.Modifier ; 023import javax.lang.model.element.TypeElement; 024// import javax.lang.model.element.ElementKind ; 025import javax.lang.model.element.VariableElement; 026// import javax.lang.model.SourceVersion ; 027import javax.lang.model.util.ElementFilter ; 028// import javax.lang.model.util.Elements ; 029import javax.tools.Diagnostic.Kind ; 030import com.sun.source.doctree.DocCommentTree ; 031import com.sun.source.util.DocTrees ; 032import com.sun.source.doctree.DocTree ; 033 034// import java.util.Locale ; 035import java.util.Set; 036import java.util.List; 037import java.util.HashSet; 038import java.util.Arrays; 039import java.util.Map; 040 041// import java.io.IOException; 042// import java.io.File; 043// import java.io.PrintWriter; 044 045// import org.opengion.fukurou.util.FileUtil; 046// import org.opengion.fukurou.util.StringUtil; 047 048/** 049 * ソースコメントから、パラメータ情報を取り出す Doclet クラスです。 050 * og.paramLevel タグと og.cryptography タグを切り出します。 051 * これらは、システムパラメータとしてGE12テーブルに設定される値をクラスより抽出する 052 * のに使用します。 053 * 054 * @version 7.3 055 * @author Kazuhiko Hasegawa 056 * @since JDK11.0, 057 */ 058public class DocTreeParam extends AbstractDocTree { 059 private static final String OG_PARAM_LVL = "og.paramLevel"; 060 private static final String OG_CRYPTOGRAPHY = "og.cryptography"; 061 062 private static final int CNST = 1000; 063 064 private String systemId = "**" ; 065 private String outfile; 066 067// private DocTrees docUtil; 068 069 /** 070 * デフォルトコンストラクター 071 * 072 * @og.rev 7.3.0.0 (2021/01/06) PMD refactoring. Each class should declare at least one constructor. 073 */ 074 public DocTreeParam() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 075 076 /** 077 * Doclet のエントリポイントメソッドです(昔の startメソッド)。 078 * 079 * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応 080 * 081 * @param docEnv ドックレットを1回呼び出す操作環境 082 * 083 * @return 正常実行時 true 084 */ 085 @Override 086 public boolean run( final DocletEnvironment docEnv ) { 087 try( DocTreeWriter writer = new DocTreeWriter( outfile,ENCODE ) ) { 088 writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE , "\" ?>" ); 089 writer.printTag( "<javadoc>" ); 090 writer.printTag( " <systemId>" , systemId , "</systemId>" ); 091 writeContents( docEnv,writer ); 092 writer.printTag( "</javadoc>" ); 093 } 094 catch( final Throwable th ) { 095 reporter.print(Kind.ERROR, th.getMessage()); 096 } 097 098 return true; 099 } 100 101 /** 102 * DocletEnvironmentよりコンテンツを作成します。 103 * 104 * @og.rev 7.3.0.0 (2021/01/06) 新しいJavaDoc対応 105 * @og.rev 8.0.1.0 (2021/10/29) titleを改行か『。』までの文字列を切り出す。 106 * 107 * @param docEnv ドックレットの最上位 108 * @param writer DocTreeWriterオブジェクト 109 */ 110 private void writeContents( final DocletEnvironment docEnv, final DocTreeWriter writer ) { 111 // get the DocTrees utility class to access document comments 112// docUtil = docEnv.getDocTrees(); 113 final DocTrees docUtil = docEnv.getDocTrees(); 114// final Elements eleUtil = docEnv.getElementUtils(); 115 116 // クラス単位にループする。 117 for( final TypeElement typEle : ElementFilter.typesIn(docEnv.getIncludedElements())) { 118 int cnt = 0; 119 final String fullName = String.valueOf( typEle.getQualifiedName() ) ; 120// final String fullName = String.valueOf(typEle); 121// System.out.println(typEle.getKind() + ":" + fullName); 122 writer.setClassName( fullName ); 123 124 // フィールドのみフィルタリングして取得する 125 for( final VariableElement varEle : ElementFilter.fieldsIn(typEle.getEnclosedElements())) { // フィールドだけに絞る 126 if( varEle.getModifiers().contains( Modifier.PUBLIC )) { // public だけに絞る 127 final DocCommentTree docTree = docUtil.getDocCommentTree(varEle); // ドキュメンテーション・コメントが見つからない場合、null が返る。 128 129 final String paramId = String.valueOf(varEle); 130 final String seq = String.valueOf(cnt*10 + CNST); 131 // final List<? extends DocTree> title = docTree == null ? EMPTY_LIST : docTree.getFirstSentence(); 132 // final List<? extends DocTree> cmnt = docTree == null ? EMPTY_LIST : docTree.getFullBody(); 133 final String[] cmnts = getTitleCmnt( docTree ); // 8.0.1.0 (2021/10/29) 134 135 final String param = String.valueOf( varEle.getConstantValue() ); 136 137 final Map<String,List<String>> blkTagMap = blockTagsMap(docTree); 138 final String paramLvl = getBlockTag( OG_PARAM_LVL , blkTagMap, "" ).split(":")[0]; // 取得した値を ':' で分割した最初の文字列。 139 final String fgcrypt = getBlockTag( OG_CRYPTOGRAPHY, blkTagMap, "" ).split(":")[0]; 140 141// String paramLvl = ""; 142// String fgcrypt = ""; 143// if( docTree != null ) { 144// for( final DocTree dt : docTree.getBlockTags() ) { 145// final String tag = String.valueOf(dt); 146// if( tag.contains( OG_PARAM_LVL ) ) { 147// paramLvl = cut( tag,' ',':' ); 148// } 149// else if( tag.contains( OG_CRYPTOGRAPHY ) ) { 150// fgcrypt = cut( tag,' ',':' ); 151// } 152// } 153// } 154 155 writer.printTag( " <fieldDoc>" ); 156 writer.printTag( " <paramId>" ,paramId ,"</paramId>" ); 157 writer.printTag( " <seq>" ,seq ,"</seq>" ); 158 writer.printTag( " <param>" ,param ,"</param>" ); 159// writer.printTag( " <title>" ,title ,"</title>" ); 160 writer.printTag( " <title>" ,cmnts[0] ,"</title>" ); // 8.0.1.0 (2021/10/29) 161// writer.printTag( " <contents>" ,cmnt ,"</contents>" ); 162 writer.printTag( " <contents>" ,cmnts[1] ,"</contents>" ); // 8.0.1.0 (2021/10/29) 163 writer.printTag( " <paramLevel>" ,paramLvl ,"</paramLevel>" ); 164 writer.printTag( " <fgcrypt>" ,fgcrypt ,"</fgcrypt>" ); 165 writer.printTag( " </fieldDoc>" ); 166 167 cnt++; 168 } 169 } 170 } 171 } 172 173 /** 174 * DocTreeリストから、最初の1文(改行か『。』まで)と本文の文字列を切り出します。 175 * 176 * title が、docTree.getFirstSentence(); でうまく取れていないようです。 177 * docTree.getFullBody() で取ってきた最初の1文と、残りの本文を切り出します。 178 * 179 * @og.rev 8.0.1.0 (2021/10/29) titleを改行か『。』までの文字列を切り出す。 180 * 181 * @param docTree DocCommentTreeオブジェクト 182 * @return 最初の1文(改行か『。』まで)と本文の文字列を分割した配列 183 */ 184 private String[] getTitleCmnt( final DocCommentTree docTree ) { 185 final String[] rtns = { "","" }; // 初期値 186 187 if( docTree == null ) { return rtns; } 188 final List<? extends DocTree> doc = docTree.getFullBody(); 189 190 if( doc.isEmpty() ) { return rtns; } 191 192 final String body = String.valueOf( doc.get(0) ); 193 int st = body.indexOf( '。' ); 194 if( st < 0 ) { 195 st = body.indexOf( '\n' ); 196 } 197 198 if( st >= 0 ) { 199 rtns[0] = body.substring( 0,st ).trim(); // 一応、スペースは削除する。 200 rtns[1] = body.substring( st ).trim(); // 201 } 202 else { 203 rtns[1] = body.trim(); 204 } 205 206 return rtns ; 207 } 208 209 /** 210 * サポートされているすべてのオプションを返します。 211 * 212 * @return サポートされているすべてのオプションを含むセット、存在しない場合は空のセット 213 */ 214 @Override 215 public Set<? extends Option> getSupportedOptions() { 216 final Option[] options = { 217 new AbstractOption( "-outfile", "-systemId" ) { 218 219 /** 220 * 必要に応じてオプションと引数を処理します。 221 * 222 * @param opt オプション名 223 * @param arguments 引数をカプセル化したリスト 224 * @return 操作が成功した場合はtrue、そうでない場合はfalse 225 */ 226 @Override 227 public boolean process(final String opt, final List<String> arguments) { 228 if( "-outfile".equalsIgnoreCase(opt) ) { 229 outfile = arguments.get(0); 230 } 231 else if( "-systemId".equalsIgnoreCase(opt) ) { 232 systemId = arguments.get(0); 233 } 234 return true; 235 } 236 } 237 }; 238 return new HashSet<>(Arrays.asList(options)); 239 } 240}