    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.util;
    017
    018import java.util.Map ;
    019import java.util.LinkedHashMap ;
    020import java.util.Collections;                                                                           // 6.4.3.1 (2016/02/12) refactoring
    021import java.util.Locale;
    022import java.util.Iterator;
    023
    024import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
    025import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
    026
    027/**
    028 * EnumType.java は、共通的に使用される 文字型選択フィールドを簡素化するクラスです。
    029 * JDK5.0 より導入された enum に類似の機能を提供しますが、内部的により特化した
    030 * 機能を提供します。
    031 * 具体的には、デバッグ情報の簡易出力や、文字列入力時の包含関係チェック、
    032 * デフォルト値(初期値)の登録などです。
    033 * 初期値には、String,int,boolean の３タイプが指定できます。
    034 *
    035 * @version  4.0
    036 * @author       Kazuhiko Hasegawa
    037 * @since    JDK5.0,
    038 */
    039public final class EnumType<T extends Comparable<T>> {  // 4.3.3.6 (2008/11/15) Generics警告対応
    040
    041        /** ８つ分のスペースです。 */
    042        private static final String SPACE = "    " ;
    043
    044        /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。  */
    045        private final Map<String,Types<T>> typemap = Collections.synchronizedMap( new LinkedHashMap<>() );
    046
    047        private final String title  ;
    048        private final T      defVal ;
    049
    050        /**
    051         * タイトルと初期値を指定して構築する コンストラクター
    052         * nval メソッドを使用する場合に、利用します。
    053         *
    054         * @param title タイトル
    055         * @param val 初期値
    056         */
    057        public EnumType( final String title,final T val ) {
    058                this.title = title ;
    059                defVal = val ;
    060        }
    061
    062        /**
    063         * キーとその説明(メッセージ)を追加します。
    064         * 内部キャッシュ(Map)に追加します。
    065         * 通常のメソッド名なら、put か add ですが、return に
    066         * 自分自身を記述できるため、初期設定(コンストラクタ)＋値設定を
    067         * 連続して記述することが出来る append メソッドにちなんで命名しています。
    068         *
    069         * @param key キー
    070         * @param msg メッセージ
    071         *
    072         * @return      自分自身
    073         */
    074        public EnumType<T> append( final T key, final String msg ) {
    075                typemap.put( String.valueOf( key ).toUpperCase( Locale.JAPAN ),new Types<T>( key,msg ) );
    076                return this ;
    077        }
    078
    079        /**
    080         * 文字列相当の設定値より、対応する T オブジェクトを返します。
    081         * T は、インスタンス作成時に、new EnumType&lt;T&gt; で指定するオブジェクトです。
    082         * 引数の文字列は、 String.valueOf( T ) で得られる文字列です。
    083         * 引数が、null か、長さゼロの文字列の場合は、コンストラクタで指定した
    084         * 初期値が返されます。
    085         * T に Boolean や Integer を指定している場合は、アンボクシング機能により、
    086         * boolean や int に自動的にキャストされます。
    087         *
    088         * @param       strKey 文字列相当の設定値
    089         *
    090         * @return      strKeyに対応するオブジェクト
    091         * @throws IllegalArgumentException 引数がMapに存在しなかった場合(nullはOK)
    092         */
    093        public T nval( final String strKey ) {
    094                if( strKey != null && strKey.length() > 0 ) {
    095                        final String upKey = strKey.toUpperCase( Locale.JAPAN );
    096                        if( typemap.containsKey( upKey ) ) {
    097                                final Types<T> type = typemap.get( upKey );
    098                                return type.getKey();
    099                        }
    100                        else {
    101                                final String errMsg = title + " 範囲設定エラー"
    102                                                        + CR + "引数 [" + strKey + "] は、内部にマップされていません。"
    103                                                        + CR + toString() ;
    104                                throw new IllegalArgumentException( errMsg );
    105                        }
    106                }
    107                return defVal ;
    108        }
    109
    110        /**
    111         * 初期値を返します。
    112         * T に Boolean や Integer を指定している場合は、アンボクシング機能により、
    113         * boolean や int に自動的にキャストされます。
    114         *
    115         * @return      初期値オブジェクト
    116         */
    117        public T getDefault() {
    118                return defVal ;
    119        }
    120
    121        /**
    122         * 設定した T が存在しているかどうかを返します。
    123         * 内部に値を取り込んだ後で使用する、存在チェックです。
    124         * 通常、nval で 取り込んだ後は、チェック不要です。
    125         * 引数が null の場合は、false を返します。
    126         *
    127         * @param key T 設定した Tオブジェクト
    128         *
    129         * @return      存在する:true / 存在しない:false
    130         */
    131        public boolean contains( final T key ) {
    132                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    133                return key != null && typemap.containsKey( String.valueOf( key ).toUpperCase( Locale.JAPAN ) );
    134        }
    135
    136        /**
    137         * 内部の文字列表現を返します。
    138         *
    139         * @return      内部の文字列表現
    140         * @og.rtnNotNull
    141         */
    142        @Override
    143        public String toString() {
    144                // 4.3.3.6 (2008/11/15) Generics警告対応 , toArray から、Iterator に、変更
    145                final Iterator<Types<T>> ite = typemap.values().iterator();
    146                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    147                buf.append( CR );
    148                while( ite.hasNext() ) {
    149                        buf.append( SPACE ).append( ite.next() ).append( CR );
    150                }
    151                return buf.toString();
    152        }
    153
    154        /**
    155         * 内部オブジェクトを管理する為の インナークラス
    156         * キーオブジェクトとその説明のペアを管理します。
    157         *
    158         * @version  4.0
    159         * @author       Kazuhiko Hasegawa
    160         * @since    JDK5.0,
    161         */
    162        private static final class Types<T> {
    163                private final T key ;
    164                private final String msg ;
    165
    166                /**
    167                 * キーと説明を指定したコンストラクタ
    168                 *
    169                 * @param key T キーオブジェクト
    170                 * @param       msg     説明
    171                 * @throws IllegalArgumentException キーオブジェクトがnullの場合
    172                 */
    173                public Types( final T key,final String msg ) {
    174                        if( key == null ) {
    175                                final String errMsg = "key には null をセットできません。" ;
    176                                throw new IllegalArgumentException( errMsg );
    177                        }
    178
    179                        this.key = key;
    180                        this.msg = msg;
    181                }
    182
    183                /**
    184                 * キーオブジェクトを返します。
    185                 *
    186                 * @return キーオブジェクト
    187                 */
    188                public T getKey() { return key; }
    189
    190                /**
    191                 * 説明を返します。
    192                 *
    193                 * @return 説明文字列
    194                 */
    195                public String getMsg() { return msg; }
    196
    197                /**
    198                 * 内部の文字列表現を返します。
    199                 *
    200                 * @return      内部の文字列表現
    201                 * @og.rtnNotNull
    202                 */
    203                @Override
    204                public String toString() {
    205                        return key + " : " + msg ;
    206                }
    207        }
    208}