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    }