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.Set; 019import java.util.Map; 020import java.util.HashMap; 021import java.util.Arrays; 022import 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 */ 037public 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}