    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}