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 */
016package org.opengion.fukurou.taglet;
017
018import org.opengion.fukurou.util.LogWriter;
019
020import com.sun.javadoc.RootDoc;
021import com.sun.javadoc.ClassDoc;
022import com.sun.javadoc.Type;
023import com.sun.javadoc.Tag;
024import java.util.Map;
025import java.util.HashMap;
026import java.io.IOException;
027
028/**
029 * ソースコメントから、属性情報を取り出す Doclet クラスです。
030 *
031 * @version  4.0
032 * @author   Kazuhiko Hasegawa
033 * @since    JDK5.0,
034 */
035public final class DocletPlugin {
036        private static Map<String,AttKeySet> map = new HashMap<String,AttKeySet>();
037
038        private static final String OG_FOR_SMPL  = "og.formSample";
039        private static final String ENCODE = "UTF-8";
040
041        /**
042         * すべてが staticメソッドなので、コンストラクタを呼び出さなくしておきます。
043         *
044         */
045        private DocletPlugin() {}
046
047        /**
048         * Doclet のエントリポイントメソッドです。
049         *
050         * @og.rev 5.7.1.1 (2013/12/13) タグのインデントを止める。
051         *
052         * @param root ドキュメントルートオブジェクト
053         *
054         * @return 正常実行時 true
055         */
056        public static boolean start( final RootDoc root ) {
057                String version = DocletUtil.getOption( "-version" , root.options() );
058                String file    = DocletUtil.getOption( "-outfile" , root.options() );
059
060                mapInit();
061
062                DocletTagWriter writer = null;
063                try {
064                        writer = new DocletTagWriter( file,ENCODE );
065
066                        // 5.7.1.1 (2013/12/13) タグのインデントを止める。
067                        writer.printTag( "<?xml version=\"1.0\" encoding=\"", ENCODE, "\" ?>" );
068                        writer.printTag( "<javadoc>" );
069                        writer.printTag(   "<version>",version,"</version>" );
070                        writer.printTag(   "<description></description>" );
071                        writeContents( root.classes(),writer );
072                        writer.printTag( "</javadoc>" );
073                }
074                catch( IOException ex ) {
075                        LogWriter.log( ex );
076                }
077                finally {
078                        if( writer != null ) { writer.close(); }
079                }
080                return true;
081        }
082
083        /**
084         * ClassDoc 配列よりコンテンツを作成します。
085         * インターフェースも処理の対象とします。
086         *
087         * @og.rev 5.5.4.1 (2012/07/06) コメントは文字列でなく、Tag配列として処理させる。
088         * @og.rev 5.7.1.1 (2013/12/13) タグのインデントを止める。
089         *
090         * @param classes       ClassDoc配列
091         * @param writer        DocletTagWriterオブジェクト
092         */
093        private static void writeContents( final ClassDoc[] classes,final DocletTagWriter writer ) {
094                for(int i=0; i< classes.length; i++) {
095                        ClassDoc classDoc      = classes[i] ;
096                        if( ! classDoc.isPublic() ) { continue; }
097
098                        AttKeySet attSet = getAttGroupName( classDoc ) ;
099
100                        if( attSet == null ) { continue; }              // map に登録されていない。
101
102                        String attKey   = attSet.getAttKey( classDoc.name() );
103
104                        if( attKey == null ) { continue; }              // 対象クラス名が、一致しない。
105
106                        String attClass = classDoc.qualifiedName() ;    // Class Full Name
107                        Tag[]  desc     = classDoc.firstSentenceTags();
108//                      String cmnt     = DocletUtil.htmlFilter( classDoc.commentText() );                      // 5.5.4.1 (2012/07/06)
109                        Tag[]  cmnt     = classDoc.inlineTags();                                                                        // 5.5.4.1 (2012/07/06)
110                        Tag[] smplTags  = classDoc.tags(OG_FOR_SMPL);
111
112                        // 5.7.1.1 (2013/12/13) タグのインデントを止める。
113                        writer.printTag( "<classDoc>" );
114                        writer.printTag(   "<attClass>"           ,attClass                               ,"</attClass>"            );
115                        writer.printTag(   "<seq>"                        ,attSet.getSeq()                ,"</seq>"                 );
116                        writer.printTag(   "<attKey>"             ,attKey                                 ,"</attKey>"              );
117                        writer.printTag(   "<valueName>"  ,attSet.getValueName()  ,"</valueName>"           );
118                        writer.printTag(   "<description>"        ,desc                                   ,"</description>" );
119                        writer.printTag(   "<contents>"           ,cmnt                                   ,"</contents>"            );
120                        writer.printTag(   "<formSample>" ,smplTags                               ,"</formSample>"  );
121                        writer.printTag( "</classDoc>" );
122                }
123        }
124
125        /**
126         * 処理する属性クラスのMapを初期化します。
127         * 指定できるのは、親クラスか、直接のインターフェースです。
128         *
129         * @og.rev 4.3.5.0 (2008/02/01) daemonパッケージ追加
130         * @og.rev 5.5.3.5 (2012/06/21) ChartWriter 削除、TransferExec,TransferRead 追加
131         * @og.rev 5.6.3.3 (2013/04/19) DBTableReport,CalendarData,DBConstValue,JspParserFilter,ConnectIF 追加
132         *
133         */
134        private static void mapInit() {
135                map.put( "org.opengion.hayabusa.db.Query"                               , new AttKeySet( "Query"                        ,0, "queryType"         ));
136                map.put( "org.opengion.hayabusa.db.CellRenderer"                , new AttKeySet( "Renderer"                     ,1, "renderer"          ));
137                map.put( "org.opengion.hayabusa.db.CellEditor"                  , new AttKeySet( "Editor"                       ,2, "editor"            ));
138                map.put( "org.opengion.hayabusa.db.DBType"                              , new AttKeySet( "DBType"                       ,3, "dbType"            ));
139                map.put( "org.opengion.hayabusa.db.TableFilter"                 , new AttKeySet( "TableFilter"          ,4, "tableFilter"       ));
140                map.put( "org.opengion.hayabusa.db.Selection"                   , new AttKeySet( "Selection"            ,5, "selection"         ));
141                map.put( "org.opengion.hayabusa.html.ViewForm"                  , new AttKeySet( "ViewForm"                     ,6, "viewFormType"      ));
142                map.put( "org.opengion.hayabusa.io.TableWriter"                 , new AttKeySet( "TableWriter"          ,7, "writerClass"       ));
143                map.put( "org.opengion.hayabusa.io.TableReader"                 , new AttKeySet( "TableReader"          ,8, "readerClass"       ));
144//              map.put( "org.opengion.hayabusa.io.ChartWriter"                 , new AttKeySet( "ChartWriter"          ,9, "chartClass"        ));             // 5.5.3.5 (2012/06/21)
145                map.put( "org.opengion.hayabusa.resource.CalendarQuery" , new AttKeySet( "CalendarQuery"        ,10, "calDB"            ));
146                map.put( "org.opengion.fukurou.process.HybsProcess"             , new AttKeySet( "Process"                      ,11, "process"          ));
147                map.put( "org.opengion.fukurou.transfer.TransferExec"   , new AttKeySet( "TransferExec"         ,12, "kbExec"           ));             // 5.5.3.5 (2012/06/21)
148                map.put( "org.opengion.fukurou.transfer.TransferRead"   , new AttKeySet( "TransferRead"         ,13, "kbRead"           ));             // 5.5.3.5 (2012/06/21)
149                map.put( "org.opengion.fukurou.util.HybsTimerTask"              , new AttKeySet( "Daemon"                       ,14, "daemon"           ));             // 4.3.4.4 (2009/01/01)
150
151                map.put( "org.opengion.hayabusa.report.DBTableReport"   , new AttKeySet( "DBTableReport"        ,15, "tableReport"      ));             // 5.6.3.3 (2013/04/19)
152                map.put( "org.opengion.hayabusa.resource.CalendarData"  , new AttKeySet( "CalendarData"         ,16, "calData"          ));             // 5.6.3.3 (2013/04/19)
153                map.put( "org.opengion.hayabusa.db.DBConstValue"                , new AttKeySet( "DBConstValue"         ,17, "cnstVal"          ));             // 5.6.3.3 (2013/04/19)
154                map.put( "org.opengion.fukurou.xml.JspParserFilter"             , new AttKeySet( "JspCreate"            ,18, "jspParser"        ));             // 5.6.3.3 (2013/04/19)
155                map.put( "org.opengion.fukurou.util.ConnectIF   "               , new AttKeySet( "ConnectIF"            ,19, "connIF"           ));             // 5.6.3.3 (2013/04/19)
156        }
157
158        /**
159         * 指定の ClassDoc が、処理する属性クラスのMapに含まれている場合、
160         * その AttKeySet クラスのオブジェクトを返します。
161         * 存在しない場合、null を返します。
162         *
163         * @param       classDoc ClassDocオブジェクト
164         *
165         * @return      ClassDocに対応する AttKeySetオブジェクト
166         */
167        private static AttKeySet getAttGroupName( final ClassDoc classDoc ) {
168                if( classDoc == null ) { return null; }
169
170                String classFullName = classDoc.qualifiedName() ;
171                AttKeySet attKey = map.get( classFullName );
172                if( attKey == null ) {
173                        Type type = classDoc.superclassType();  // 親クラスタイプ
174                        if( type != null ) {
175                                attKey = getAttGroupName( type.asClassDoc() );  // 親クラス
176                        }
177
178                        if( attKey == null ) {
179                                Type[] itface = classDoc.interfaceTypes();              // 直近インターフェース
180                                for( int i=0; i<itface.length; i++ ) {
181                                        attKey = getAttGroupName( itface[i].asClassDoc() );
182                                        if( attKey != null ) { break; }
183                                }
184                        }
185                }
186                return attKey;
187        }
188
189        /**
190         * カスタムオプションを使用するドックレットの必須メソッド optionLength(String) です。
191         *
192         * ドックレットに認識させる各カスタムオプションに、 optionLength がその
193         * オプションを構成する要素 (トークン) の数を返さなければなりません。
194         * このカスタムオプションでは、 -tag オプションそのものと
195         * その値の 2 つの要素で構成されるので、作成するドックレットの
196         * optionLengthメソッドは、 -tag オプションに対して 2 を返さなくては
197         * なりません。また、認識できないオプションに対しては、0 を返します。
198         *
199         * @param option オプション文字列
200         *
201         * @return 要素 (トークン) の数
202         */
203        public static int optionLength( final String option ) {
204                if(option.equalsIgnoreCase("-version")) {
205                        return 2;
206                }
207                else if(option.equalsIgnoreCase("-outfile")) {
208                        return 2;
209                }
210                return 0;
211        }
212}