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.xml;
017
018import java.util.Map;
019import java.util.LinkedHashMap;
020import java.util.List;
021
022/**
023 * このクラスは、XMLファイルのタグエレメントを表すオブジェクトです。
024 * タグとしては、コンストラクタにMapを指定すれば(defaultMap)タグのカラムを
025 * 初期設定します。この場合、Map に LinkedHashMap を指定すれば、カラムの
026 * 順番も指定順になります。
027 * ここで指定したMapの値は、put メソッドにより上書きされます。
028 * setAfterMap で指定したMapは、既存の内部情報を上書きします。キーがあれば、
029 * afterMap の値が上書きされ、キーが無ければ新規にキーが追加されます。
030 * 一般には、XMLファイルから構築された後で、XMLファイルの情報を一括して
031 * 書き換える場合などに使用します。
032 * 処理の途中にセットした場合は、それまでの値が上書きされ、それ以降の値は、
033 * put により設定された値が 優先されます。
034 * toString() により、簡易的に オラクルXDK形式のXMLファイルの
035 * 1レコード 分の情報を返します。
036 * オラクルXDK形式のXMLファイルとは、下記のような ROWSET をトップとする ROW の
037 * 集まりで1レコードを表し、各ROWには、カラム名をキーとするXMLになっています。
038 *
039 *   <ROWSET>
040 *       <ROW num="1">                         ← この部分のみ
041 *           <カラム1>値1</カラム1>      ← この部分のみ
042 *             ・・・                                   ← この部分のみ
043 *           <カラムn>値n</カラムn>      ← この部分のみ
044 *       </ROW>                                ← この部分のみ
045 *        ・・・
046 *       <ROW num="n">
047 *          ・・・
048 *       </ROW>
049 *   <ROWSET>
050 *
051 * この形式であれば、XDK(Oracle XML Developer's Kit)を利用すれば、非常に簡単に
052 * データベースとXMLファイルとの交換が可能です。
053 * <a href="http://otn.oracle.co.jp/software/tech/xml/xdk/index.html" target="_blank" >
054 * XDK(Oracle XML Developer's Kit)</a>
055 *
056 * @version  4.0
057 * @author   Kazuhiko Hasegawa
058 * @since    JDK5.0,
059 */
060public class TagElement {
061        private static final String CR = System.getProperty("line.separator");
062        private final String name ;
063        private final Map<String,String> map ;
064        private String num  = null;
065        private String body = null;
066
067        /**
068         * Tag名を指定して、オブジェクトを構築します。
069         *
070         * @param       name    Tag名
071         */
072        public TagElement( final String name ) {
073                this( name,null );
074        }
075
076        /**
077         * Tag名と初期化マップを指定して、オブジェクトを構築します。
078         *
079         * @param       name            Tag名
080         * @param       defaultMap      初期化マップ
081         */
082        public TagElement( final String name, final Map<String,String> defaultMap ) {
083                this.name = name;
084                if( defaultMap != null ) {
085                        map = new LinkedHashMap<String,String>( defaultMap );
086                }
087                else {
088                        map = new LinkedHashMap<String,String>();
089                }
090        }
091
092        /**
093         * Tag名を取得します。
094         *
095         * @return      Tag名
096         */
097        public String getName() {
098                return name;
099        }
100
101        /**
102         * カラムと値のペアを登録します。
103         * すでに 内部に同一カラムが存在する場合は、値の書き換えを、カラムが
104         * 存在しない場合は、カラムの追加を行います。
105         * カラムは、追加された順番を再現してXML化できます。
106         *
107         * @og.rev 5.6.6.1 (2013/07/12) key が null や ゼロ文字列の場合は、Map に追加しません。
108         *
109         * @param       key     カラム
110         * @param       val     値
111         */
112        public void put( final String key, final String val ) {
113                if( key != null && key.length() > 0 ) {                                 // 5.6.6.1 (2013/07/12)
114                        map.put( key,val );
115                }
116        }
117
118        /**
119         * すでに構築済みの カラムと値に、上書きで マップ情報を追加します。
120         * すでに 内部に同一カラムが存在する場合は、値の書き換えを、カラムが
121         * 存在しない場合は、カラムの追加を行います。
122         * カラムは、追加された順番を再現してXML化できます。
123         *
124         * @param afterMap      後設定マップ
125         */
126        public void setAfterMap( final Map<String,String> afterMap ) {
127                if( afterMap != null ) {
128                        map.putAll( afterMap );
129                }
130        }
131
132        /**
133         * キーを指定して値を取得します。
134         *
135         * @param       key     カラム
136         *
137         * @return      値
138         */
139        public String get( final String key ) {
140                return map.get( key );
141        }
142
143        /**
144         * 行番号を取得します。
145         *
146         * @return      値
147         */
148        public String getRowNo() {
149                return num;
150        }
151
152        /**
153         * 行番号を設定します。
154         *
155         * @param       num     値
156         */
157        public void setRowNo( final String num ) {
158                this.num = num ;
159        }
160
161        /**
162         * BODY部の文字列を取得します。
163         *
164         * @return      値
165         */
166        public String getBody() {
167                return body;
168        }
169
170        /**
171         * BODY部の文字列を設定します。
172         *
173         * @param       body    値
174         */
175        public void setBody( final String body ) {
176                this.body = body ;
177        }
178
179        /**
180         * カラムの配列を返します。
181         *
182         * @return      カラムの配列(順序は、カラムの登録順)
183         */
184        public String[] getKeys() {
185                return map.keySet().toArray( new String[map.size()] );
186        }
187
188        /**
189         * カラム配列の順と同じ、値の配列を返します。
190         *
191         * @return      値の配列(順序は、カラムの登録順と一致しています。)
192         */
193        public String[] getValues() {
194                return map.values().toArray( new String[map.size()] );
195        }
196
197        /**
198         * 引数のカラム名のListの順番で、カラム配列の値の配列を返します。
199         *
200         * @param clms  カラム名のListオブジェクト
201         *
202         * @return      値の配列(順序は、カラムの登録順と一致しています。)
203         */
204        public String[] getValues( final List<String> clms ) {
205                int size = clms.size();
206                String[] vals = new String[size];
207                for( int i=0; i<size; i++ ) {
208                        vals[i] = map.get( clms.get(i) );
209                }
210
211                return vals;
212        }
213
214        /**
215         * 引数のカラム名の配列の順番で、カラム配列の値の配列を返します。
216         * カラム名が、存在しない場合は、値は、null を返します。
217         *
218         * @param       clms    カラム名の配列文字列
219         *
220         * @return      値の配列(順序は、カラムの配列順と一致しています。)
221         */
222        public String[] getValues( final String[] clms ) {
223                int size = clms.length;
224                String[] vals = new String[size];
225                for( int i=0; i<size; i++ ) {
226                        vals[i] = map.get( clms[i] );
227                }
228
229                return vals;
230        }
231
232        /**
233         * 内部情報の文字列表現を返します。
234         * 1レコード分を表す ROW のXML表現を作成します。前後に、ROWSET を
235         * 追加すれば、オラクルXDK形式のXMLを作成できます。
236         *
237         * @return      内部情報の文字列表現
238         */
239        @Override
240        public String toString() {
241
242                StringBuilder buf = new StringBuilder();
243                buf.append( "<" ).append( name );
244                if( num != null ) {
245                        buf.append( " num=\"" ).append( num ).append( "\" " );
246                }
247                buf.append( ">" ).append( CR );
248
249                if( body != null ) {
250                        buf.append( body ).append( CR );
251                }
252                else {
253                        String[] keys = getKeys();
254                        for( int i=0; i<keys.length; i++ ) {
255                                String val = get( keys[i] );
256                                if( val == null ) {
257                                        buf.append( "  <" ).append( keys[i] ).append( " />" );
258                                }
259                                else {
260                                        buf.append( "  <" ).append( keys[i] ).append( ">" );
261                                        buf.append( val );
262                                        buf.append( "</" ).append( keys[i] ).append( ">" );
263                                }
264                                buf.append( CR );
265                        }
266                }
267                buf.append( "</" ).append( name ).append( ">" ).append( CR );
268
269                return buf.toString();
270        }
271}