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;
019
020/**
021 * JSP/XMLファイルを読み取って、構築される最上位の OGDocument オブジェクト を定義します。
022 *
023 * JspSaxParser での read/write で構築される トップレベルの OGNode になります。
024 *
025 * @og.rev 5.1.8.0 (2010/07/01) 新規作成
026 *
027 * @version  5.0
028 * @author   Kazuhiko Hasegawa
029 * @since    JDK6.0,
030 */
031public class OGDocument extends OGNode {
032        private Map<String,OGElement> idMap = null;             // 5.1.9.0 (2010/08/01)
033        private String file   = null;
034        private String encode = "UTF-8";                                // 基本的には、XML は、UTF-8 で扱うのが良い。
035        private String nameSpace = null;                                // 5.2.1.0 (2010/10/01) トップエレメントの名前空間のキャッシュ
036
037        /**
038         * デフォルトコンストラクター
039         *
040         * NodeType を Document に設定し、デフォルトの OGNode を構築します。
041         *
042         */
043        public OGDocument() {
044                super();
045                setNodeType( OGNodeType.Document );
046        }
047
048        /**
049         * 最上位の エレメントを返します。
050         *
051         * ノードが、まだ登録されていない、または、エレメントノードでない場合は、null が返されます。
052         *
053         * @return      最上位のエレメント
054         */
055        public OGElement getTopElement() {
056                if( nodeSize() > 0 ) {
057                        OGNode node = getNode( 0 );
058                        if( node.getNodeType() == OGNodeType.Element ) {
059                                return (OGElement)node;
060                        }
061                }
062                return null ;
063        }
064
065        /**
066         * このドキュメントの読み込み元のファイル名をセットします。
067         *
068         * ドキュメントの処理の可否を判断したり、デバッグ時に使用します。
069         *
070         * @param       name    読み込んだファイル名
071         */
072        public void setFilename( final String name ) {
073                file = name;
074        }
075
076        /**
077         * このドキュメントの読み込み元のファイル名を取得します。
078         *
079         * ドキュメントの処理の可否を判断したり、デバッグ時に使用します。
080         *
081         * @return      読み込んだファイル名
082         */
083        public String getFilename() {
084                return file;
085        }
086
087        /**
088         * このドキュメントのXML宣言のエンコード属性をセットします(初期値:UTF-8)。
089         *
090         * ドキュメントの出力時の XML 宣言に付与します。
091         * null の設定が可能です。 null をセットすると、XML宣言出力時に、
092         * encode 属性になにもセットしません。
093         *
094         * @param       encode  XML宣言のエンコード属性
095         */
096        public void setEncode( final String encode ) {
097                this.encode = encode;
098        }
099
100        /**
101         * このドキュメントのXML宣言のエンコード属性を取得します(初期値:UTF-8)。
102         *
103         * ドキュメントの出力時の XML 宣言に付与します。
104         * encode 属性になにもセットされていない場合は、null が返されます。
105         *
106         * @return      XML宣言のエンコード属性
107         */
108        public String getEncode() {
109                return encode;
110        }
111
112        /**
113         * このドキュメントの "hybs-taglib.tld" の nameSpace(名前空間)を返します。
114         *
115         * 通常は、標準エンジンの場合は "og" になります。
116         * 社内システムの場合は、互換性の関係から、"mis" になっています。
117         * Ver3 の時代は、"mis-taglib.tld" だったので、この処理はできません。
118         *
119         * @og.rev 5.2.1.0 (2010/10/01) 新規作成
120         *
121         * @return      名前空間(存在しないときは、ゼロ文字列)
122         */
123        public String getNameSpace() {
124                if( nameSpace != null ) { return nameSpace; }
125
126                nameSpace = "" ;                // 存在しないときは、ゼロ文字列になる。
127                OGElement ele = getTopElement();
128                if( ele != null ) {
129                        OGAttributes attri = ele.getOGAttributes();
130                        for( int i=0; i<attri.size(); i++ ) {
131                                if( "hybs-taglib.tld".equals( attri.getVal(i) ) ) {
132                                        String key = attri.getKey(i);                   // xmlns:og , xmlns:mis などのはず
133                                        int cm = key.indexOf( ':' );
134                                        nameSpace = key.substring( cm+1 );                      // : は削除している。"og" など
135                                        break;
136                                }
137                        }
138                }
139                return nameSpace;
140        }
141
142        /**
143         * このドキュメントに含まれる id に対する、エレメントのマップをセットします。
144         *
145         * id 指定されているエレメントは、特別にキャッシュされます。
146         * また、ドキュメント中には、id は、一意に設定されていることとします。
147         * 複数、おなじ id が存在する場合は、(保障されませんが)性質上、最後に登録された
148         * エレメントが、設定されます。
149         *
150         * @param       map     エレメントのマップ
151         */
152        public void setIdMap( final Map<String,OGElement> map ) {
153                idMap = map;
154        }
155
156        /**
157         * 指定の id に対するエレメントを返します。
158         *
159         * id に対するエレメントが存在しない場合は、null が返されます。
160         *
161         * @param       id      指定のID
162         *
163         * @return      OGエレメント
164         */
165        public OGElement getElementById( final String id ) {
166                OGElement ele = null;
167
168                if( idMap != null ) { ele = idMap.get( id ); }
169
170                return ele ;
171        }
172
173        /**
174         * オブジェクトの文字列表現を返します。
175         *
176         * ここでは、ドキュメントにXML宣言をつけた状態の文字列を返します。
177         * 基本的には、ドキュメントには、一つだけ エレメントを含むことになります。
178         * よって、XML宣言をつけない状態で出力する場合は、#getTopElement() で
179         * エレメントを取得して、それを、toString() してください。
180         *
181         * @og.rev 5.6.4.4 (2013/05/31) 改行3つを改行2つに置換します。
182         *
183         * @return      このオブジェクトの文字列表現
184         * @see OGNode#toString()
185         * @see #getTopElement()
186         */
187        @Override
188        public String toString() {
189                StringBuilder buf = new StringBuilder();
190
191                buf.append( "<?xml version=\"1.0\"" );
192                if( encode != null ) {
193                        buf.append( " encoding=\"" ).append( encode ).append( "\"" );
194                }
195                buf.append( "?>" ).append( CR ).append( super.toString() );
196
197                return buf.toString().replaceAll( CR+CR+CR , CR+CR ) ;                  // 改行3つを改行2つに置換します。
198        }
199}