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 */
016 package org.opengion.fukurou.taglet;
017
018 import org.opengion.fukurou.util.LogWriter;
019
020 import java.util.Set;
021 import java.util.HashSet;
022 import java.io.IOException;
023 import java.lang.reflect.Field;
024
025 import com.sun.javadoc.RootDoc;
026 import com.sun.javadoc.ClassDoc;
027 import com.sun.javadoc.MethodDoc;
028 import com.sun.javadoc.FieldDoc;
029 import com.sun.javadoc.Doc;
030 import com.sun.javadoc.ConstructorDoc;
031 import com.sun.javadoc.ExecutableMemberDoc;
032 import com.sun.javadoc.Type;
033 import com.sun.javadoc.Parameter;
034 import com.sun.javadoc.Tag;
035 import com.sun.javadoc.SourcePosition;
036 import com.sun.javadoc.AnnotationDesc;
037 import com.sun.javadoc.AnnotationTypeDoc;
038
039 /**
040 * ソースコメントからã?タグæƒ??を取りå?ã�?Doclet クラスですã?
041 * クラスファイルの仕様を表現する為、og.formSample , og.rev , og.group ,
042 * version , author , since のå�?‚¿グコメントよりå?を抽出しますã?
043 * またã?å�?‚¯ラスの継承関係ã?インターフェース、メソãƒ?ƒ‰なども抽出しますã?
044 * これらã?抽出結果をDB化し、EXCELファイルに帳票出力する事で、クラスファイルの
045 * ソースから仕様書をé?作æ?しますã?
046 *
047 * @version 4.0
048 * @author Kazuhiko Hasegawa
049 * @since JDK5.0,
050 */
051 public final class DocletSpecific {
052 private static final String SELECT_PACKAGE = "org.opengion" ;
053 private static final boolean NOT_PRIVATE = false ;
054 private static final String ENCODE = "UTF-8";
055
056 private static final String OG_FOR_SMPL = "og.formSample";
057 private static final String OG_REV = "og.rev";
058 private static final String OG_GROUP = "og.group";
059 private static final String DOC_VERSION = "version";
060 private static final String DOC_AUTHOR = "author";
061 private static final String DOC_SINCE = "since";
062
063 private static final String DOC_PARAM = "param"; // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
064 private static final String DOC_RETURN = "return"; // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
065
066 private static final String CONSTRUCTOR = "コンストラクタ" ;
067 private static final String METHOD = "メソãƒ?ƒ‰" ;
068 private static final Set<String> methodSet = new HashSet<String>();
069
070 private static int debugLevel = 0; // 0:なã�? 1:æœ?°�チェãƒ?‚¯ 2:日本語化 3:体è£?
071
072 /**
073 * すべてã�?staticメソãƒ?ƒ‰なので、コンストラクタを呼び出さなくしておきますã?
074 *
075 */
076 private DocletSpecific() {}
077
078 /**
079 * Doclet のエントリポイントメソãƒ?ƒ‰ですã?
080 *
081 * @og.rev 5.5.4.1 (2012/07/06) Tag出力時の CR â†?BR 変換を行わなã�?§˜にするã€?
082 *
083 * @param root エントリポイントã?RootDocオブジェクãƒ?
084 *
085 * @return 正常実行時 true
086 */
087 public static boolean start( final RootDoc root ) {
088 String version = DocletUtil.getOption( "-version" , root.options() );
089 String file = DocletUtil.getOption( "-outfile" , root.options() );
090 String dbgLvl = DocletUtil.getOption( "-debugLevel" , root.options() ); // 5.5.4.1 (2012/07/06) パラメータ引数
091 if( dbgLvl != null ) { debugLevel = Integer.parseInt( dbgLvl ); }
092
093 DocletTagWriter writer = null;
094 try {
095 // writer = new DocletTagWriter( file,ENCODE,true );
096 writer = new DocletTagWriter( file,ENCODE ); // 5.5.4.1 (2012/07/06)
097
098 writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE, "\" ?>" );
099 writer.printTag( "<javadoc>" );
100 writer.printTag( " <version>",version,"</version>" );
101 writer.printTag( " <description></description>" );
102 writeContents( root.classes(),writer );
103 writer.printTag( "</javadoc>" );
104 }
105 catch( IOException ex ) {
106 LogWriter.log( ex );
107 }
108 finally {
109 if( writer != null ) { writer.close(); }
110 }
111 return true;
112 }
113
114 /**
115 * ClassDoc 配å?よりコンãƒ?ƒ³ãƒ?‚’作æ?しますã?
116 *
117 * @og.rev 5.5.4.1 (2012/07/06) コメントã?æ–?—å?でなくã?Tag配å?として処ç�?�•せるã€?
118 * @og.rev 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメントã?比è¼?ƒ�ェãƒ?‚¯
119 *
120 * @param classes ClassDoc配å?
121 * @param writer Tagを書きå?すWriterオブジェクãƒ?
122 */
123 private static void writeContents( final ClassDoc[] classes,final DocletTagWriter writer ) {
124 for(int i=0; i< classes.length; i++) {
125 ClassDoc classDoc = classes[i] ;
126 String className = classDoc.name();
127 String fullName = classDoc.qualifiedName() ;
128 String modifiers = (classDoc.modifiers()
129 + ( classDoc.isClass() ? " class" : "" ) ).trim();
130
131 Type superType = classDoc.superclassType();
132 String superClass = ( superType == null ) ? "" : superType.qualifiedTypeName();
133
134 Type[] interfaceTypes = classDoc.interfaceTypes();
135 StringBuilder buf = new StringBuilder( 200 );
136 for( int j=0; j<interfaceTypes.length; j++ ) {
137 buf.append( interfaceTypes[j].qualifiedTypeName() ).append( "," );
138 }
139 if( interfaceTypes.length > 0 ) { buf.deleteCharAt( buf.length()-1 ); }
140 String intFase = buf.toString();
141
142 Tag[] desc = classDoc.firstSentenceTags();
143 // String cmnt = DocletUtil.htmlFilter( classDoc.commentText() ); // 5.5.4.1 (2012/07/06)
144 Tag[] cmnt = classDoc.inlineTags(); // 5.5.4.1 (2012/07/06)
145 Tag[] smplTags = classDoc.tags(OG_FOR_SMPL);
146 Tag[] revTags = classDoc.tags(OG_REV);
147 Tag[] createVer = classDoc.tags(DOC_VERSION);
148 Tag[] author = classDoc.tags(DOC_AUTHOR);
149 Tag[] since = classDoc.tags(DOC_SINCE);
150 Tag[] grpTags = classDoc.tags(OG_GROUP);
151
152 writer.printTag( "<classDoc>" );
153 writer.printTag( " <fullName>" ,fullName ,"</fullName>" );
154 writer.printTag( " <modifiers>" ,modifiers ,"</modifiers>" );
155 writer.printTag( " <className>" ,className ,"</className>" );
156 writer.printTag( " <superClass>" ,superClass ,"</superClass>" );
157 writer.printTag( " <interface>" ,intFase ,"</interface>" );
158 writer.printTag( " <createVer>" ,createVer ,"</createVer>" );
159 writer.printTag( " <author>" ,author ,"</author>" );
160 writer.printTag( " <since>" ,since ,"</since>" );
161 writer.printTag( " <description>" ,desc ,"</description>" );
162 writer.printTag( " <contents>" ,cmnt ,"</contents>" );
163 writer.printTag( " <classGroup>" );
164 writer.printCSVTag( grpTags );
165 writer.printTag( "</classGroup>" );
166 writer.printTag( " <formSample>" ,smplTags ,"</formSample>" );
167 writer.printTag( " <history>" ,revTags ,"</history>" );
168
169 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用(コメントや概要が無ã�??合ã?スーパã?クラスは省く)
170 // if( ( cmnt.length() == 0 || desc.length == 0 ) && superClass.length() == 0 ) {
171 if( debugLevel >= 2 && ( cmnt.length == 0 || desc.length == 0 ) && superClass.length() == 0 ) {
172 System.err.println( "警å‘?:コメンãƒ?=\t" + classDoc.position() );
173 }
174
175 // methodSet.clear(); // 5.5.4.1 (2012/07/06) メソãƒ?ƒ‰の重è¤??ç�?ˆ¤定ã?、クラス名も含めて行うので、clear() しなã�??
176 int extendFlag = 0; // 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend
177 // while( fullName.startsWith( SELECT_PACKAGE ) ) {
178
179 // 5.6.6.0 (2013/07/05) VERSION staticフィールドと、@og.rev コメントã?比è¼?ƒ�ェãƒ?‚¯
180 // while 以下で、fullName と classDoc をé?番に上にさかのぼってã�?‚‹ので、å?にチェãƒ?‚¯しますã?
181 checkTag2( fullName,classDoc );
182
183 while( true ) {
184 // ConstructorDoc[] cnstrctrs = classDoc.constructors();
185 ConstructorDoc[] cnstrctrs = classDoc.constructors( false ); // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
186 for(int j=0; j < cnstrctrs.length; j++) {
187 if( isAction( cnstrctrs[j],extendFlag ) ) {
188 if( extendFlag < 2 ) { checkTag( cnstrctrs[j] ); } // 5.5.4.1 (2012/07/06) チェãƒ?‚¯をå?離
189 menberTag( cnstrctrs[j],CONSTRUCTOR,writer,extendFlag );
190 }
191 }
192
193 // MethodDoc[] methods = classDoc.methods();
194 MethodDoc[] methods = classDoc.methods( false ); // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
195 for(int j=0; j < methods.length; j++) {
196 if( isAction( methods[j],extendFlag ) ) {
197 if( extendFlag < 2 ) { checkTag( methods[j] ); } // 5.5.4.1 (2012/07/06) チェãƒ?‚¯をå?離
198 menberTag( methods[j],METHOD,writer,extendFlag );
199 }
200 }
201
202 // 対象クラス(オリジナル)から、上に上がってã�?��ã€?
203 Type type = classDoc.superclassType();
204 if( type == null ) { break; }
205 classDoc = type.asClassDoc() ;
206 fullName = classDoc.qualifiedName();
207 // java.lang.Object クラスは対象が多いため、å?ç�?�—ませんã€?
208 if( "java.lang.Object".equals( fullName ) || classDoc.isEnum() ) {
209 break;
210 }
211 else if( fullName.startsWith( SELECT_PACKAGE ) ) {
212 extendFlag = 1;
213 }
214 else {
215 extendFlag = 2;
216 }
217 }
218
219 writer.printTag( " </classDoc>" );
220 }
221 }
222
223 /**
224 * メンバã?クラスのXML化を行うかどã�?�‹[true/false]を判定しますã?
225 *
226 * 以下ã?条件に合è?する場合ã?、å?ç�?‚’行いませんã€?false を返しますã?)
227 *
228 * ?‘.同ä¸?‚¯ラスをå?ç�?¸にEXTENDで継承å…?‚’さかのぼるå?合ã?すでに同じシグネチャのメソãƒ?ƒ‰ã�?
229 * 存在してã�?‚‹ã€?
230 * ?’.NOT_PRIVATE ã�?true の時ã? private メソãƒ?ƒ‰
231 * ?“.extendFlag ã�?0以ä¸?1,2)の時ã? private メソãƒ?ƒ‰
232 * ?”.メソãƒ?ƒ‰名におかしな記号(<など)が含まれてã�?‚‹場å�?
233 *
234 * @og.rev 5.5.4.1 (2012/07/06) メソãƒ?ƒ‰の重è¤??ç�?ˆ¤定ã?、クラス名も含めて行う
235 *
236 * @param menber ExecutableMemberDocオブジェクãƒ?
237 * @param extendFlag 0:オリジナル 1:org.opengion関連Extend 2:Java関連Extend
238 *
239 * @return XML化を行うかどã�?�‹[true/false]
240 */
241 private static boolean isAction( final ExecutableMemberDoc menber,final int extendFlag ) {
242 String menberName = menber.name() ;
243 // String signature = menberName + menber.signature();
244 // boolean rtn = ( ! methodSet.add( signature ) )
245 boolean rtn = ( ! methodSet.add( menber.toString() ) ) // 5.5.4.1 (2012/07/06) メソãƒ?ƒ‰の重è¤??ç�?ˆ¤定ã?、クラス名も含めて行う
246 || ( NOT_PRIVATE && menber.isPrivate() )
247 || ( extendFlag > 0 && menber.isPrivate() )
248 || ( menberName.charAt(0) == '<' ) ;
249
250 return ! rtn ;
251 }
252
253 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用(半角文字+空白æ–?—ã?み)
254 private static java.util.regex.Pattern PTN = java.util.regex.Pattern.compile("[\\w\\s]+");
255
256 /**
257 * param,return 等ã?整合æ?をチェãƒ?‚¯しますã?
258 *
259 * @og.rev 5.5.4.1 (2012/07/06) 新規作æ?ã€?
260 * @og.rev 5.6.6.1 (2013/07/12) Deprecated アノテーション のチェãƒ?‚¯
261 *
262 * @param menber ExecutableMemberDocオブジェクãƒ?
263 */
264 private static void checkTag( final ExecutableMemberDoc menber ) {
265
266 // 親ã�?Enum クラスの場合ã?処ç�?�—ませんã€?
267 Type prntType = menber.containingClass().superclassType();
268 String prntClass = ( prntType == null ) ? "" : prntType.qualifiedTypeName();
269 if( "java.lang.Enum".equals( prntClass ) ) { return; }
270
271 SourcePosition posi = menber.position();
272 String modifiers = null;
273
274 if( menber instanceof MethodDoc ) {
275 // メソãƒ?ƒ‰の処ç�?コンストラクターを省ã�?
276 Type rtnType = ((MethodDoc)menber).returnType();
277 String typNm = rtnType.typeName();
278
279 StringBuilder modifyBuf = new StringBuilder( 200 );
280 modifyBuf.append( menber.modifiers() ).append( " " ).append( typNm );
281 if( rtnType.dimension() != null ) { modifyBuf.append( rtnType.dimension() ); }
282 modifiers = modifyBuf.toString();
283
284 String wormMsg = "=\t" + posi + "\t" + modifiers ;
285
286 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用(@return との整合æ?チェãƒ?‚¯)
287 Tag[] docReturn = menber.tags(DOC_RETURN); // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
288 if( docReturn.length > 0 ) {
289 String data = (docReturn[0].text()).trim(); // 5.5.4.1 (2012/07/06) trim でスペã?ス等ã?削除
290 wormMsg = wormMsg + "\t" + data ;
291
292 // 5.5.4.1 (2012/07/06) ソースチェãƒ?‚¯用(@return と引数の個数が異なるå?å�?
293 if( debugLevel >= 1 && "void".equals( typNm ) ) {
294 System.err.println( "警å‘?:RTNコメント不è¦? + wormMsg );
295 }
296 // ?¢@return 解説?£ の形式で、解説に日本語がなければ、警å‘?
297 // if( debugLevel >= 2 && PTN.matcher( data ).matches() && data.indexOf( ' ' ) < 0 && data.indexOf( '\t' ) < 0 ) {
298 if( debugLevel >= 2 && PTN.matcher( data ).matches() ) {
299 System.err.println( "警å‘?:RTN未解説" + wormMsg );
300 }
301 // ?¢@return String?£ の形式ã?場合ã?警å‘?
302 if( debugLevel >= 2 && data.equals( typNm ) ) {
303 System.err.println( "警å‘?:RTNä¸??" + wormMsg );
304 }
305 // ?¢@return String[]?£ などã€??列やã€?String>などが含まれる場合ã?警å‘?
306 if( debugLevel >= 2 && ( data.indexOf( "[]" ) >= 0 || data.indexOf( '<' ) >= 0 ) ) {
307 System.err.println( "警å‘?:RTN配å?" + wormMsg );
308 }
309 // ?¢@return String 解説?£ の場合ã?警å‘?後ろにスペã?スかã?タブがある場å�?
310 if( debugLevel >= 3 && (data.indexOf( typNm + " " ) >= 0 || data.indexOf( typNm + "\t" ) >= 0 ) ) {
311 System.err.println( "警å‘?:RTNタイãƒ? + wormMsg );
312 }
313 // ?¢@return xxxx 解説?£ の場合で、最初ã?スペã?スまでがã?すべて英数字ã?みの場合ã?警å‘?
314 int adrs1 = data.indexOf( ' ' );
315 if( debugLevel >= 3 && adrs1 > 0 ) {
316 boolean flag = true;
317 for( int j=0; j<adrs1; j++ ) {
318 char ch = data.charAt( j );
319 if( ( ch < '0' || ch > '9' ) && ( ch < 'a' || ch > 'z' ) && ( ch < 'A' || ch > 'Z' ) && ch != '[' && ch != ']' ) {
320 flag = false; // 英数字でなã�?¨˜号が現れた場å�?
321 break;
322 }
323 }
324 if( flag ) { // すべてが英数字ã?場合ã?ã€?
325 System.err.println( "警å‘?:RTN値" + wormMsg );
326 }
327 }
328 }
329 else { // Tag上には、@return 記述が存在しなã�??
330 // 5.5.4.1 (2012/07/06) ソースチェãƒ?‚¯用(@return と引数の個数が異なるå?å�?
331 if( debugLevel >= 1 && !"void".equals( typNm ) ) {
332 System.err.println( "警å‘?:RTNコメントなã�? + wormMsg );
333 }
334 }
335
336 // オーバã?ライドチェãƒ?‚¯?šアノテーションの記述漏れ
337 // そã?é€??、コンパイラが警告してくれるã?
338 MethodDoc mdoc= ((MethodDoc)menber).overriddenMethod();
339 if( debugLevel >= 3 && mdoc != null ) {
340 AnnotationDesc[] annotations = menber.annotations();
341 // 本来は、Override の有無を調べるべきだがã?Deprecated と SuppressWarnings の付いてã�?‚‹
342 // 旧のメソãƒ?ƒ‰に、いちã�?�¡Overrideを付けなã�??で、何もなければと条件を緩めますã?
343 if( annotations.length == 0 ) {
344 System.err.println( "警å‘?:@Overrideなã�? + wormMsg );
345 }
346 }
347 }
348
349 Parameter[] prm = menber.parameters();
350
351 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用(@param と引数の個数が異なるå?å�?
352 Tag[] docParam = menber.tags(DOC_PARAM); // 5.1.9.0 (2010/08/01) チェãƒ?‚¯用
353 if( debugLevel >= 1 && docParam.length != prm.length ) {
354 System.err.println( "警å‘?:PRM個数違い=\t" + posi );
355 }
356
357 for( int k=0; k<prm.length; k++ ) {
358 String typNm = prm[k].type().typeName();
359 String prmNm = prm[k].name();
360
361 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用(@param と引数の個数が異なるå?å�?
362 if( docParam.length > k ) {
363 String data = (docParam[k].text()).trim(); // 5.5.4.1 (2012/07/06) trim でスペã?ス等ã?削除
364 String data2 = data.replaceAll( prmNm,"" ).trim();
365 String data3 = data2.replaceAll( typNm,"" ).replaceAll( "\\[\\]","" ).trim();
366 String wormMsg = "=\t" + posi + "\t" + data ;
367
368 // ?¢@param aaa 解説?£形式で、aaa(引数å�?がなã�??å�?
369 if( debugLevel >= 1 && data.indexOf( prmNm ) < 0 ) {
370 System.err.println( "警å‘?:PRM引数å�? + wormMsg );
371 }
372 // 引数のæ–?—å?の長さがã€?¼‘文字ã?場å�?
373 if( debugLevel >= 2 && prmNm.length() == 1 ) {
374 System.err.println( "警å‘?:PRM短ã�? + wormMsg );
375 }
376 // ?¢@param aaa 解説?£形式で、解説に日本語がなã�??またã?、解説がなければ、警å‘?
377 // if( debugLevel >= 2 && PTN.matcher( data ).matches() && data.indexOf( ' ' ) < 0 && data.indexOf( '\t' ) < 0 ) {
378 if( debugLevel >= 2 && ( PTN.matcher( data2 ).matches() || data3.length() == 0 ) ) {
379 System.err.println( "警å‘?:PRM未解説" + wormMsg );
380 }
381 // ?¢@param aaa String[]?£などã€??列やã€?String>などが含まれる場合ã?警å‘?
382 if( debugLevel >= 2 && ( data.indexOf( "[]" ) >= 0 || data.indexOf( '<' ) >= 0 ) ) {
383 System.err.println( "警å‘?:PRM配å?" + wormMsg );
384 }
385 // ?¢@param aaa 解説?£形式で、String が有って、その後ろにスペã?スかã?タブがあれば警å‘?
386 // data2 を使ã�??は、パラメータå�?xxxMap)にタイプ名(Map)が含まれてã�?‚‹ケースの対å¿?
387 if( debugLevel >= 3 && (data2.indexOf( typNm + " " ) >= 0 || data2.indexOf( typNm + "\t" ) >= 0 ) ) {
388 System.err.println( "警å‘?:PRMタイãƒ? + wormMsg );
389 }
390 // ?¢@param aaa 解説?£形式で、解説がなã�??å�?
391 // if( debugLevel >= 3 && data3.length() == 0 ) {
392 // System.err.println( "警å‘?:PRM解説なã�? + wormMsg );
393 // }
394 }
395 }
396
397 Tag[] desc = menber.firstSentenceTags();
398 Tag[] cmnt = menber.inlineTags(); // 5.5.4.1 (2012/07/06)
399 // String extClass = ( extendFlag == 0 ) ? "" : menber.containingClass().qualifiedName() ;
400
401 // 5.1.9.0 (2010/08/01) ソースチェãƒ?‚¯用
402 if( ( cmnt.length == 0 || desc.length == 0 ) // コメントや概要が無ã�?
403 // && extClass.length() == 0 // 拡張クラスが存在しなã�?
404 && ( menber instanceof MethodDoc ) // メソãƒ?ƒ‰に限å®?
405 && !menber.isSynthetic() // コンパイラによって合æ?されてã�?�ªã�?
406 && !menber.isNative() // ネイãƒ?‚£ブメソãƒ?ƒ‰でなã�?
407 && debugLevel >= 2 ) { // debugLevel ã�?2 以ä¸?
408
409 // さらに、親ã�?Enum クラス以å¤?
410 // Type prntType = menber.containingClass().superclassType();
411 // String prntClass = ( prntType == null ) ? "" : prntType.qualifiedTypeName();
412 // if( debugLevel >= 2 && !"java.lang.Enum".equals( prntClass ) ) {
413 System.err.println( "警å‘?:コメンãƒ?=" + "\t" + posi + "\t" + menber.name() );
414 // }
415 }
416
417 // 5.6.6.1 (2013/07/12) Deprecated アノテーション のチェãƒ?‚¯
418 AnnotationDesc[] descList = menber.annotations();
419 for( int i=0; i<descList.length; i++ ) {
420 AnnotationTypeDoc annDoc = descList[i].annotationType();
421 if( "Deprecated".equalsIgnoreCase( annDoc.name() ) ) {
422 String text = menber.commentText();
423 if( text != null && text.indexOf( "【å»?¢ã€? ) < 0 ) {
424 System.err.println( "警å‘?:【å»?¢ã€?" + "\t" + posi + "\t" + menber.name() );
425 }
426 }
427 }
428 }
429
430 /**
431 * VERSION staticフィールドと、@og.rev コメントã?比è¼?ƒ�ェãƒ?‚¯を行いますã?
432 *
433 * @og.rev 5.6.6.0 (2013/07/05) 新規作æ?
434 *
435 * @param fullName オリジナルのクラスå�?
436 * @param classDoc ClassDocオブジェクãƒ?
437 */
438 private static void checkTag2( final String fullName, final ClassDoc classDoc ) {
439 String cnstVar = getFieldVERSION( fullName ) ; // VERSION æ–?—å? ä¾?5.6.6.0 (2013/07/05)
440 String seriUID = getSerialVersionUID( fullName ) ; // serialVersionUID ä¾?566020130705L
441
442 // VERSION æ–?—å? かã?serialVersionUID のどちらかがあれã?処ç�?�—ますã?
443 if( cnstVar != null || seriUID != null ) {
444 SourcePosition posi = null;
445
446 String maxRev = ( cnstVar != null ) ? cnstVar : "4.0.0.0 (2005/01/31)" ; // Ver4 のæœ?‚‚古ã�?‰ˆ
447 int lenVar = maxRev.length(); // 比è¼?™‚に使用する長ã�?
448 boolean isChange = false; // max がå?れ替わったら、true
449
450 // 本体ã?コンストラクタ、フィールドã?メソãƒ?ƒ‰å†?�‹らã?æœ?¤§の @og.rev の値を取得しますã?
451 Doc[][] docs = new Doc[4][] ;
452
453 docs[0] = new Doc[] { classDoc } ;
454 docs[1] = classDoc.constructors( false ) ;
455 docs[2] = classDoc.fields( false ) ;
456 docs[3] = classDoc.methods( false ) ;
457
458 for( int i=0; i<docs.length; i++ ) {
459 for( int j=0; j < docs[i].length; j++ ) {
460 Doc doc = docs[i][j];
461
462 Tag[] revTags = doc.tags(OG_REV);
463 for( int k=0 ; k<revTags.length; k++ ) {
464 String rev = revTags[k].text();
465
466 if( rev.length() < lenVar ) {
467 System.err.println( "警å‘?:og.revが短ã�?" + "\t" + rev + "\t" + doc.position() );
468 continue;
469 }
470
471 rev = rev.substring( 0,lenVar );
472 if( maxRev.compareTo( rev ) < 0 ) { // revTags の og.rev が大きい場å�?
473 maxRev = rev ;
474 posi = doc.position(); // æœ?¾Œに入れ替わった位置 = æœ?¤§のrevの位置
475 isChange = true;
476 }
477 }
478 }
479 }
480
481 // VERSION æ–?—å? の定義がありã?かつ、max の入れ替えが発生したå?合ã?み、警å‘?:VERSIONが古ã�?
482 if( cnstVar != null && isChange ) {
483 System.err.println( "警å‘?:VERSIONが古ã�?" + "\t" + cnstVar + " â‡?" + maxRev + "\t" + posi );
484 }
485
486 // serialVersionUID の定義があるã?
487 if( seriUID != null ) {
488 StringBuilder buf = new StringBuilder();
489 // maxRev は、最大の Revかã?初期のVERSIONæ–?—å? ä¾?5.6.6.0 (2013/07/05)
490 for( int i=0; i<maxRev.length(); i++ ) { //
491 char ch = maxRev.charAt( i );
492 if( ch >= '0' && ch <= '9' ) { buf.append( ch ); } // 数字だけ取りå?すã? ä¾?566020130705
493 }
494 if( !seriUID.equals( buf.toString() ) ) {
495 // 以下ã?処ç�??、serialVersionUID のソースの位置(posi)を取りå?すためだけに使用してã�?�¾すã?
496 FieldDoc[] fileds = classDoc.fields( false );
497 for( int i=0; i<fileds.length; i++ ) {
498 FieldDoc filed = fileds[i];
499 // private static final long serialVersionUID で宣è¨?�•れてã�?‚‹のでã€?
500 if( filed.isPrivate() && filed.isStatic() && filed.isFinal() ) {
501 String nm = filed.qualifiedName();
502 if( nm.endsWith( "serialVersionUID" ) ) {
503 // String val = filed.constantValueExpression(); // これは、serialVersionUID の設定å?の取得サンプル
504 posi = filed.position();
505 }
506 }
507 }
508 System.err.println( "警å‘?:serialVersionUIDが古ã�?" + "\t" + seriUID + " â‡?" + buf.toString() + "L\t" + posi );
509 }
510 }
511 }
512 }
513
514 /**
515 * メンバã?クラス(コンストラクタ、メソãƒ?ƒ‰)をXML化しますã?
516 *
517 * @og.rev 5.5.4.1 (2012/07/06) コメントã?æ–?—å?でなくã?Tag配å?として処ç�?�•せるã€?
518 *
519 * @param menber ExecutableMemberDocオブジェクãƒ?
520 * @param menberType メンバã?タイãƒ?コンストラクタ、メソãƒ?ƒ‰)
521 * @param writer Tagを書きå?すWriterオブジェクãƒ?
522 * @param extendFlag 0:オリジナル 1::org.opengion関連Extend 2:Java関連Extend
523 */
524 private static void menberTag( final ExecutableMemberDoc menber,
525 final String menberType,
526 final DocletTagWriter writer,
527 final int extendFlag ) {
528
529 final String modifiers ;
530 if( menber instanceof MethodDoc ) {
531 // メソãƒ?ƒ‰の処ç�?
532 Type rtnType = ((MethodDoc)menber).returnType();
533 StringBuilder modifyBuf = new StringBuilder( 200 );
534 modifyBuf.append( menber.modifiers() );
535 // modifyBuf.append( " " ).append( rtnType.qualifiedTypeName() );
536 modifyBuf.append( " " ).append( rtnType.typeName() );
537 if( rtnType.dimension() != null ) { modifyBuf.append( rtnType.dimension() ); }
538
539 modifiers = modifyBuf.toString();
540 }
541 else {
542 // コンストラクター処ç�?
543 modifiers = menber.modifiers();
544 }
545
546 String menberName = menber.name();
547
548 StringBuilder sigBuf = new StringBuilder( 200 );
549 sigBuf.append( menberName ).append( "(" ) ;
550 Parameter[] prm = menber.parameters();
551
552 for( int k=0; k<prm.length; k++ ) {
553 // sigBuf.append( prm[k].toString() ).append( "," );
554 Type ptyp = prm[k].type();
555 String prmNm =prm[k].name();
556
557 sigBuf.append( ptyp.typeName() ).append( ptyp.dimension() ).append( " " )
558 .append( prmNm ).append( "," );
559 }
560
561 if( prm.length > 0 ) { sigBuf.deleteCharAt( sigBuf.length()-1 ); }
562 sigBuf.append( ")" );
563 String signature = sigBuf.toString();
564
565 Tag[] desc = menber.firstSentenceTags();
566 // String cmnt = DocletUtil.htmlFilter( menber.commentText() ); // 5.5.4.1 (2012/07/06)
567 Tag[] cmnt = menber.inlineTags(); // 5.5.4.1 (2012/07/06)
568 Tag[] tags = menber.tags();
569 Tag[] revTags = menber.tags(OG_REV);
570 String extend = String.valueOf( extendFlag );
571 String extClass = ( extendFlag == 0 ) ? "" : menber.containingClass().qualifiedName() ;
572
573 String position = String.valueOf( menber.position().line() );
574
575 writer.printTag( " <menber>" );
576 writer.printTag( " <type>" ,menberType ,"</type>" );
577 writer.printTag( " <name>" ,menberName ,"</name>" );
578 writer.printTag( " <modifiers>" ,modifiers ,"</modifiers>" );
579 writer.printTag( " <signature>" ,signature ,"</signature>" );
580 writer.printTag( " <position>" ,position ,"</position>" );
581 writer.printTag( " <extendClass>",extClass ,"</extendClass>" );
582 writer.printTag( " <extendFlag>" ,extend ,"</extendFlag>" );
583 writer.printTag( " <description>",desc ,"</description>" );
584 writer.printTag( " <contents>" ,cmnt ,"</contents>" );
585 writer.printTag( " <tagText>" );
586 writer.printTagsInfo( tags );
587 writer.printTag( " </tagText>" );
588 writer.printTag( " <history>" ,revTags ,"</history>" );
589 writer.printTag( " </menber>");
590 }
591
592 /**
593 * æŒ?®šã?オブジェクトã? VERSION と、serialVersionUID staticフィールドã?値を取得しますã?
594 *
595 * 結果は、文字å?配å?にして返しますã?
596 * どちらもなければ、null, どちらかあれば、文字å?配å?にして、ä¸?�¤目は、VERSION。2つめã?、serialVersionUID ã‚?
597 * æ–?—å?にした値を返しますã?
598 *
599 * こã?メソãƒ?ƒ‰のオリジナルは、org.opengion.hayabusa.servlet.HybsAdmin の private å†?ƒ¨クラス ClassInfo にありますã?
600 * 汎用性がなã�?‚º、ソースのコピã????ーストで持ってきてã�?�¾すã??ˆ若干、修正もしてã�?�¾すï¼?
601 *
602 * @og.rev 5.6.6.0 (2013/07/05) 新規作æ?
603 *
604 * @param clsName æŒ?®šã?クラスを表す名称
605 * @return VERSIONæ–?—å?( staticフィールドã?値 ) と、serialVersionUIDを文字å?にした値を含ã‚??åˆ?
606 */
607 private static String getFieldVERSION( final String clsName ) {
608 String rtn ;
609 try {
610 Class<?> cls = Class.forName( clsName ) ;
611 Field fld = cls.getDeclaredField( "VERSION" ) ;
612 // privateフィールドã?取得には、accessibleフラグã‚?trueにするå¿?¦�がありますã?
613 fld.setAccessible( true );
614 rtn = (String)fld.get( null );
615 }
616 catch( Throwable ex ) {
617 rtn = null;
618 }
619 return rtn ;
620 }
621
622 /**
623 * æŒ?®šã?オブジェクトã? VERSION と、serialVersionUID staticフィールドã?値を取得しますã?
624 *
625 * 結果は、文字å?配å?にして返しますã?
626 * どちらもなければ、null, どちらかあれば、文字å?配å?にして、ä¸?�¤目は、VERSION。2つめã?、serialVersionUID ã‚?
627 * æ–?—å?にした値を返しますã?
628 *
629 * こã?メソãƒ?ƒ‰のオリジナルは、org.opengion.hayabusa.servlet.HybsAdmin の private å†?ƒ¨クラス ClassInfo にありますã?
630 * 汎用性がなã�?‚º、ソースのコピã????ーストで持ってきてã�?�¾すã??ˆ若干、修正もしてã�?�¾すï¼?
631 *
632 * @og.rev 5.6.6.0 (2013/07/05) 新規作æ?
633 *
634 * @param clsName æŒ?®šã?クラスを表す名称
635 * @return VERSIONæ–?—å?( staticフィールドã?値 ) と、serialVersionUIDを文字å?にした値を含ã‚??åˆ?
636 */
637 private static String getSerialVersionUID( final String clsName ) {
638 String rtn ;
639 try {
640 Class<?> cls = Class.forName( clsName );
641 Field fld = cls.getDeclaredField( "serialVersionUID" ) ;
642 // privateフィールドã?取得には、accessibleフラグã‚?trueにするå¿?¦�がありますã?
643 fld.setAccessible( true );
644 rtn = String.valueOf( (Long)fld.get( null ) );
645 }
646 catch( Throwable ex ) {
647 rtn = null;
648 }
649 return rtn ;
650 }
651
652 /**
653 * カスタãƒ?‚ªプションを使用するドックレãƒ?ƒˆのå¿??メソãƒ?ƒ‰ optionLength(String) ですã?
654 *
655 * ドックレãƒ?ƒˆに認識させるå�?‚«スタãƒ?‚ªプションにã€?optionLength がその
656 * オプションを構æ?する要ç´?(トã?クン) の数を返さなければなりませんã€?
657 * こã?カスタãƒ?‚ªプションではã€?-tag オプションそã?もã?と
658 * そã?値の 2 つの要ç´?�§構æ?されるã?で、作æ?するドックレãƒ?ƒˆの
659 * optionLengthメソãƒ?ƒ‰はã€?-tag オプションに対して 2 を返さなくては
660 * なりません。またã?認識できなã�?‚ªプションに対してはã€? を返しますã?
661 *
662 * @param option オプションæ–?—å?
663 *
664 * @return 要ç´?トã?クン) の数
665 */
666 public static int optionLength( final String option ) {
667 if(option.equalsIgnoreCase("-version")) {
668 return 2;
669 }
670 else if(option.equalsIgnoreCase("-outfile")) {
671 return 2;
672 }
673 else if(option.equalsIgnoreCase("-debugLevel")) {
674 return 2;
675 }
676 return 0;
677 }
678 }