    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() により、簡易的に オラクルＸＤＫ形式のＸＭＬファイルの
    035 * １レコード 分の情報を返します。
    036 * オラクルＸＤＫ形式のＸＭＬファイルとは、下記のような ROWSET をトップとする ROW の
    037 * 集まりで１レコードを表し、各ROWには、カラム名をキーとするXMLになっています。
    038 *
    039 *   &lt;ROWSET&gt;
    040 *       &lt;ROW num="1"&gt;                         ← この部分のみ
    041 *           &lt;カラム1&gt;値1&lt;/カラム1&gt;      ← この部分のみ
    042 *             ･･･                                   ← この部分のみ
    043 *           &lt;カラムn&gt;値n&lt;/カラムn&gt;      ← この部分のみ
    044 *       &lt;/ROW&gt;                                ← この部分のみ
    045 *        ･･･
    046 *       &lt;ROW num="n"&gt;
    047 *          ･･･
    048 *       &lt;/ROW&gt;
    049 *   &lt;ROWSET&gt;
    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         * １レコード分を表す 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}