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             * ?”.メソãƒ?ƒ‰名におかしな記号(&lt;など)が含まれてã�?‚‹場å�?
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    }