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.hayabusa.taglib; 017 018import org.opengion.hayabusa.common.HybsSystemException; 019import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 020import static org.opengion.fukurou.util.StringUtil.nval ; 021 022/** 023 * case タグは、上位の switch タグの key とマッチした場合に、処理を行います。 024 * 025 * case タグの以下の属性について、説明します。 026 * match : switch_key.match( case_match ) でマッチした場合は、BODY が処理されます。 027 * isDefault: trueに設定すると、どのcase にもマッチしなかった場合に処理されます(初期値:false) 028 * isBreak : 通常、最初にマッチした段階で、switch 処理を抜けます(初期値:true) 029 * isNull : trueに設定すると、switchのkeyが、null(またはゼロ文字列)の場合、マッチします(初期値:false) 030 * 031 * @og.formSample 032 * ●形式:<og:switch key="・・・" > 033 * <og:case match="A" > ・・・ </og:case> 034 * <og:case match="B" > ・・・ </og:case> 035 * <og:case match="C" > ・・・ </og:case> 036 * <og:case isDefault="true" > ・・・ </og:case> 037 * </og:switch> 038 * ●body:あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{@XXXX} は解析しません) 039 * 040 * ●Tag定義: 041 * <og:case 042 * match 【TAG】switch-case のマッチ条件(case_match)を指定します 043 * isDefault 【TAG】どのcase にもマッチしなかった場合に処理する case 文かどうかを指定します(初期値:false) 044 * isBreak 【TAG】マッチした以降に継続処理を行わない(ブレイクする)かどうかを指定(初期値:true) 045 * isNull 【TAG】switchのkeyが、null(またはゼロ文字列)の場合、マッチするかどうか[true/false]を設定します(初期値:false) 046 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 047 * > ... Body ... 048 * </og:case> 049 * 050 * ●使用例 051 * <og:switch key="{@PARAM}" > 052 * <og:case match="A" > 処理A </og:case> 053 * <og:case match="B" > 処理B </og:case> 054 * <og:case match="C" > 処理C </og:case> 055 * <og:case isDefault="true" > 処理X </og:case> 056 * </og:switch> 057 * 058 * ・switch の key に対して、case の match に指定された値が、マッチ(switch_key.match( case_match )) 059 * した場合に、case の BODY 部分が処理されます。 060 * マッチしなければ、BODY部は、スキップされます。 061 * ・isDefault="true" の場合は、どれとも マッチしなかった場合に、実行されます。 062 * ・Javaの switch-case 文は、最初に処理された case 以降を処理します。通常は、break を入れて 063 * 後続処理を実行されないようにしています。 064 * この、switch-case タグは、caseタグの isBreak 属性で制御します。初期値が isBreak="true" に、 065 * なっているため、通常は、どれかの case が実行された段階で、switchの処理は、終了されます。 066 * isBreak="false" にすると、switchから抜けずに、継続して case との match を実行します。 067 * この場合、Java等と異なるのは、直後のcase文が実行されるのではなく、あくまで match 作業が 068 * 継続されるということです。つまり、複数の case で処理を行いたい場合は、isBreak="false" に 069 * すると同時に、match 条件もそれぞれで、マッチするように設定する必要があります。 070 * 071 * <og:switch key="{@PARAM}" > 072 * <og:case match="[1]" isBreak="false" > 処理A </og:case> 073 * <og:case match="[12]" isBreak="false" > 処理B </og:case> 074 * <og:case match="[123]" isBreak="false" > 処理C </og:case> 075 * <og:case isNull="true" > 処理X </og:case> 076 * <og:case isDefault="true" > 処理Y </og:case> 077 * </og:switch> 078 * 079 * ・上記指定では、isBreak="false" が指定されているため、マッチした後も継続して判定処理が実施されます。 080 * ・上記例で言うと、PARAM が "1" の場合、上記3つともにマッチします。 081 * ・isNull="true" は、switch の key が null の場合に成立します。(null とは、ゼロ文字列も含む) 082 * 083 * @og.group 画面制御 084 * @og.rev 5.2.3.0 (2010/12/01) 新規追加 085 * 086 * @version 5.2.3.0 (2010/12/01) 087 * @author Kazuhiko Hasegawa 088 * @since JDK1.6, 089 */ 090public class CaseTag extends CommonTagSupport { 091 /** このプログラムのVERSION文字列を設定します。 {@value} */ 092 private static final String VERSION = "6.4.2.0 (2016/01/29)" ; 093 private static final long serialVersionUID = 642020160129L ; 094 095 private String caseMatch ; // switch_key.match( case_match ) でマッチした場合は、BODY が処理されます。 096 private boolean isDefault ; // trueに設定すると、どのcase にもマッチしなかった場合に処理されます(初期値:false) 097 private boolean isBreak = true ; // 通常、最初にマッチした段階で、switch 処理を抜けます(初期値:true) 098 private boolean isNull ; // trueに設定すると、switchのkeyが、null(またはゼロ文字列)の場合、マッチします(初期値:false) 099 100 /** 101 * デフォルトコンストラクター 102 * 103 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 104 */ 105 public CaseTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 106 107 /** 108 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 109 * 110 * @return 後続処理の指示 111 */ 112 @Override 113 public int doStartTag() { 114 final SwitchTag switchTag = (SwitchTag)findAncestorWithClass( this,SwitchTag.class ); 115 if( switchTag == null ) { 116 final String errMsg = "<b>" + getTagName() + "タグは、switch タグの内部におく必要があります。</b>"; 117 throw new HybsSystemException( errMsg ); 118 } 119 120 boolean rtn = false; 121 if( switchTag.isMatch() ) { 122 final String key = switchTag.getKey(); 123 rtn = ( key != null && caseMatch != null && key.matches( caseMatch ) ) || 124 ( isNull && key == null ) || isDefault ; 125 126 if( rtn && isBreak ) { switchTag.setBreak(); } 127 } 128 129 if( rtn ) { return EVAL_BODY_INCLUDE ; } 130 else { return SKIP_BODY ; } 131 } 132 133 /** 134 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 135 * 136 * @return 後続処理の指示 137 */ 138 @Override 139 public int doEndTag() { 140 debugPrint(); // 4.0.0 (2005/02/28) 141 142 return EVAL_PAGE ; 143 } 144 145 /** 146 * タグリブオブジェクトをリリースします。 147 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 148 * 149 */ 150 @Override 151 protected void release2() { 152 super.release2(); 153 caseMatch = null ; // switch_key.match( case_match ) でマッチした場合は、BODY が処理されます。 154 isDefault = false; // trueに設定すると、どのcase にもマッチしなかった場合に処理されます(初期値:false) 155 isBreak = true ; // 通常、最初にマッチした段階で、switch 処理を抜けます(初期値:true) 156 isNull = false; // trueに設定すると、switchのkeyが、null(またはゼロ文字列)の場合、マッチします(初期値:false) 157 } 158 159 /** 160 * 【TAG】switch-case のマッチ条件(case_match)を指定します。 161 * 162 * @og.tag 163 * switch_key.match( case_match ) でマッチした場合は、BODY が処理されます。 164 * 165 * @param mkey マッチ条件 166 */ 167 public void setMatch( final String mkey ) { 168 caseMatch = nval( getRequestParameter( mkey ),caseMatch ); 169 } 170 171 /** 172 * 【TAG】どのcase にもマッチしなかった場合に処理する case 文かどうかを指定します(初期値:false)。 173 * 174 * @og.tag 175 * trueに設定すると、どのcase にもマッチしなかった場合に処理されます 176 * このタグそのものがなにも出力しません。(つまり条件から消えます。) 177 * BODY 部に記述することが可能です。その場合は、value 属性になにも設定できません。 178 * 初期値は、false:default case 文ではない です。 179 * 180 * @param flag デフォルト処理 [true:する/false:しない] 181 */ 182 public void setIsDefault( final String flag ) { 183 isDefault = nval( getRequestParameter( flag ),isDefault ); 184 } 185 186 /** 187 * 【TAG】マッチした以降に継続処理を行わない(ブレイクする)かどうかを指定(初期値:true)。 188 * 189 * @og.tag 190 * true に設定すると、マッチした段階で、ブレイクします。 191 * Javaの switch-case 文は、最初に処理された case 以降を処理します。通常は、break を入れて 192 * 後続処理を実行されないようにしています。 193 * この、switch-case タグは、caseタグの break 属性で制御します。初期値が break="true" に、 194 * なっているため、通常は、どれかの case が実行された段階で、switchの処理は、終了されます。 195 * break="false" にすると、switchから抜けずに、継続して case との match を実行します。 196 * この場合、Java等と異なるのは、直後のcase文が実行されるのではなく、あくまで match 作業が 197 * 継続されるということです。つまり、複数の case で処理を行いたい場合は、break="false" に 198 * すると同時に、match 条件もそれぞれで、マッチするように設定する必要があります。 199 * 初期値は、true:ブレイクする です。 200 * 201 * @param flag ブレイク可否 [true:する/false:しない(=継続処理する)] 202 */ 203 public void setIsBreak( final String flag ) { 204 isBreak = nval( getRequestParameter( flag ),isBreak ); 205 } 206 207 /** 208 * 【TAG】switchのkeyが、null(またはゼロ文字列)の場合、マッチするかどうか[true/false]を設定します(初期値:false)。 209 * 210 * @og.tag 211 * trueに設定すると、switchのkeyが、null(またはゼロ文字列)の場合、マッチします。 212 * 初期値のfalse にすると、キーが null でない場合だけ、マッチ処理を実行します。 213 * case の条件判定で使用されます。 214 * 初期値は、 false (null でない) です。 215 * 216 * @param flag nullマッチ判定 [true:する/false:しない] 217 */ 218 public void setIsNull( final String flag ) { 219 isNull = nval( getRequestParameter( flag ),isNull ); 220 } 221 222 /** 223 * このオブジェクトの文字列表現を返します。 224 * 基本的にデバッグ目的に使用します。 225 * 226 * @return このクラスの文字列表現 227 * @og.rtnNotNull 228 */ 229 @Override 230 public String toString() { 231 return ToString.title( this.getClass().getName() ) 232 .println( "VERSION" ,VERSION ) 233 .println( "caseMatch" ,caseMatch ) 234 .println( "isDefault" ,isDefault ) 235 .println( "isBreak" ,isBreak ) 236 .println( "isNull" ,isNull ) 237 .println( "Other..." ,getAttributes().getAttribute() ) 238 .fixForm().toString() ; 239 } 240}