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    import org.opengion.fukurou.util.StringUtil;
020    
021    import com.sun.javadoc.RootDoc;
022    import com.sun.javadoc.ClassDoc;
023    import com.sun.javadoc.MethodDoc;
024    import com.sun.javadoc.Type;
025    import com.sun.javadoc.Tag;
026    import java.util.Map;
027    import java.util.HashMap;
028    import java.io.IOException;
029    
030    /**
031     * ソースコメントから?タグ??を取り??Doclet クラスです?
032     * こ? Doclet は?:org.opengion.hayabusa.taglib" のみ対象として処?ます?
033     * og.formSample , og.tag , og.group タグを?り?します?
034     *
035     * @version  4.0
036     * @author   Kazuhiko Hasegawa
037     * @since    JDK5.0,
038     */
039    public final class DocletTaglib {
040            private static Map<String,String> map = new HashMap<String,String>();
041    
042            private static final String OG_FOR_SMPL = "og.formSample";
043            private static final String OG_TAG_NAME = "og.tag";
044            private static final String OG_GROUP    = "og.group";
045    
046            private static final String OG_TAG_CLASS = "org.opengion.hayabusa.taglib";
047            private static final String ENCODE = "UTF-8";
048    
049            /**
050             * すべて?staticメソ?なので、コンストラクタを呼び出さなくしておきます?
051             *
052             */
053            private DocletTaglib() {}
054    
055            /**
056             * Doclet のエントリポイントメソ?です?
057             *
058             * @og.rev 5.7.1.1 (2013/12/13) タグのイン?トを止める?
059             *
060             * @param       root    エントリポイント?RootDocオブジェク?
061             *
062             * @return      正常実行時 true
063             */
064            public static boolean start( final RootDoc root ) {
065                    String version = DocletUtil.getOption( "-version" , root.options() );
066                    String file    = DocletUtil.getOption( "-outfile" , root.options() );
067    
068                    DocletTagWriter writer = null;
069                    try {
070                            writer = new DocletTagWriter( file,ENCODE );
071    
072                            // 5.7.1.1 (2013/12/13) タグのイン?トを止める?
073                            writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE, "\" ?>" );
074                            writer.printTag( "<javadoc>" );
075                            writer.printTag(   "<version>",version,"</version>" );
076                            writer.printTag(   "<description></description>" );
077                            writeContents( root.classes(),writer );
078                            writer.printTag( "</javadoc>" );
079                    }
080                    catch( IOException ex ) {
081                            LogWriter.log( ex );
082                    }
083                    finally {
084                            if( writer != null ) { writer.close(); }
085                    }
086                    return true;
087            }
088    
089            /**
090             * ClassDoc 配?よりコン??作?します?
091             *
092             * @og.rev 5.5.4.1 (2012/07/06) コメント???でなく?Tag配?として処?せる?
093             * @og.rev 5.6.6.1 (2013/07/12) og.group を?tagGroup として独立させる?
094             * @og.rev 5.7.1.1 (2013/12/13) cmnt と tags の間に改行をセ?
095             * @og.rev 5.7.1.1 (2013/12/13) タグのイン?トを止める?
096             *
097             * @param classes       ClassDoc配?
098             * @param writer        DocletTagWriterオブジェク?
099             */
100            private static void writeContents( final ClassDoc[] classes,final DocletTagWriter writer ) {
101                    for(int i=0; i< classes.length; i++) {
102                            ClassDoc classDoc      = classes[i] ;
103                            String   classFullName = classDoc.qualifiedName() ;
104    
105                            if( ! classDoc.isPublic() ||
106                                    classFullName.indexOf( OG_TAG_CLASS ) < 0 ) { continue; }
107    
108                            Tag[]  desc = classDoc.firstSentenceTags();
109    //                      String cmnt = DocletUtil.htmlFilter( classDoc.commentText() );                  // 5.5.4.1 (2012/07/06)
110                            Tag[]  cmnt = classDoc.inlineTags();                                                                    // 5.5.4.1 (2012/07/06)
111                            Tag[] smplTags  = classDoc.tags(OG_FOR_SMPL);
112                            Tag[] grpTags   = classDoc.tags(OG_GROUP);
113    
114                            // 5.7.1.1 (2013/12/13) タグのイン?トを止める?
115                            writer.printTag( "<classDoc>" );
116                            writer.printTag(   "<tagClass>"           ,classFullName  ,"</tagClass>" );
117                            // 5.6.6.1 (2013/07/12) og.group を?tagGroup として独立させる?
118                            writer.printTag(   "<tagGroup>"           ,makeGroupTag( grpTags )        ,"</tagGroup>" );
119                            writer.printTag(   "<description>"        ,desc                                           ,"</description>" );
120    //                      writer.printTag(   "<description>" );
121    ////            writer.printTag(         makeGroupTag( grpTags )   );           // 5.6.6.1 (2013/07/12)
122    //                      writer.printTag(         desc      );
123    //                      writer.printTag( "</description>" );
124                            writer.printTag(   "<contents>"           ,cmnt                   ,"</contents>" );
125                            writer.printTag(   "<formSample>" ,smplTags               ,"</formSample>" );
126    
127                            map.clear();
128                            String className = classDoc.name();
129                            while(  ! "BodyTagSupport".equals( className ) &&
130                                            ! "TagSupport".equals( className ) ) {
131                                    String extendFlag = "false";
132                                    if( "HTMLTagSupport".equals( className ) ) {
133                                            extendFlag = "true" ;
134                                    }
135                                    MethodDoc[] methods = classDoc.methods();
136                                    for(int j=0; j < methods.length; j++) {
137                                            if( ! methods[j].isPublic() ) { continue; }
138                                            Tag[] tags = methods[j].tags(OG_TAG_NAME);
139                                            if(tags.length > 0) {
140                                                    String methodName = DocletUtil.removeSetter( methods[j].name() );
141                                                    if( map.containsKey( methodName ) ) { continue; }
142                                                    map.put( methodName,className );
143                                                    Tag[] ftag = methods[j].firstSentenceTags();
144    //                                              cmnt = DocletUtil.htmlFilter( methods[j].commentText() );               // 5.5.4.1 (2012/07/06)
145                                                    cmnt = methods[j].inlineTags();                                                                 // 5.5.4.1 (2012/07/06)
146    
147                            // 5.7.1.1 (2013/12/13) タグのイン?トを止める?
148                                                    writer.printTag(   "<method>" );
149                                                    writer.printTag(     "<name>"             ,methodName     ,"</name>" );
150                                                    writer.printTag(     "<htmlExtend>"       ,extendFlag     ,"</htmlExtend>" );
151                                                    writer.printTag(     "<description>",ftag         ,"</description>" );
152                                                    // 5.7.1.1 (2013/12/13) cmnt と tags の間に改行をセ?
153                                                    writer.printTag(     "<contents>" ,cmnt           ,"" );
154                                                    writer.printTag( ""                                     ,tags           ,"</contents>" );
155    //                                              writer.printTag( "    <contents>" );
156    //                                              writer.printTag(        cmnt );
157    //                                              writer.printTag(        tags );
158    //                                              writer.printTag( "    </contents>" );
159                                                    writer.printTag(   "</method>");
160                                            }
161                                    }
162                                    Type type = classDoc.superclassType();
163                                    if( type == null ) { break; }
164                                    classDoc  = type.asClassDoc() ;
165                                    className = classDoc.name();
166                            }
167                            writer.printTag( "  </classDoc>" );
168                    }
169            }
170    
171            /**
172             * タグ配?を受け取り?タグ出力します?
173             * ?のタグを?力する?合に、カンマ区??で連結します?
174             *
175             * @og.rev 5.5.4.1 (2012/07/06) DocletUtil.htmlFilter ?StringUtil.htmlFilter に変更
176             * @og.rev 5.6.6.1 (2013/07/12) og.group の表示方法を変更する?
177             *
178             * @param       tag タグ配?
179             *
180             * @return      タグ出力文字?
181             */
182            private static String makeGroupTag( final Tag[] tag ) {
183                    StringBuilder but = new StringBuilder( 200 );
184                    for( int i=0; i<tag.length; i++ ) {
185    //                      String data = DocletUtil.htmlFilter( tag[i].text() );
186                            String data = StringUtil.htmlFilter( tag[i].text() );           // 5.5.4.1 (2012/07/06) DocletUtil ?StringUtil に変更
187                            if( i > 0 ) { but.append( "," ); }
188    //                      but.append( data );
189                            but.append( "? ).append( data ).append( "? );                 // 5.6.6.1 (2013/07/12) og.group の表示方法を変更
190                    }
191                    return but.toString() ;                                                                                 // 5.6.6.1 (2013/07/12)
192    //              if( but.length() > 0 ) {
193    //                      return "? + but.toString() + "? ;
194    //              }
195    //              else {
196    //                      return "";
197    //              }
198            }
199    
200            /**
201             * カスタ?プションを使用するドックレ?の??メソ? optionLength(String) です?
202             *
203             * ドックレ?に認識させる?スタ?プションに?optionLength がその
204             * オプションを構?する要?(ト?クン) の数を返さなければなりません?
205             * こ?カスタ?プションでは?-tag オプションそ?も?と
206             * そ?値の 2 つの要?構?される?で、作?するドックレ?の
207             * optionLengthメソ?は?-tag オプションに対して 2 を返さなくては
208             * なりません。また?認識できな?プションに対しては? を返します?
209             *
210             * @param option カスタ?プションのキーワー?
211             *
212             * @return 要?(ト?クン) の数
213             */
214            public static int optionLength( final String option ) {
215                    if(option.equalsIgnoreCase("-version")) {
216                            return 2;
217                    }
218                    else if(option.equalsIgnoreCase("-outfile")) {
219                            return 2;
220                    }
221                    return 0;
222            }
223    }