    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 javax.xml.transform.TransformerException ;
    019import javax.xml.transform.ErrorListener;
    020import javax.xml.transform.SourceLocator;
    021
    022import org.xml.sax.ErrorHandler;
    023import org.xml.sax.SAXParseException;
    024
    025import static org.opengion.fukurou.system.HybsConst.CR;
    026import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;              // 6.4.2.1 (2016/02/05) refactoring
    027
    028/**
    029 * TransformerFactory、Transformer 等で発生するエラーや警告を補足する ErrorListener の実装クラスです。
    030 * さらに、XMLReader 等で発生するエラーや警告を補足する ErrorHandler の実装クラスも兼ねています。
    031 *
    032 * ErrorListener や、ErrorHandler で捕らえたエラーを、内部の StringBuilder に書き出して、
    033 * エラー発生時にその内容を、読み出します。
    034 *
    035 * TransformerFactory と Transformer に、同じオブジェクトを渡すことで、エラー発生時の
    036 * 状況に応じて、メッセージが設定されていきます。
    037 * 取り出しは、セットしたオブジェクトを、取り出して、toString() するだけにしています。
    038 *
    039 * @og.rev 6.4.0.2 (2015/12/11) 新規作成
    040 * @og.rev 6.4.3.2 (2016/02/19) 新規作成
    041 *
    042 * @version  6.4
    043 * @author   Kazuhiko Hasegawa
    044 * @since    JDK8.0,
    045 */
    046public class HybsErrorListener implements ErrorListener , ErrorHandler {
    047        // 6.4.3.2 (2016/02/19) 最初から用意しておきます。
    048        private final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE ) ;
    049
    050        /**
    051         * 引数なしのコンストラクタ。
    052         *
    053         * @og.rev 6.4.3.2 (2016/02/19) 内部の StringBuilder は、最初から用意しておきます。
    054         */
    055        public HybsErrorListener() { super(); }         // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    056
    057        /**
    058         * TransformerFactory,Transformer処理の、警告の通知を受け取ります。
    059         *
    060         * @param       ex Transformer例外にカプセル化されたエラー情報
    061         * @see         javax.xml.transform.ErrorListener#warning( TransformerException )
    062         */
    063        @Override       // ErrorListener
    064        public void warning( final TransformerException ex ) { errMsg( "Warning:" , ex ); }
    065
    066        /**
    067         * TransformerFactory,Transformer処理の、回復可能なエラーの通知を受け取ります。
    068         *
    069         * @param       ex Transformer例外にカプセル化されたエラー情報
    070         * @see         javax.xml.transform.ErrorListener#error( TransformerException )
    071         */
    072        @Override       // ErrorListener
    073        public void error( final TransformerException ex ) { errMsg( "Error:" , ex ); }
    074
    075        /**
    076         * TransformerFactory,Transformer処理の、回復できないエラーの通知を受け取ります。
    077         *
    078         * @param       ex Transformer例外にカプセル化されたエラー情報
    079         * @see         javax.xml.transform.ErrorListener#fatalError( TransformerException )
    080         */
    081        @Override       // ErrorListener
    082        public void fatalError( final TransformerException ex ) { errMsg( "Fatal:" , ex ); }
    083
    084        /**
    085         * XML構文解析エラーまたは警告の、警告の通知を受け取ります。
    086         *
    087         * @param       ex SAXParseException例外にカプセル化されたエラー情報
    088         * @see         org.xml.sax.ErrorHandler#warning( SAXParseException )
    089         */
    090        @Override       // ErrorHandler
    091        public void warning( final SAXParseException ex ) { errMsg( "Warning:" , ex ); }
    092
    093        /**
    094         * XML構文解析エラーまたは警告の、回復可能なエラーの通知を受け取ります。
    095         *
    096         * @param       ex SAXParseException例外にカプセル化されたエラー情報
    097         * @see         org.xml.sax.ErrorHandler#error( SAXParseException )
    098         */
    099        @Override       // ErrorHandler
    100        public void error( final SAXParseException ex ) { errMsg( "Error:" , ex ); }
    101
    102        /**
    103         * XML構文解析エラーまたは警告の、回復できないエラーの通知を受け取ります。
    104         *
    105         * @param       ex SAXParseException例外にカプセル化されたエラー情報
    106         * @see         org.xml.sax.ErrorHandler#fatalError( SAXParseException )
    107         */
    108        @Override       // ErrorHandler
    109        public void fatalError( final SAXParseException ex ) { errMsg( "Fatal:" , ex ); }
    110
    111        /**
    112         * warning,error,fatalErrorの通知を受け取ります。
    113         *
    114         * @param       type 例外の発生元( "Warning:","Error:","Fatal:" )
    115         * @param       ex       Transformer例外にカプセル化されたエラー情報
    116         */
    117        private void errMsg( final String type , final TransformerException ex ) {
    118                final SourceLocator locator = ex.getLocator();          // 例外発生元情報の取得
    119                if( locator != null ) {
    120                        errBuf.append( " (" ).append( locator.getLineNumber() ).append( "): " );
    121                }
    122
    123                final String errMsg = ex.getMessage();
    124                // null という文字列が取得されているようです。
    125                if( errMsg != null && !"null".equals( errMsg ) ) {
    126                        errBuf.append( type ).append( errMsg ).append( CR );
    127                }
    128
    129                Throwable cause = ex.getException();                    // この例外がラップする例外を取得
    130                if( cause instanceof TransformerException ) {
    131                        errMsg( "ﾗｯﾌﾟ:" , (TransformerException)cause );
    132                }
    133
    134                cause = ex.getCause();                                                  // この例外の原因となる例外を取得
    135                if( cause instanceof TransformerException ) {
    136                        errMsg( "原因:" , (TransformerException)cause );
    137                }
    138        }
    139
    140        /**
    141         * warning,error,fatalErrorの通知を受け取ります。
    142         *
    143         * @param       type 例外の発生元( "Warning:","Error:","Fatal:" )
    144         * @param       ex       SAXParseException例外にカプセル化されたエラー情報
    145         */
    146        private void errMsg( final String type , final SAXParseException ex ) {
    147                final int lineNo = ex.getLineNumber();          // 発生元テキストの終わりの行番号(最初は１、使用できない場合は、-1
    148                if( lineNo >= 0 ) {
    149                        errBuf.append( " (" ).append( lineNo ).append( "): " );
    150                }
    151
    152                final String errMsg = ex.getMessage();
    153                // null という文字列が取得されるかどうかは、未確認です。
    154                if( errMsg != null && !"null".equals( errMsg ) ) {
    155                        errBuf.append( type ).append( errMsg ).append( CR );
    156                }
    157
    158                Throwable cause = ex.getException();                    // この例外がラップする例外を取得
    159                if( cause instanceof SAXParseException ) {
    160                        errMsg( "ﾗｯﾌﾟ:" , (SAXParseException)cause );
    161                }
    162
    163                cause = ex.getCause();                                                  // この例外の原因となる例外を取得
    164                if( cause instanceof SAXParseException ) {
    165                        errMsg( "原因:" , (SAXParseException)cause );
    166                }
    167        }
    168
    169        /**
    170         * 内部で保管しているエラーメッセージを返します。
    171         *
    172         * メソッド的には、getMessage() がよいのですが、ErrorListener のまま、
    173         * オブジェクトとして文字列(メッセージ)を取り出すには、Objectから継承している
    174         * toString() メソッドが、便利なので、こちらにしておきます。
    175         *
    176         * @return      エラーメッセー
    177         */
    178        @Override       // Object
    179        public String toString() { return errBuf.toString(); }
    180}