    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.hayabusa.taglib;
    017
    018import org.opengion.hayabusa.common.HybsSystem;
    019import org.opengion.hayabusa.common.HybsSystemException;
    020import org.opengion.fukurou.util.XHTMLTag;
    021import org.opengion.fukurou.util.Attributes;
    022import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
    023import org.opengion.fukurou.util.ArraySet;                                              // 6.4.3.4 (2016/03/11)
    024
    025import static org.opengion.fukurou.util.StringUtil.nval ;
    026
    027import java.io.File;
    028import java.io.FileFilter;
    029import java.io.Serializable;
    030import java.util.Set;                                                                                   // 6.4.3.4 (2016/03/11)
    031import java.util.Arrays;
    032import java.util.Comparator;
    033
    034/**
    035 * ファイルのプルダウンリストの作成するタグです。
    036 *
    037 * SelectタグのBODY部に指定します。
    038 * 並び替えについては、このタグで指定しますが、ファイルの選別は、
    039 * BODY 部に記述する fileWhere タグで指定します。
    040 *
    041 * @og.formSample
    042 * ●形式：&lt;og:fileOption from="…" value="[…]" ･･･ &gt;･･･&lt;/og:fileOption&gt;
    043 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    044 *
    045 * ●Tag定義：
    046 *   &lt;og:fileOption
    047 *       from               【TAG】ファイルの検索元となるディレクトリを指定します (初期値:FILE_URL[=filetemp/])
    048 *       value              【TAG】Optionの初期値で選ばれる値を指定します
    049 *       useDir             【廃止】(廃止：7.2.6.0 (2020/06/30))optionリストの作成を、ディレクトリの値で行います。
    050 *       nameOnly           【TAG】ファイルの拡張子を除いた名前部分のみの値で行います。7.2.4.0 (2020/05/11)
    051 *       groupDir           【TAG】optgroupを、ディレクトリの値で作成します(１レベルのみ)。
    052 *       orderBy            【TAG】検索した結果を表示する表示順をファイル属性名で指定します(初期値:自然順序)
    053 *       desc               【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false)
    054 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 6.8.0.0 (2017/06/02)
    055 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 6.8.0.0 (2017/06/02)
    056 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 6.8.0.0 (2017/06/02)
    057 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 6.8.0.0 (2017/06/02)
    058 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 6.8.0.0 (2017/06/02)
    059 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    060 *   &gt;   ... Body ...
    061 *   &lt;/og:fileOption&gt;
    062 *
    063 * ●使用例
    064 *      ・&lt;og:fileOption val1="ABCD" val2="{&#064;value}" &gt;
    065 *            &lt;og:fileWhere startsWith="ABCD" ･･･ /&gt;
    066 *        &lt;/og:fileOption&gt;
    067 *
    068 * @og.rev 2.1.1.0 (2002/11/11) 新規作成
    069 * @og.rev 4.0.0.0 (2005/01/31) 内部ロジック改定
    070 * @og.group その他入力
    071 *
    072 * @version  4.0
    073 * @author   Kazuhiko Hasegawa
    074 * @since    JDK5.0,
    075 */
    076public class FileOptionTag extends CommonTagSupport {
    077        /** このプログラムのVERSION文字列を設定します。   {@value} */
    078        private static final String VERSION = "7.2.6.0 (2020/06/30)" ;
    079        private static final long serialVersionUID = 726020200630L ;
    080
    081        private String          orderBy         ;                               // ｿｰﾄ項目
    082//      private boolean         useDir          ;                               // 6.3.4.0 (2015/08/01) 7.2.6.0 (2020/06/30) useDIR 属性 廃止
    083        private boolean         nameOnly                ;                       // 7.2.4.0 (2020/05/11)
    084        private boolean         groupDir        ;                               // 6.3.4.0 (2015/08/01)
    085        private boolean         desc            ;                               // 降順ﾌﾗｸﾞ
    086        private String      from                = HybsSystem.sys( "FILE_URL" ); // 検索起点ﾌｧｲﾙ
    087        private String          selValue        ;                               // 選択済み初期値にする場合
    088        private transient       FileFilter      filter  ;               // FileWhere で指定したフィルター
    089
    090        // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
    091        private static final Set<String> ORDER_BY_SET = new ArraySet<>( "NAME","LASTMODIFIED","FILE_LENGTH","LENGTH" );
    092
    093        /**
    094         * デフォルトコンストラクター
    095         *
    096         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    097         */
    098        public FileOptionTag() { super(); }             // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    099
    100        /**
    101         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    102         *
    103         * @og.rev 6.8.0.0 (2017/06/02) caseKey,caseVal,caseNN,caseNull 属性を追加
    104         *
    105         * @return      後続処理の指示( EVAL_BODY_BUFFERED )
    106         */
    107        @Override
    108        public int doStartTag() {
    109                // 6.8.0.0 (2017/06/02) caseKey,caseVal,caseNN,caseNull 属性を追加
    110                return useTag() ? EVAL_BODY_BUFFERED : SKIP_BODY ;
    111        }
    112
    113        /**
    114         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    115         *
    116         * @return      後続処理の指示(SKIP_BODY)
    117         */
    118        @Override
    119        public int doAfterBody() {
    120                return SKIP_BODY ;
    121        }
    122
    123        /**
    124         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    125         *
    126         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    127         * @og.rev 6.3.4.0 (2015/08/01) useDir 属性と、groupDir 属性 を追加します。
    128         * @og.rev 6.8.0.0 (2017/06/02) caseKey,caseVal,caseNN,caseNull 属性を追加
    129         *
    130         * @return      後続処理の指示
    131         */
    132        @Override
    133        public int doEndTag() {
    134                debugPrint();           // 4.0.0 (2005/02/28)
    135                // 6.8.0.0 (2017/06/02) caseKey,caseVal,caseNN,caseNull 属性を追加
    136                if( useTag() ) {
    137                        final OptionAncestorIF select = (OptionAncestorIF)findAncestorWithClass( this, OptionAncestorIF.class );
    138                        if( select == null ) {
    139                                final String errMsg = "<b>" + getTagName() + "タグは、SelectTag または、DatalistTag のBODY に記述する必要があります。</b>";
    140                                throw new HybsSystemException( errMsg );
    141                        }
    142                        final Comparator<File> comp = makeComparator( orderBy,desc );
    143        //              makeLabel( select,comp );
    144                        makeLabel( new File( from ) , select , comp , groupDir );
    145                }
    146
    147                return EVAL_PAGE ;
    148        }
    149
    150        /**
    151         * タグリブオブジェクトをリリースします。
    152         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    153         *
    154         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    155         * @og.rev 6.3.4.0 (2015/08/01) useDir 属性と、groupDir 属性 を追加します。
    156         * @og.rev 7.2.4.0 (2020/05/11) nameOnly 属性 を追加します。
    157         * @og.rev 7.2.6.0 (2020/06/30) ディレクトリ処理を統一します。
    158         */
    159        @Override
    160        protected void release2() {
    161                super.release2();
    162                orderBy         = null;         // ｿｰﾄ項目
    163//              useDir          = false;        // 6.3.4.0 (2015/08/01) 7.2.6.0 (2020/06/30)
    164                nameOnly        = false;        // 7.2.4.0 (2020/05/11)
    165                groupDir        = false;        // 6.3.4.0 (2015/08/01)
    166                desc            = false;        // 降順ﾌﾗｸﾞ
    167                from            = HybsSystem.sys( "FILE_URL" );
    168                filter          = null;
    169                selValue        = null;
    170        }
    171
    172        /**
    173         * オプションを作成します。
    174         *
    175         * ファイル名を "value" に、
    176         * BODY属性 に登録するOptionを作成します。
    177         *
    178         * @og.rev 5.3.4.0 (2011/04/01) FILE_LENGTH 追加
    179         *
    180         * @param       orderBy ソートする属性 [NAME/LASTMODIFIED/FILE_LENGTH/LENGTH]
    181         * @param       desc    並び順 [true:昇順/false:降順]
    182         *
    183         * @return      ファイル比較用のComparatorオブジェクト
    184         */
    185        private Comparator<File> makeComparator( final String orderBy,final boolean desc ) {
    186                if( orderBy == null ) { return null; }
    187
    188                Comparator<File> comp = null ;
    189
    190                if( "NAME".equalsIgnoreCase( orderBy ) ) {
    191                        comp = new NameComparator( desc );
    192                }
    193                else if( "LASTMODIFIED".equalsIgnoreCase( orderBy ) ) {
    194                        comp = new ModifiedComparator( desc );
    195                }
    196                // "LENGTH" を残すのは、互換性のため
    197                else if( "FILE_LENGTH".equalsIgnoreCase( orderBy ) || "LENGTH".equalsIgnoreCase( orderBy ) ) {
    198                        comp = new LengthComparator( desc );
    199                }
    200
    201                return comp ;
    202        }
    203
    204        /**
    205         * オプションを作成します。
    206         *
    207         * ﾌｧｲﾙ名を "value" と、BODY属性 に登録するOptionを作成します。
    208         *
    209         * @og.rev 3.8.0.9 (2005/10/17) 複数選択可能時に全選択を設定する。
    210         * @og.rev 6.3.4.0 (2015/08/01) useDir 属性と、groupDir 属性 を追加します。
    211         * @og.rev 6.8.0.0 (2017/06/02) フォルダ内のファイルが無い場合は、階層に加えない。
    212         * @og.rev 7.2.4.0 (2020/05/11) nameOnly 属性 を追加します。
    213         *
    214         * @param       path    処理の開始パス名(ディレクトリ)
    215         * @param       select  SelectTagオブジェクト
    216         * @param       comp    並び順を指定するためのComparatorオブジェクト
    217         * @param       grpDir  フォルダ階層を、optgroup タグで表すかどうか [true:階層/false:１層]
    218         * @return      フォルダ内のファイルが無い場合は階層に加えないためのﾌﾗｸﾞ [true:階層/false:ファイルなし]
    219         */
    220        private boolean makeLabel( final File path , final OptionAncestorIF select , final Comparator<File> comp , final boolean grpDir ) {
    221
    222                final File[] list = path.listFiles( filter );
    223
    224                final boolean multipleAll = select.isMultipleAll();             // 3.8.0.9 (2005/10/17)
    225                if( list != null )  {
    226                        Arrays.sort( list, comp );
    227                        boolean isSet = false;                                                          // 6.8.0.0 (2017/06/02)
    228                        for( int i=0; i<list.length; i++ ) {
    229//                              final String value = list[i].getName();
    230                                String value = list[i].getName();                               // 7.2.4.0 (2020/05/11) 書き換える
    231                                // 6.3.4.0 (2015/08/01) useDir 属性と、groupDir 属性 を追加
    232                                if( grpDir && list[i].isDirectory() ) {
    233                                        select.addOption( "<optgroup label=\"" + value + "\">" );
    234                                        if( makeLabel( list[i] , select , comp , false ) ) {    // ﾘｽﾄに追加されたかどうかを判定します。
    235                                                select.addOption( "</optgroup>" );
    236                                                isSet = true;                                                           // 6.8.0.0 (2017/06/02)
    237                                        }
    238                                        else {
    239                                                select.removeLast();                                            // 6.8.0.0 (2017/06/02) ﾘｽﾄに追加されなかった場合は、最後に追加した optgroup を削除します。
    240                                        }
    241
    242                                        continue;
    243                                }
    244//                              // 7.2.6.0 (2020/06/30) useDIR 属性 廃止
    245//                              else {
    246//                                      // ディレクトリ時のuseDir=true と、ﾌｧｲﾙ時useDir=false でない場合( XOR )時は、処理しない。
    247//                                      if( list[i].isDirectory() ^ useDir ) { continue; }
    248//                              }
    249
    250                                // 7.2.4.0 (2020/05/11) nameOnly 属性 を追加します。
    251                                if( nameOnly ) {
    252                                        final int ad = value.lastIndexOf( '.' );
    253                                        if( ad >= 0 ) { value = value.substring( 0,ad ); }
    254                                }
    255
    256                                // 6.1.1.0 (2015/01/17) Attributesの連結記述
    257                                final String selected = ( selValue != null && selValue.equalsIgnoreCase( value ) ) || multipleAll
    258                                                                                        ? "selected" : null ;
    259
    260                                select.addOption(
    261                                        XHTMLTag.option(
    262                                                new Attributes()
    263                                                        .set( "value"   , value )
    264                                                        .set( "selected", selected )
    265                                                        .set( "body"    , value )
    266                                        )
    267                                );
    268                        }
    269                        return isSet;   // 6.8.0.0 (2017/06/02)
    270                }
    271                return false;           // 6.8.0.0 (2017/06/02) フォルダ内のファイルが無い場合は、階層に加えない。
    272        }
    273
    274        /**
    275         * 【TAG】Optionの初期値で選ばれる値を指定します。
    276         *
    277         * @og.tag
    278         * キーになるのは、ファイル属性の NAME です。(ディレクトリなしのファイル名)
    279         * ここで value属性に指定した場合、このファイル名と(大文字小文字を無視して)
    280         * 一致する場合に、プルダウンの初期値に表示されます。(selected 属性が設定される。)
    281         *
    282         * @param   val  初期値で選ばれる値
    283         */
    284        public void setValue( final String val ) {
    285                selValue = nval( getRequestParameter( val ),selValue );
    286        }
    287
    288        /**
    289         * 【廃止】optionリストの作成を、ディレクトリの値で行います(初期値:false)。
    290         *
    291         * @og.tag
    292         * ファイル検索で、ディレクトリ名のリストで、オプションを作成します。
    293         * 初期値は、false (ファイル名でリスト) です。
    294         *
    295         * @og.rev 6.3.4.0 (2015/08/01) useDir 属性の追加
    296         * @og.rev 7.2.6.0 (2020/06/30) ディレクトリ処理を統一します。
    297         *
    298         * @param       flag ディレクトリ名のリストで、オプションを作成するかどうか [true:ディレクトリ/false:ファイル]
    299         */
    300        public void setUseDir( final String flag ) {
    301//              useDir = nval( getRequestParameter( flag ),useDir );
    302        }
    303
    304        /**
    305         * 【TAG】ファイルの拡張子を除いた名前部分のみの値で行います(初期値:false)。
    306         *
    307         * @og.tag
    308         * ファイル検索の値を、ファイルの拡張子を取り除いた値のみで、オプションを作成します。
    309         * 初期値は、false (拡張子付きファイル名でリスト) です。
    310         *
    311         * @og.rev 7.2.4.0 (2020/05/11) nameOnly 属性 を追加します。
    312         *
    313         * @param       flag ファイルの拡張子を除いた名前部分のみで、オプションを作成するかどうか [true:名前部分のみ/false:ファイル名]
    314         */
    315        public void setNameOnly( final String flag ) {
    316                nameOnly = nval( getRequestParameter( flag ),nameOnly );
    317        }
    318
    319        /**
    320         * 【TAG】optgroupを、ディレクトリの値で作成します(１レベルのみ)(初期値:false)。
    321         *
    322         * @og.tag
    323         * optgroupをディレクトリで作成することで、階層のメニューを作成します。
    324         * 初期値は、false(通常) です。
    325         *
    326         * @og.rev 6.3.4.0 (2015/08/01) groupDir 属性の追加
    327         *
    328         * @param       flag ディレクトリで階層メニューを作成するかどうか [true:階層/false:通常]
    329         */
    330        public void setGroupDir( final String flag ) {
    331                groupDir = nval( getRequestParameter( flag ),groupDir );
    332        }
    333
    334        /**
    335         * 【TAG】ファイルの検索元となるディレクトリを指定します
    336         *              (初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。
    337         *
    338         * @og.tag ファイルの検索元となるディレクトリを指定します。
    339         * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。
    340         *
    341         * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
    342         * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。
    343         * @og.rev 6.4.2.1 (2016/02/05) HybsSystem.url2dir に引数追加。
    344         *
    345         * @param       url ファイルの検索元となるディレクトリ
    346         * @see         org.opengion.hayabusa.common.SystemData#FILE_URL
    347         */
    348        public void setFrom( final String url ) {
    349                final String furl = nval( getRequestParameter( url ),null );
    350                from = HybsSystem.url2dir( from,furl,"." );                     // 6.4.2.1 (2016/02/05)
    351        }
    352
    353        /**
    354         * 【TAG】検索した結果を表示する表示順をファイル属性名[null/NAME/LASTMODIFIED/FILE_LENGTH]で指定します(初期値:自然順序)。
    355         *
    356         * @og.tag
    357         * ファイルをソートする順(Comparator)を指定します。ソートに指定できる
    358         * ファイル属性名は、"NAME","LASTMODIFIED","FILE_LENGTH" の内のどれかひとつです。
    359         * 何も指定しない場合は、Fileオブジェクトの自然順序でのソートになります。
    360         * (※ 下位互換性のため、LENGTH も残しますが、廃止予定です。)
    361         *
    362         * @og.rev 3.5.6.2 (2004/07/05) 文字列の連結にStringBuilderを使用します。
    363         * @og.rev 4.0.0.0 (2005/01/31) 新規ロジックで改定
    364         * @og.rev 5.3.4.0 (2011/04/01) ORDER_BYリストの出力方法 見直し
    365         * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。
    366         * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
    367         *
    368         * @param       ordr  ソートキー [null/NAME/LASTMODIFIED/FILE_LENGTH]
    369         */
    370        public void setOrderBy( final String ordr ) {
    371                orderBy = nval( getRequestParameter( ordr ),orderBy );
    372
    373                if( orderBy != null && ! check( orderBy, ORDER_BY_SET ) ) {
    374                        final String errMsg = "orderBy 属性に、下記の属性名以外の値が設定されました。" + CR
    375                                                        + "orderBy=[" + orderBy + "] "                                                          + CR
    376                                                        + "orderBy List=" + String.join( ", " , ORDER_BY_SET ) ;
    377                        throw new HybsSystemException( errMsg );
    378                }
    379        }
    380
    381        /**
    382         * 【TAG】表示順を逆転するかどうか[true/false]を指定します(初期値:false)。
    383         *
    384         * @og.tag
    385         * orderBy 属性で指定した表示順を、逆順にするかどうかを指定できます。
    386         * 初期値は、false (昇順) です。
    387         *
    388         * @param       flag 表示順を逆転するかどうか [true:逆順/false:昇順]
    389         */
    390        public void setDesc( final String flag ) {
    391                desc = nval( getRequestParameter( flag ),desc );
    392        }
    393
    394        /**
    395         * FileFilterオブジェクトをセットします。
    396         * これは、BODY 部に登録した、FileWhereタグによって設定された
    397         * ファイルフィルターです。
    398         *
    399         * @param       filter  オブジェクト
    400         */
    401        protected void setFileFilter( final FileFilter filter ) {
    402                this.filter = filter;
    403        }
    404
    405        /**
    406         * 名前順でのソート順を指定する Comparator の実体内部クラス
    407         *
    408         * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private static final class に変更。
    409         *
    410         * @version  4.0
    411         * @author   Kazuhiko Hasegawa
    412         * @since    JDK5.0,
    413         */
    414        private static final class NameComparator implements Comparator<File>,Serializable {
    415                private static final long serialVersionUID = 400020050131L ;    // 4.0.0.0 (2005/01/31)
    416
    417                private final boolean desc ;
    418
    419                /**
    420                 * 名前順での比較を行うオブジェクトを作成します。
    421                 *
    422                 * @param desc 表示順逆転 [true:昇順/false:降順]
    423                 */
    424                public NameComparator( final boolean desc ) { this.desc = desc; }
    425
    426                /**
    427                 * Comparator インターフェースの compare( File,File ) メソッド。
    428                 *
    429                 * @param o1 比較元１のファイルオブジェクト
    430                 * @param o2 比較元２のファイルオブジェクト
    431                 * @return      最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
    432                 */
    433                public int compare( final File o1, final File o2 ) {
    434                        final File f1 = desc ? o2 : o1 ;
    435                        final File f2 = desc ? o1 : o2 ;
    436                        return f1.getName().compareTo( f2.getName() ) ;
    437                }
    438        }
    439
    440        /**
    441         * 更新日順でのソート順を指定する Comparator の実体内部クラス
    442         *
    443         * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private static final class に変更。
    444         *
    445         * @version  4.0
    446         * @author   Kazuhiko Hasegawa
    447         * @since    JDK5.0,
    448         */
    449        private static final class ModifiedComparator implements Comparator<File>,Serializable {
    450                private static final long serialVersionUID = 400020050131L ;    // 4.0.0.0 (2005/01/31)
    451
    452                private final boolean desc ;
    453
    454                /**
    455                 * 更新日順での比較を行うオブジェクトを作成します。
    456                 *
    457                 * @param desc 表示順逆順 [true:昇順/false:降順]
    458                 */
    459                public ModifiedComparator( final boolean desc ) { this.desc = desc; }
    460
    461                /**
    462                 * Comparator インターフェースの compare( File,File ) メソッド。
    463                 *
    464                 * @param o1 比較元１のファイルオブジェクト
    465                 * @param o2 比較元２のファイルオブジェクト
    466                 * @return      最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
    467                 */
    468                public int compare( final File o1, final File o2 ) {
    469                        final File f1 = desc ? o2 : o1 ;
    470                        final File f2 = desc ? o1 : o2 ;
    471                        return (int)( f1.lastModified() - f2.lastModified() ) ;
    472                }
    473        }
    474
    475        /**
    476         * ファイルサイズ順でのソート順を指定する Comparator の実体内部クラス
    477         *
    478         * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private static final class に変更。
    479         *
    480         * @version  4.0
    481         * @author   Kazuhiko Hasegawa
    482         * @since    JDK5.0,
    483         */
    484        private static final class LengthComparator implements Comparator<File>,Serializable {
    485                private static final long serialVersionUID = 400020050131L ;    // 4.0.0.0 (2005/01/31)
    486
    487                private final boolean desc ;
    488
    489                /**
    490                 * ファイルサイズでの比較を行うオブジェクトを作成します。
    491                 *
    492                 * @param desc 表示順逆順 [true:昇順/false:降順]
    493                 */
    494                public LengthComparator( final boolean desc ) { this.desc = desc; }
    495
    496                /**
    497                 * Comparator インターフェースの compare( File,File ) メソッド。
    498                 *
    499                 * @param o1 比較元１のファイルオブジェクト
    500                 * @param o2 比較元２のファイルオブジェクト
    501                 * @return      最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数
    502                 */
    503                public int compare( final File o1, final File o2 ) {
    504                        final File f1 = desc ? o2 : o1 ;
    505                        final File f2 = desc ? o1 : o2 ;
    506                        return (int)( f1.length() - f2.length() ) ;
    507                }
    508        }
    509
    510        /**
    511         * このオブジェクトの文字列表現を返します。
    512         * 基本的にデバッグ目的に使用します。
    513         *
    514         * @return このクラスの文字列表現
    515         * @og.rtnNotNull
    516         */
    517        @Override
    518        public String toString() {
    519                return ToString.title( this.getClass().getName() )
    520                                .println( "VERSION"             ,VERSION        )
    521                                .println( "orderBy"             ,orderBy        )
    522                                .println( "desc"                ,desc           )
    523                                .println( "from"                ,from           )
    524                                .println( "selValue"    ,selValue       )
    525                                .println( "Other..."    ,getAttributes().getAttribute() )
    526                                .fixForm().toString() ;
    527        }
    528}