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