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.util;
017    
018    import java.util.Set;
019    import java.util.Map;
020    import java.util.HashMap;
021    import java.util.Arrays;
022    import java.util.Locale;
023    
024    /**
025     * Attributes.java は、String 型キーにString型å?ã‚?Map するクラスですã?
026     *
027     * HTMLのPOST/GET等ã?受け渡しや、String型ã?引数が多い場合に効果がありますã?
028     * 特に、getAttributes( String[] param ) による属æ?リスト作æ?はã€?
029     * HTMLタグの属æ?定義を行う上で?Œ非常に便利に利用できますã?
030     *
031     * こã?実è£??同期化されませんã€?
032     *
033     * @version  4.0
034     * @author   Kazuhiko Hasegawa
035     * @since    JDK5.0,
036     */
037    public final class Attributes {
038            private final Map<String,String> attri ;
039    
040            /**
041             * ãƒ?ƒ•ォルトコンストラクター
042             *
043             */
044            public Attributes() {
045                    attri = new HashMap<String,String>();
046            }
047    
048            /**
049             * Attributesオブジェクãƒ?を与えて新しく作æ?するコンストラクター
050             *
051             * @param att Attributesオブジェクãƒ?
052             */
053            public Attributes( final Attributes att ) {
054                    attri = new HashMap<String,String>( att.attri );
055            }
056    
057            /**
058             * マップからã?ãƒ?ƒ”ングをすべて削除しまã�?ã€?
059             *
060             */
061            public void clear()  {
062                    attri.clear() ;
063            }
064    
065            /**
066             * マップがæŒ?®šã?キーをã?ãƒ??する値を返しますã?
067             * マップがこã?キーのマッピングを保持してã�?�ªã�??合ã? null
068             * を返しますã?戻りå?の null は、ã?ãƒ??がキーのマッピングã‚?
069             * 保持してã�?�ªã�?�“とを示すとはかぎりません。つまりã?マップが
070             * 明示çš?�«キーã‚?null にマップすることもありますã?
071             *
072             * @param    key 関連付けられたå?が返されるキー(大æ–?­—小文字ã?同å?)
073             *
074             * @return   マップが、指定されたキーにマッピングしてã�?‚‹値ã€?
075             *           こã?キーに対するマッピングがã?ãƒ??になã�??合ã? null
076             */
077            public String get( final String key ) {
078                    return attri.get( key.toLowerCase( Locale.JAPAN ) ) ;
079            }
080    
081            /**
082             * æŒ?®šされた値とæŒ?®šされたキーをこのマップに関連付けまã�?
083             * æŒ?®šされたキーに、null を関連付けることはできませんã€?
084             * (もちろんã€?"?šゼロストリング は登録できますã?)
085             * なぜならã?getAttribute( String[] keys ) 等で値ã�?null の
086             * キーは、取得できなã�?‚ºですã?
087             * またã?すでに何らかã?値がセãƒ?ƒˆされてã�?‚‹æ‰?�«?¤null をセãƒ?ƒˆした
088             * 場合ã??¤前ã?値をなにも変更しませんã€?
089             * 通常、å?をクリアしたã�??合ã??¤ remove( String key ) を利用してくださいã€?
090             *
091             * @param    key æŒ?®šされる値が関連付けられるキー(大æ–?­—小文字ã?同å?)
092             * @param    value æŒ?®šされるキーに関連付けられるå?
093             */
094            public void set( final String key,final String value ) {
095                    if( value != null ) {
096                            attri.put( key.toLowerCase( Locale.JAPAN ),value ) ;
097                    }
098            }
099    
100            /**
101             * æŒ?®šされた値とæŒ?®šされたキーをこのマップに関連付けまã�?
102             * set( String key,String value ) との違いは?¤value ã�?null
103             * の場合に、def を代わりにセãƒ?ƒˆすることですã?
104             * ただしã?value ã�?null で、def ã‚?null の場合ã??¤
105             * なにもセãƒ?ƒˆされませんã€?
106             *
107             * @param    key æŒ?®šされる値が関連付けられるキー(大æ–?­—小文字ã?同å?)
108             * @param    value æŒ?®šされるキーに関連付けられるå?
109             * @param    def value ã�?null の場合にキーに関連付けられるå?
110             */
111            public void set( final String key,final String value,final String def ) {
112                    if( value != null )    { attri.put( key.toLowerCase( Locale.JAPAN ),value ) ; }
113                    else if( def != null ) { attri.put( key.toLowerCase( Locale.JAPAN ),def )   ; }
114            }
115    
116            /**
117             * æŒ?®šされた値とæŒ?®šされたキーをこのマップに追åŠ?�—まã�?
118             *
119             * マップè?身のキーは、ユニã?クである為、既存ã?値に対してã€?
120             * 新しく値を追åŠ?�—ますã?
121             * 追åŠ?�™る方法ã?、å?のæ–?­—å?の結合ですã?こã?メソãƒ?ƒ‰ではã€?
122             * ãƒ?ƒ•ォルトã?スペã?スで結合しますã?
123             *
124             * 値ã�?null またã?、すでにそã?キーに同ä¸??値が関連付けられてã�?‚‹場合ã?ã€?
125             * 何もしませんã€?
126             *
127             * @param    key   æŒ?®šされる値が関連付けられるキー(大æ–?­—小文字ã?同å?)
128             * @param    value æŒ?®šされるキーの値に、追åŠ?�•れる値
129             */
130            public void add( final String key,final String value ) {
131                    add( key,value," " ) ;
132            }
133    
134            /**
135             * æŒ?®šされた値とæŒ?®šされたキーをこのマップに追åŠ?�—まã�?
136             *
137             * マップè?身のキーは、ユニã?クである為、既存ã?値に対してã€?
138             * 新しく値を追åŠ?�—ますã?
139             * 追åŠ?�™る方法ã?、å?のæ–?­—å?の結合ですã?こã?メソãƒ?ƒ‰ではã€?
140             * 引数 sepa でæ–?­—å?を結合しますã?
141             *
142             * 値ã�?null またã?、sepa ã�?null またã?、すでにそã?キーに
143             * 同ä¸??値が関連付けられてã�?‚‹場合ã?、何もしませんã€?
144             *
145             * @param    key   æŒ?®šされる値が関連付けられるキー(大æ–?­—小文字ã?同å?)
146             * @param    value æŒ?®šされるキーの値に、追åŠ?�•れる値
147             * @param    sepa  値をé?結するときã?æ–?­—å?
148             */
149            public void add( final String key,final String value,final String sepa ) {
150                    if( value != null && sepa != null ) {
151                            String lkey = key.toLowerCase( Locale.JAPAN );
152                            String temp = attri.get( lkey );
153                            if( temp != null ) {
154                                    temp = temp.trim();
155                                    if( temp.indexOf( value ) < 0 ||                     // 存在しなã�?またã?ã€?
156                                            ( ! temp.equals( value ) &&                             // ä¸??しなã�?
157                                              ! temp.startsWith( value + sepa ) &&  // 先é?になã�?
158                                              ! temp.endsWith( sepa + value ) &&    // æœ?µ‚になã�?
159                                              temp.indexOf( sepa + value + sepa ) < 0 ) ) {      // 途中になã�?
160                                                    if( temp.endsWith( sepa ) ) {
161                                                            attri.put( lkey,temp + value );
162                                                    }
163                                                    else {
164                                                            attri.put( lkey,temp + sepa + value );
165                                                    }
166                                    }
167                            }
168                            else {
169                                    attri.put( lkey,value );
170                            }
171                    }
172            }
173    
174            /**
175             * Attributes 属æ?をã?既存ã?属æ?に追åŠ?�—ますã?
176             * すでに同ä¸?‚­ーの属æ?が存在してã�?‚‹場合ã??Œ上書きで
177             * 置き換えますã?
178             * 引数 att ã�?null の場合ã??Œ何もしませんã€?
179             *
180             * @param att Attributes属æ?
181             */
182            public void addAttributes( final Attributes att ) {
183                    if( att != null ) {
184                            String[] keys = att.getKeyArray();
185                            for( int i=0; i<keys.length; i++ ) {
186                                    set( keys[i],att.get( keys[i] ) );
187                            }
188                    }
189            }
190    
191            /**
192             * こã?キーにマッピングがあるå?合に、そのマッピングをã?ãƒ??から削除しまã�?
193             *
194             * @param    key マッピングがã?ãƒ??から削除されるキー(大æ–?­—小文字ã?同å?)
195             *
196             * @return   こã?キーにマッピングがあるå?合に、そのマッピングをã?ãƒ??から削除しまã�?
197             *           æŒ?®šされたキーに関連した以前ã?値。key にマッピングがなかったå?合ã? nullã€?
198             */
199            public String remove( final String key ) {
200                    return attri.remove( key.toLowerCase( Locale.JAPAN ) );
201            }
202    
203            /**
204             * マップå?のキーと値のマッピングの数を返しますã?
205             *
206             * @return   インタフェース Map å†?? size
207             *
208             */
209            public int size() {
210                    return attri.size() ;
211            }
212    
213            /**
214             * マップに含まれてã�?‚‹キーの配å?を返しますã?
215             * ここでは、キーの配å?はソートして返しますã?
216             *
217             * @return   マップに含まれてã�?‚‹キーの配å?
218             *
219             */
220            public String[] getKeyArray() {
221                    Set<String> keyset = attri.keySet();
222                    String[] rtn = keyset.toArray( new String[keyset.size()] ) ;
223                    Arrays.sort( rtn );
224                    return rtn ;
225            }
226    
227            /**
228             * マップに含まれてã�?‚‹キーと属æ?のペアã‚?タグの属æ?リストã?形式で返しますã?
229             * key1="value1" key2="value2" key3="value3" .... の形式で、value ã�?null の
230             * 場合ã??Œkey そã?もã?のペアをå?力しませんã€?
231             * value が空æ–?­—å? "" の場合ã??Œkey="" で出力しますã?
232             *
233             * 引数には?Œkey として出力したい値をé?列文字å?で渡しますã?
234             * これは、拡張性に乏しã�?すべて出せã??Œ属æ?é ?›®の追åŠ?�«対応できるã€?
235             * 方法ですが、タグ毎に異なる属æ?のみを管ç�?�™るには?Œ厳格に出åŠ?
236             * タグ属æ?を定義したã�?�¨ã�?�†思いから?Œ導å?しましたã€?
237             *
238             * @param    keys æŒ?®?key の配å?æ–?­—å?(大æ–?­—小文字ã?同å?)
239             *
240             * @return   キーと属æ?のペアをタグの属æ?リストã?形式で返しまã�?
241             *
242             */
243            public String getAttribute( final String[] keys ) {
244                    StringBuilder buf = new StringBuilder( 200 );
245    
246                    for( int i=0; i<keys.length; i++ ) {
247                            String value = get( keys[i].toLowerCase( Locale.JAPAN ) );
248                            if( value != null ) {
249                                    buf.append( keys[i] ).append("=");
250                                    buf.append("\"").append( value ).append("\" ");
251                            }
252                    }
253                    return buf.toString();
254            }
255    
256            /**
257             * マップに含まれてã�?‚‹キーと属æ?のペアã‚?タグの属æ?リストã?形式ですべて返しますã?
258             * なおã?value ã�?null の場合ã??Œkey そã?もã?のペアをå?力しませんã€?
259             * value が空æ–?­—å? "" の場合ã??Œkey="" で出力しますã?
260             *
261             * @return   キーと属æ?のペアをタグの属æ?リストã?形式で返しまã�?
262             *
263             */
264            public String getAttribute() {
265                    return getAttribute( getKeyArray() );
266            }
267    
268            /**
269             * こã?オブジェクトã?æ–?­—å?表現を返しますã?
270             * 基本çš?�«ãƒ?ƒ�ãƒ?‚°目çš?�«使用しますã?
271             *
272             * @return      オブジェクトã?æ–?­—å?表現
273             */
274            @Override
275            public String toString() {
276                    return( getAttribute() );
277            }
278    }