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 }