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.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.resource.GUIInfo; 021import org.opengion.hayabusa.resource.UserInfo; 022import org.opengion.hayabusa.resource.CodeData; 023import org.opengion.hayabusa.resource.FavoriteGUIData; 024import org.opengion.hayabusa.resource.ResourceManager; 025import org.opengion.fukurou.util.XHTMLTag; 026import org.opengion.fukurou.util.FileMap; 027import org.opengion.fukurou.util.TagBuffer; 028import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 029import org.opengion.fukurou.util.StringUtil ; 030import org.opengion.fukurou.util.ArraySet; // 6.4.3.4 (2016/03/11) 031 032import org.opengion.fukurou.system.OgBuilder ; // 6.4.4.1 (2016/03/18) 033import static org.opengion.fukurou.util.StringUtil.nval ; 034import static org.opengion.fukurou.system.HybsConst.BUFFER_LARGE; // 6.1.0.0 (2014/12/26) refactoring 035import static org.opengion.fukurou.system.HybsConst.BR; // 6.1.0.0 (2014/12/26) refactoring 036 037import java.util.Set ; 038import java.util.LinkedHashSet; 039import java.util.TreeSet; // 6.8.3.1 (2017/12/01) 040import java.util.Iterator; 041import java.util.Map; 042 043/** 044 * 画面アクセスメニューを作成します。 045 * 046 * 画面リソースの階層番号(レベル)は、 047 * 0:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます) 048 * 1:トップ階層(【分類名称】) 049 * 2:選択階層(通常の折りたたみメニュー) 050 * 3:選択非表示(通常は、隠してあります) 051 * です。 052 * お気に入りメニューを登録するキーワードに、HybsSystem.GUI_FAV_MENU_KEY を使用しています。 053 * これは、エンジン内部で使用しているキーワードです。 054 * 055 * ※ 6.9.4.1 (2018/04/09) HYBS_BR の廃止 056 * 以前から、画面メニューを少し空けるために、HYBS_BR が使われていましたが、廃止しました。 057 * 058 * @og.formSample 059 * ●形式:<og:topMenu /> 060 * ●body:なし 061 * 062 * ●Tag定義: 063 * <og:topMenu 064 * menuType 【TAG】作成するメニューの種類(NORMAL,GROUP,ONELEVEL,NEXTGUI,MATRIX,MATRIX2,NONE,TILE)を指定します(初期値:NORMAL) 065 * expand 【TAG】折り返しメニューを構築するかどうかを指定します(初期値:true) 066 * groups 【TAG】表示対象となるグループをCSV形式で指定します 067 * classify 【TAG】表示対象となる分類(classify)を指定します 068 * href 【TAG】グループメニューの表示対象となるソース名(href)を指定します(初期値:menu.jsp) 069 * target 【TAG】グループメニューの表示対象となるフレーム名(target)を指定します(初期値:MENU) 070 * imageOnly 【TAG】グループメニューの表示に、画像のみかどうか[true:画像のみ/false:画像+ラベル]を指定します(初期値:false) 071 * sideCount 【TAG】グループメニューの表示対象となるメニューを横並びさせる数を指定します 072 * minCellCount 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最小行数を指定します(初期値:8) 073 * maxCellCount 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最大行数を指定します(初期値:8) 074 * cache 【TAG】グループメニューのキャッシュを使用するかどうか[true/false]を指定します(初期値:true) 075 * match 【TAG】正判定(マッチする場合に、メニューに出す)条件を設定します 076 * unmatch 【TAG】逆判定(マッチする場合に、メニューに出さない)条件を設定します 077 * useButton 【TAG】画面リンクにボタンを使用するかどうか[true/false]を指定します(初期値:false) 078 * buttonRequest 【TAG】マトリクスからの遷移先でボタンメニュー表示するかどうか[true/false]を指定します(初期値:false) 079 * inlineStyle 【TAG】標準画面を初期状態で表示するかどうか[true/false]を指定します(初期値:false) 080 * useDivOneLevel 【TAG】ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうか[true/false]を指定します(初期値:false) 081 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 082 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 083 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 084 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 085 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 086 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 087 * > ... Body ... 088 * </og:topMenu> 089 * 090 * ●使用例 091 * <og:topMenu /> 092 * 093 * <og:topMenu 094 * menuType = "NORMAL" NORMAL:通常 / GROUP:グループメニュー / ONELEVEL:1レベル / NEXTGUI:次アクセス先 095 * / MATRIX:一覧表メニュー / MATRIX2:一覧表メニュー(大分類なし版) / NONE:表示しない / TILE:タイル表示 096 * expand = "true" true:折り返しメニュー / false:階層メニュー 097 * groups = "AA,BB,CC" 表示対象となるグループをCSV形式で指定します。 098 * classify = "ABC" 表示対象となる分類を指定します。 099 * href = "menu.jsp" グループメニューの対象ソース名(href)を指定します。 100 * target = "MENU" グループメニューの対象フレーム名(target)を指定します。 101 * imageOnly = "false" グループメニューに、 true:画像のみ / false:画像+ラベル を指定します。 102 * sideCount = "6" グループメニューの表示対象となるメニューを横並びさせる数を指定します。 103 * minCellCount = "8" 表形式メニューの1セルの最小行数を指定します。 104 * maxCellCount = "8" 表形式メニューの1セルの最大行数を指定します。 105 * cache = "true" グループメニューのキャッシュを使用するかどうか指定します。 106 * match = "正規表現" 正判定(マッチする場合に、メニューに出す)条件を設定します。 107 * unmatch = "正規表現" 逆判定(マッチする場合に、メニューに出さない)条件を設定します。 108 * useButton = "false" ボタン形式のリンクを使用するかを指定します。 109 * useDivOneLevel = "false" ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。 110 * /> 111 * 112 * @og.rev 3.5.5.3 (2004/04/09) 新規作成 113 * @og.group メニュー制御 114 * 115 * @version 4.0 116 * @author Kohei Naruse 117 * @since JDK5.0, 118 */ 119public class TopMenuTag extends CommonTagSupport { 120 /** このプログラムのVERSION文字列を設定します。 {@value} */ 121 private static final String VERSION = "7.2.9.4 (2020/11/20)" ; 122 private static final long serialVersionUID = 729420201120L ; 123 124 private static final String FIELD_IN = "<fieldset style=\"display:inline;\">"; 125 private static final String FIELD_OUT = "</fieldset>" + BR; 126// private static final String JSP = HybsSystem.sys( "JSP" ); 127// private static final String CNTX = HybsSystem.sys( "CONTEXT_NAME" ); // 5.5.4.2 (2012/07/13) META-INF/resources 対応 128 private static final String MENU_IMG = "/jsp/menuImage/" ; // 5.5.4.2 (2012/07/13) META-INF/resources 対応 129 130 // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 131// private boolean multiSessionCheck = HybsSystem.sysBool( "USE_MULTI_SESSION_CHECK" ); 132 133 // 6.7.5.0 (2017/03/10) TILE表示追加 134 private static final Set<String> MENU_TYPE_SET = new ArraySet<>( "NORMAL","GROUP","ONELEVEL","NEXTGUI","MATRIX","MATRIX2","NONE","TILE" ); 135 136 private String menuType = "NORMAL" ; // NORMAL,GROUP,ONELEVEL,NEXTGUI,MATRIX,MATRIX2,NONE,TILE 137 private boolean expand = true; // true:折り返しメニュー / false:階層メニュー 138 private String[] groups ; // 表示対象となるグループをCSV形式で指定します。 139 private String selClassify; // 表示対象となる分類を指定します。 140 private String href = "menu.jsp"; // グループメニューの対象ソース名(href)を指定します。 141 private String target = "MENU"; // グループメニューの対象フレーム名(target)を指定します。 142 private boolean imageOnly ; // グループメニューに、 true:画像のみ / false:画像+ラベル を指定します 143 private int sideCount = -1; // 5.2.3.0 (2010/12/01) 表示対象となるメニューを横並びさせる数を指定します。 144 private int minCellCount = 8; // 表形式メニューの1セルの最小行数を指定します。 145 private int maxCellCount = 8; // 表形式メニューの1セルの最大行数を指定します。 146 private boolean cache = true; // グループメニューのキャッシュを使用するかどうか指定します。 147 // 3.8.8.7 (2007/05/01) メニューの表示条件指定追加 148 private String match ; // 正判定(マッチする場合に、メニューに出す)条件を設定 149 private String unmatch ; // 逆判定(マッチする場合に、メニューに出さない)条件を設定 150 private String imageDir = MENU_IMG; // 6.7.5.0 (2017/03/10) TILE表示追加 151 152 private final transient FileMap imgFileMap = new FileMap() ; // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。 153 154 private final String JSP = HybsSystem.sys( "JSP" ); // 6.9.9.3 (2018/09/25) JavaDoc エラー対応 155 156 // MULTI_SESSION_CHECK 時のリンクに付加する情報 157 private String mscKey ; 158 159 private boolean useButton ; // ボタン形式のリンクを使用するか 4.2.1.0 (2008/04/01) 160 private boolean buttonRequest ; // マトリクス2からの遷移でボタン形式にするかのリクエスト変数 4.2.1.0 (2008/04/17) 161 private boolean excludeButton ; // 4.3.3.0 (2008/10/01) ボタンメニューの場合でも強制的に従来のプルダウンにします。 162 private boolean inlineStyle ; // 4.3.3.0 (2008/10/01) trueでLv3の画面にstyle属性でinlineを付加 163 164 private boolean useDivOneLevel ; // 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。 165 166 /** 167 * デフォルトコンストラクター 168 * 169 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 170 */ 171 public TopMenuTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 172 173 /** 174 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 175 * 176 * @og.rev 4.0.0.0 (2007/10/31) 1レベルメニューの見直し 177 * @og.rev 4.2.1.0 (2008/04/01) マトリクスメニュー2追加 178 * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加 179 * @og.rev 5.3.0.0 (2010/11/22) NEXTGUI もマルチセッションチェックをしない。 180 * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応 181 * @og.rev 5.5.0.4 (2012/03/12) FAQ表示対応 182 * @og.rev 5.5.2.5 (2012/05/21) FAQ対応 廃止 183 * @og.rev 5.5.4.2 (2012/07/13) META-INF/resources からの読み取り対応 184 * @og.rev 6.3.8.3 (2015/10/03) NONE(表示しない) 追加。 185 * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。 186 * @og.rev 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。 187 * @og.rev 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。 188 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加) 189 * @og.rev 6.9.4.0 (2018/04/02) caseKey 、caseVal 属性対応 190 * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 191 * @og.rev 6.9.5.0 (2018/04/23) 6.9.9.3 (2018/09/25) JavaDoc エラー対応 192 * 193 * @return 後続処理の指示 194 */ 195 @Override 196 public int doEndTag() { 197 debugPrint(); // 4.0.0 (2005/02/28) 198 if( useTag() ) { // 6.9.4.0 (2018/04/02) caseKey 、caseVal 属性対応 199 200 // 6.3.8.3 (2015/10/03) NONE(表示しない) 追加。 201 if( "NONE".equals( menuType ) ) { return EVAL_PAGE; } 202 203 // Ver 4.0.0 2007/09/04 204 // ONELEVEL, NEXTGUI の場合は、multiSessionCheck を行いません。 205// if( multiSessionCheck && !"ONELEVEL".equals( menuType ) && !"NEXTGUI".equals( menuType ) ) { 206 if( !"ONELEVEL".equals( menuType ) && !"NEXTGUI".equals( menuType ) ) { // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 207 final String cnt = (String)getSessionAttribute( HybsSystem.MULTI_SESSION_CHECK ); 208 if( cnt == null ) { 209 final String errMsg = "マルチセッションチェックのキーが存在しません。" 210 + "topMenu タグを実行する前に、必ず jspInit タグを" 211 + "実行しておいてください。" ; 212 jspPrint( errMsg ); 213 return SKIP_PAGE ; // ページの残りの処理を行わない。 214 } 215 mscKey = HybsSystem.MULTI_SESSION_CHECK + "=" + cnt ; 216 } 217 218 // 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加) 219 final Set<?> set = pageContext.getServletContext().getResourcePaths( imageDir ); 220 // 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。 221 // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。 222// imgFileMap.init( imageDir , "/" + CNTX + imageDir , set ); 223 imgFileMap.init( imageDir , "/" + HybsSystem.getContextName() + imageDir , set ); // 6.9.9.3 (2018/09/25) JavaDoc エラー対応 224 225 if( "NORMAL".equals( menuType ) ) { 226 jspPrint( "<div class=\"forpos\" id=\"dummy\"></div>" + CR ); 227 if( ! useButton ){ // 4.2.1.0 (2008/04/26) ボタン時にはお気に入りを出さない 228 jspPrint( makeFavoriteMenu() ); 229 } 230 jspPrint( makeMenu() ); 231 } 232 else if( "GROUP".equals( menuType ) ) { 233 jspPrint( makeGroupMenu() ); 234 } 235 // else if( "CLASSIFY".equals( menuType ) ) { 236 // jspPrint( makeClassifyMenu() ); 237 // } 238 else if( "ONELEVEL".equals( menuType ) && selClassify != null ) { 239 jspPrint( makeOneLevelMenu() ); 240 } 241 // 5.2.3.0 (2010/12/01) NEXTGUI 追加 242 else if( "NEXTGUI".equals( menuType ) ) { 243 jspPrint( makeNextguiMenu() ); 244 } 245 else if( "MATRIX".equals( menuType ) ) { 246 jspPrint( makeMatrixMenu() ); 247 } 248 else if( "MATRIX2".equals( menuType ) ) { // 4.2.1.0 (2008/04/01) 大分類なし版追加 249 jspPrint( makeMatrixMenu2() ); 250 } 251 else if( "TILE".equals( menuType ) ) { // 6.7.5.0 (2017/03/10) TILE表示追加 252 jspPrint( makeTileMenu() ); 253 } 254 // else { 255 // jspPrint( "menuType が想定外です。menuType=[" + menuType + "]" ); 256 // } 257 } 258 259 return EVAL_PAGE ; // ページの残りを評価する。 260 } 261 262 /** 263 * タグリブオブジェクトをリリースします。 264 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 265 * 266 * @og.rev 5.2.3.0 (2010/12/01) sideCountの初期値を -1(無制限)に変更 267 * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応 268 * @og.rev 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。 269 * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。 270 * @og.rev 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。 271 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加) 272 * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 273 */ 274 @Override 275 protected void release2() { 276 super.release2(); 277 expand = true; 278 menuType = "NORMAL"; 279 groups = null; 280 selClassify = null; 281// multiSessionCheck = HybsSystem.sysBool( "USE_MULTI_SESSION_CHECK" ); 282 href = "menu.jsp"; // グループメニューの対象ソース名(href)を指定します。 283 imageOnly = false; // グループメニューに、 true:画像のみ / false:画像+ラベル を指定します 284 target = "MENU"; // グループメニューの対象フレーム名(target)を指定します。 285 sideCount = -1; // 5.2.3.0 (2010/12/01) 表示対象となるメニューを横並びさせる数を指定します。 286 minCellCount = 8; // 表形式メニューの1セルの最小行数を指定します。 287 maxCellCount = 8; // 表形式メニューの1セルの最大行数を指定します。 288 mscKey = null; // MULTI_SESSION_CHECK 時のリンクに付加する情報 289 imgFileMap.clear(); // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。 290 cache = true; // グループメニューのキャッシュを使用するかどうか指定します。 291 match = null; // 正判定(マッチする場合に、メニューに出す)条件を設定 292 unmatch = null; // 逆判定(マッチする場合に、メニューに出さない)条件を設定 293 imageDir = MENU_IMG; // 6.7.5.0 (2017/03/10) TILE表示追加 294 useButton = false; // ボタン形式のリンクを使用するか 295 buttonRequest = false; // trueでボタンメニューの表示を行う 296 excludeButton = false; // trueでボタンメニュー時でも強制的に従来のプルダウンにする。 297 inlineStyle = false; // trueの場合は標準画面(Lv3)にdisplay:inlineを付加 298 useDivOneLevel = false; // 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。 299 } 300 301 /** 302 * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。 303 * 304 * @og.rev 3.5.6.5 (2004/08/09) GUIInfo の comments 属性を title にセットする。 305 * @og.rev 3.6.0.9 (2004/12/03) リアルアドレス設定時に、{@XXXX}処理を追加 306 * @og.rev 3.8.0.0 (2005/06/07) 同一セッションでのマルチ起動対策を行います。 307 * @og.rev 4.0.0.0 (2005/01/31) GUIInfoの実アドレスのパラメータを考慮する。 308 * @og.rev 4.0.0.0 (2007/10/31) 分類の廃止に伴い、全面見直し 309 * @og.rev 4.2.1.0 (2008/04/01) 小分類指定での表示対応(↑の対応での再実装漏れ) 310 * @og.rev 4.2.1.0 (2008/04/11) 小分類をexpandしない場合にはspanタグで囲う。 311 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 312 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定 313 * 314 * @return メニュー 315 * @og.rtnNotNull 316 */ 317 private String makeMenu() { 318 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 319 320 final UserInfo userInfo = getUser(); 321 322 // 4.0.0 (2005/01/31) 323 324 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 325// String gamenId ; // 画面ID 326 int menuNo = 11; 327 int kmokuNo = 0; 328 329 boolean isInFieldset = false; // 大分類の中か? 330 boolean isInClassify = false; // 小分類の中か? 331 boolean isHiddenMenu = false; // 隠しメニューが存在するか? 6.0.2.5 (2014/10/31) refactoring 332 boolean isClassHidden = false; // 分類隠しが存在するか? 6.0.2.5 (2014/10/31) refactoring 333 int level ; 334 int preLevel = 0; 335 336 for( int i=0; i<guiInfos.length; i++ ) { 337 if( guiInfos[i].isRead() ) { // 4.0.0 (2005/01/31) 338 final String gamenId = guiInfos[i].getKey() ; 339 340// if( match != null && !gamenId.matches( match ) ) { continue; } 341// if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 342 // 6.9.7.0 (2018/05/14) PMD 343 if( match != null && !gamenId.matches( match ) 344 || unmatch != null && gamenId.matches( unmatch ) ) { continue; } 345 346 // 4.2.1.0 (2008/04/01) 347 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 348// if( selClassify != null ) { 349//// if( !selClassify.equals( guiInfos[i].getKey() ) && !selClassify.equals( guiInfos[i].getClassify() ) ) { 350// if( !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) { 351 if( selClassify != null && !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) { 352 continue; // 分類(classify) に含まれない 353// } 354 } 355 356 // 処理すべき画面かのチェック 357 final int guiFlg = guiCheck( guiInfos, i ); 358 if( guiFlg == 0 ) { continue; } 359 360 level = guiInfos[i].getLevel(); // 4.0.0 (2005/01/31) 361 362 // 隠しメニュー展開用 363 if( preLevel >= 3 && level < 3 ) { 364 if( isHiddenMenu ) { // 6.0.2.5 (2014/10/31) refactoring 365 rtn.append( makeEllipses( menuNo,kmokuNo,3 ) ); 366 kmokuNo++; 367 } 368 isHiddenMenu = false; // 6.0.2.5 (2014/10/31) refactoring 369 } 370 371 // 大分類(フィールドメニュー) 372 if( level == 1 ) { 373 if( isInFieldset ) { 374 rtn.append( FIELD_OUT ) 375 .append( "</div>" ); 376 } 377 isInFieldset = true; 378 379 // 隠しメニュー用 380 if( expand ) { 381 rtn.append( "<div class=\"expand1 " ); 382 383 if( guiFlg == 1 ) { 384 rtn.append( "unpopular "); 385 } 386 387 rtn.append( "\">" ); 388 } 389 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 390 391 isInClassify = false; 392 } 393 // 小分類・直リンク 394 else if( level == 2 ) { 395 menuNo++; 396 kmokuNo = 0; 397 if( expand ) { 398 rtn.append( "<div class=\"expand1 " ); 399 400 // 隠しメニュー用 401 if( guiFlg == 1 ) { 402 rtn.append( "unpopular " ); 403 isClassHidden = true; // 6.0.2.5 (2014/10/31) refactoring 404 } 405 406 // rtn.append( "\" id=\"menu" + menuNo + "\">" ); 407 // 4.3.3.0 (2008/10/01) useButton=true時は表示しない 408 rtn.append( "\" id=\"menu" + menuNo + "\" "); 409 if( useButton ){ 410 rtn.append( "style=\"display:none\""); 411 } 412 rtn.append( '>'); // 6.0.2.5 (2014/10/31) char を append する。 413 } 414 else{ // 4.2.1.0 (2008/04/11)expandしない場合にはspan要素で囲ってnon-expandクラスを指定。 415 rtn.append( "<span class=\"non-expand\">" ); 416 } 417 418 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 419 rtn.append( BR ); 420 if( expand ) { 421 rtn.append( "</div>" ); 422 } 423 else{ // 4.2.1.0 (2008/04/11) 424 rtn.append( "</span>"); 425 } 426 427 isInClassify = true; 428 } 429 // 通常メニュー・隠しメニュー 430 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 431// else if( level >= 3 ) { 432// if( isInClassify ) { 433 else if( level >= 3 && isInClassify ) { 434 if( expand ) { 435 rtn.append( "<div class=\"expand2 " ); 436 437 // 隠しメニュー用 438 if( level == 4 ) { 439 rtn.append( "unpopular " ); 440 isHiddenMenu = true; // 6.0.2.5 (2014/10/31) refactoring 441 } 442 443 // rtn.append( "\" id=\"menu" + menuNo + "_" + kmokuNo + "\">" ); 444 // 4.3.3.0 (2008/10/01) メニューを初期状態で開けるようにする 445 // 6.0.2.5 (2014/10/31) char を append する。 446 rtn.append( "\" id=\"menu" ).append( menuNo ).append( '_' ).append( kmokuNo ).append( "\" " ); 447 if( inlineStyle && level == 3 ) { 448 rtn.append( " style=\"display:inline\"" ); 449 } 450 rtn.append( '>' ); // 6.0.2.5 (2014/10/31) char を append する。 451 } 452 // // 6.9.4.1 (2018/04/09) HYBS_BR 対応 453 // if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) { 454 // rtn.append( BR ); 455 // } 456 // else { 457// // // 画面IDが"HYBS_BR"の時は処理しない 458// // if( !"HYBS_BR".equals( guiInfos[i].getKey() ) ) { 459 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 460 // } 461 rtn.append( BR ); 462 if( expand ) { 463 rtn.append( "</div>" ); 464 } 465 kmokuNo++; 466// } 467 } 468 469 rtn.append( CR ); 470 471 preLevel = level; 472 } 473 } 474 475 // 終了処理 476 if( isHiddenMenu ) { // 6.0.2.5 (2014/10/31) refactoring 477 rtn.append( makeEllipses( menuNo,kmokuNo,3 ) ); 478 } 479 480 if( isInFieldset ) { 481 rtn.append( FIELD_OUT ); 482 rtn.append( "</div>" ); 483 } 484 485 if( isClassHidden ) { // 6.0.2.5 (2014/10/31) refactoring 486 rtn.append( makeEllipses( menuNo,0,2 ) ); 487 } 488 489 return rtn.toString(); 490 } 491 492 /** 493 * TILEメニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。 494 * 495 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加 496 * @og.rev 6.9.4.0 (2018/04/02) HYBS_BR(ブレイク)の条件を緩める。 497 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定 498 * 499 * @return メニュー 500 * @og.rtnNotNull 501 */ 502 private String makeTileMenu() { 503 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 504 505 final UserInfo userInfo = getUser(); 506 507 // 4.0.0 (2005/01/31) 508 509 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 510// String gamenId ; // 画面ID 511 int menuNo = 11; 512 int kmokuNo = 0; 513 514 boolean isInFieldset = false; // 大分類の中か? 515 boolean isInClassify = false; // 小分類の中か? 516 boolean isHiddenMenu = false; // 隠しメニューが存在するか? 6.0.2.5 (2014/10/31) refactoring 517 boolean isClassHidden = false; // 分類隠しが存在するか? 6.0.2.5 (2014/10/31) refactoring 518 int level ; 519 int preLevel = 0; 520 521 String hybsBR = ""; // 6.7.5.0 (2017/03/10) 522 for( int i=0; i<guiInfos.length; i++ ) { 523 if( guiInfos[i].isRead() ) { // 4.0.0 (2005/01/31) 524 final String gamenId = guiInfos[i].getKey() ; 525 if( match != null && !gamenId.matches( match ) ) { continue; } 526 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 527 528 // 4.2.1.0 (2008/04/01) 529 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 530// if( selClassify != null ) { 531// if( !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) { 532 if( selClassify != null && !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) { 533 continue; // 分類(classify) に含まれない 534// } 535 } 536 537 // 6.9.4.0 (2018/04/02) HYBS_BR(ブレイク)の条件を緩める。 538 if( isInFieldset && isInClassify && "HYBS_BR".equals( guiInfos[i].getAddress() ) ) { // 6.7.5.0 (2017/03/10) 539// if( "HYBS_BR".equals( gamenId ) ) { // 6.9.4.0 (2018/04/02) 540 hybsBR = "</tr><tr>" ; 541 } 542 543 // 処理すべき画面かのチェック 544 final int guiFlg = guiCheck( guiInfos, i ); 545 if( guiFlg == 0 ) { continue; } 546 547 level = guiInfos[i].getLevel(); // 4.0.0 (2005/01/31) 548 549 // 隠しメニュー展開用 550 if( preLevel >= 3 && level < 3 ) { 551 if( isHiddenMenu ) { // 6.0.2.5 (2014/10/31) refactoring 552 rtn.append( makeEllipses( menuNo,kmokuNo,3 ) ); 553 kmokuNo++; 554 } 555 isHiddenMenu = false; // 6.0.2.5 (2014/10/31) refactoring 556 } 557 558 // 大分類(フィールドメニュー) 559 if( level == 1 ) { 560 if( isInFieldset ) { 561 rtn.append( "</td></tr></table>" ) // 6.7.5.0 (2017/03/10) 562 .append( FIELD_OUT ) 563 .append( "</div>" ); 564 } 565 isInFieldset = true; 566 567 // 隠しメニュー用 568 if( expand ) { 569 rtn.append( "<div class=\"expand1 " ); 570 571 if( guiFlg == 1 ) { 572 rtn.append( "unpopular "); 573 } 574 rtn.append( "\">" ); 575 } 576 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) ) // 5.5.2.5 (2012/05/21) イメージアイコン対応 577 .append( "<table><tr>" ); // 6.7.5.0 (2017/03/10) 578 579 isInClassify = false; 580 } 581 // 小分類・直リンク 582 else if( level == 2 ) { 583 menuNo++; 584 kmokuNo = 0; 585 if( expand ) { 586 if( isInFieldset ) { // 6.7.5.0 (2017/03/10) 587 if( isInClassify ) { 588 rtn.append( "</td>" ).append( hybsBR ).append( "<td>" ); 589 hybsBR = ""; 590 } 591 else { 592 rtn.append( "<td>" ); 593 } 594 } 595 rtn.append( "<div class=\"expand1 " ); 596 597 // 隠しメニュー用 598 if( guiFlg == 1 ) { 599 rtn.append( "unpopular " ); 600 isClassHidden = true; // 6.0.2.5 (2014/10/31) refactoring 601 } 602 603 // rtn.append( "\" id=\"menu" + menuNo + "\">" ); 604 // 4.3.3.0 (2008/10/01) useButton=true時は表示しない 605 rtn.append( "\" id=\"menu" + menuNo + "\" "); 606 if( useButton ){ 607 rtn.append( "style=\"display:none\""); 608 } 609 rtn.append( '>'); // 6.0.2.5 (2014/10/31) char を append する。 610 } 611 else{ // 4.2.1.0 (2008/04/11)expandしない場合にはspan要素で囲ってnon-expandクラスを指定。 612 rtn.append( "<span class=\"non-expand\">" ); 613 } 614 615 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-6 ) ); // 6.7.5.0 (2017/03/10) TILE表示 616 rtn.append( BR ); 617 if( expand ) { 618 rtn.append( "</div>" ); 619 } 620 else{ // 4.2.1.0 (2008/04/11) 621 rtn.append( "</span>"); 622 } 623 624 isInClassify = true; 625 } 626 // 通常メニュー・隠しメニュー 627 // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined 628// else if( level >= 3 ) { 629// if( isInClassify ) { 630 else if( level >= 3 && isInClassify ) { 631 if( expand ) { 632 rtn.append( "<div class=\"expand2 " ); 633 634 // 隠しメニュー用 635 if( level == 4 ) { 636 rtn.append( "unpopular " ); 637 isHiddenMenu = true; // 6.0.2.5 (2014/10/31) refactoring 638 } 639 640 // rtn.append( "\" id=\"menu" + menuNo + "_" + kmokuNo + "\">" ); 641 // 4.3.3.0 (2008/10/01) メニューを初期状態で開けるようにする 642 // 6.0.2.5 (2014/10/31) char を append する。 643 rtn.append( "\" id=\"menu" ).append( menuNo ).append( '_' ).append( kmokuNo ).append( "\" " ); 644 if( inlineStyle && level == 3 ) { 645 rtn.append( " style=\"display:inline\"" ); 646 } 647 rtn.append( '>' ); // 6.0.2.5 (2014/10/31) char を append する。 648 } 649 650 // // 6.9.4.1 (2018/04/09) HYBS_BR 対応 651 // if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) { // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定 652 // rtn.append( BR ); 653 // } 654 // else { 655// // // 画面IDが"HYBS_BR"の時は処理しない 656// // if( !"HYBS_BR".equals( gamenId ) ) { 657 rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 658 // } 659 rtn.append( BR ); 660 if( expand ) { 661 rtn.append( "</div>" ); 662 } 663 kmokuNo++; 664// } 665 } 666 667 rtn.append( CR ); 668 preLevel = level; 669 } 670 } 671 672 // 終了処理 673 if( isHiddenMenu ) { // 6.0.2.5 (2014/10/31) refactoring 674 rtn.append( makeEllipses( menuNo,kmokuNo,3 ) ); 675 } 676 677 if( isInFieldset ) { 678 rtn.append( "</td></tr></table>" ) // 6.7.5.0 (2017/03/10) 679 .append( FIELD_OUT ) 680 .append( "</div>" ); 681 } 682 683 if( isClassHidden ) { // 6.0.2.5 (2014/10/31) refactoring 684 rtn.append( makeEllipses( menuNo,0,2 ) ); 685 } 686 687 return rtn.toString(); 688 } 689 690 /** 691 * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。 692 * 693 * @og.rev 4.0.0.0 (2005/01/31) 個人別のお気に入りメニューを作成します。 694 * @og.rev 4.0.0.0 (2007/10/31) 分類項目の廃止 695 * @og.rev 4.1.1.0 (2008/02/05) お気に入り情報はGEA09から取得するように変更 696 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 697 * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。 698 * @og.rev 6.9.9.1 (2018/08/27) お気に入り編集メニュー(GE0014→GFX000)変更。 699 * 700 * @return 個人別のお気に入りメニュー 701 * @og.rtnNotNull 702 */ 703 private String makeFavoriteMenu() { 704 705 final UserInfo userInfo = getUser(); 706 final Map<String,FavoriteGUIData> favoriteMap = userInfo.getFavoriteMap(); 707 708 if( favoriteMap.isEmpty() ) { return ""; } 709 710 final ResourceManager resource = getResource(); // リソース参照 711 final String largeClassify = resource.getLabelData( "FAVORITE_MENU" ).getShortLabel(); // お気に入り 712 String lastClassify = ""; // 前方画面の分類 713 int menuNo = 99999; 714 int kmokuNo = 0; 715 716 // fieldSetタグ、お気に入り編集画面リンクの出力 717// final GUIInfo editFavorite = userInfo.getGUIInfo( "GE0014" ); 718 final GUIInfo editFavorite = userInfo.getGUIInfo( "GFX000" ); // 6.9.9.1 (2018/08/27) 719 720 final OgBuilder rtn = new OgBuilder() 721 .append( "<div class=\"expand1\"> " 722 , makeTagMenuString( null,null,largeClassify,null,1 ) 723 , makeTagMenu( editFavorite,resource.getLabelData( "EDIT" ).getShortLabel(),2 ) // 5.5.2.5 (2012/05/21) イメージアイコン対応 724 , BR ); 725 726 String thisClassify = null; 727// String gamenId = null; 728 FavoriteGUIData favoriteGui = null; 729 // 4.3.4.4 (2009/01/01) findBugs警告対応 730 for( final Map.Entry<String, FavoriteGUIData> entry : favoriteMap.entrySet() ) { 731 final String gamenId = entry.getKey(); 732 favoriteGui = entry.getValue(); 733 final GUIInfo guiInfo = userInfo.getGUIInfo( gamenId ); 734 735 if( match != null && !gamenId.matches( match ) ) { continue; } 736 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 737 738 thisClassify = favoriteGui.getClassify(); 739 if( !lastClassify.equals( thisClassify ) ) { 740 menuNo++; 741 kmokuNo = 0; 742 rtn.appendIf( expand , "<div class=\"expand1\" id=\"menu" , String.valueOf( menuNo ) , "\">" ) 743 .append( makeTagMenuString( null,null,thisClassify,thisClassify,2 ) ) 744 .append( BR ) 745 .appendIfCR( expand , "</div>" ); 746 lastClassify = thisClassify; 747 } 748 749 final String linkLabel = favoriteGui.getName(); 750 rtn.appendIf( expand 751 , "<div class=\"expand2\" id=\"menu" 752 , String.valueOf( menuNo ) , "_" , String.valueOf( kmokuNo ) , "\">" ) 753 .append( makeTagMenu( guiInfo,linkLabel,3 ) ) // 5.5.2.5 (2012/05/21) イメージアイコン対応 754 .append( BR ) 755 .appendIfCR( expand , "</div>" ); 756 kmokuNo++; 757 } 758 return rtn.append( FIELD_OUT , "</div>" ).toString(); 759 } 760 761 /** 762 * 折りたたみメニューで、非標準メニューの 表示に使う、"←・・・→" を作成します。 763 * 764 * @param menuNo 階層番号 765 * @param kmokuNo 階層項目番号 766 * @param type タイプ(1,2限定) 767 * 768 * @og.rev 4.0.0.0 (2005/01/31) 新規作成 769 * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。 770 * 771 * @return メニュー 772 * @og.rtnNotNull 773 */ 774 private String makeEllipses( final int menuNo,final int kmokuNo,final int type ) { 775 final int tmpType = type-1; // 超暫定対応 4.0.0.0 (2007/10/31) 776 final String kmkNo = ( tmpType == 1 ) ? "" : "_" + kmokuNo ; 777 778 // 4.3.3.0 (2008/10/01) inlineStyleがtrueの場合は←・・・→をinlineで表示する 779 return new OgBuilder() 780 .append( "<div class=\"expand" , String.valueOf( tmpType ) ) 781 .append( " ellipses\" id=\"menu" , String.valueOf( menuNo ) , kmkNo ) 782 .append( "\" " ) 783 .appendIf( inlineStyle , "style=\"display:inline\" " ) // if 784 .appendCR( ">" , makeTagMenuString( null,null,"←・・・→",null,type ) 785 , BR , "</div>" ) 786 .toString(); 787 } 788 789 /** 790 * menuType="GROUP" 時に作成するグループメニュー。 791 * 792 * @og.rev 4.0.0.0 (2005/01/31) 新規作成 793 * @og.rev 4.0.0.0 (2007/10/05) グループのコードリソースが存在しない場合 794 * @og.rev 4.2.2.0 (2008/05/14) buttonRequestがtrueの場合はTOPへのリンクを表示しない 795 * @og.rev 4.2.2.0 (2008/05/15) グループ絞込解除(GUI_ALL)の表示文字にラベルリソースを使う。 796 * @og.rev 5.0.0.3 (2009/09/22) グループが1件の場合に表示されないバグを修正 797 * @og.rev 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正 798 * @og.rev 5.9.7.1 (2016/04/06) GROPUにgroupsが効くようにする 799 * @og.rev 6.4.5.0 (2016/04/08) GROPUにgroupsが効くようにする(効率化、ループから出す) 800 * @og.rev 6.8.3.1 (2017/12/01) GROPUの表示順を、コードリソースの並び順にします。 801 * @og.rev 5.10.15.2 (2019/09/20) GROUPのマルチバイト文字対応 802 * 803 * @return メニュー 804 */ 805 private String makeGroupMenu() { 806 807 // 画面のグループメニューのキャッシュを取得します。 808 String groupMenu ; 809 final String cacheKey = HybsSystem.GUI_GR_MENU_CACHE_KEY + href + target ; 810 if( cache ) { 811 groupMenu = (String)getSessionAttribute( cacheKey ); 812 if( groupMenu != null ) { return groupMenu; } // キャッシュを返します。 813 } 814 else { 815 removeSessionAttribute( cacheKey ); 816 } 817 818 final UserInfo userInfo = getUser(); 819 820 // 6.8.3.1 (2017/12/01) GROPUの表示順を、コードリソースの並び順にします。 821 final CodeData groupCode = getResource().getCodeData( "GROUPS" ) ; 822 final Set<String> groupSet = groupCode == null ? new LinkedHashSet<>() // 要素がセットに挿入された順序です(挿入順)。 823 : new TreeSet<>( (v1,v2) -> groupCode.getAddress( v1 ) - groupCode.getAddress( v2 ) ); // コードリソースの並び順 824 825 // そのユーザーで使用できる画面をすべてピックアップします。 826 // その上で、読取可能なメニューを含むグループを順番に Set にセットしていきます。 827 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 828 829 // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop 830 for( final GUIInfo guiInfo : guiInfos ) { 831 if( guiInfo.isRead() ) { 832// for( int i=0; i<guiInfos.length; i++ ) { 833// if( guiInfos[i].isRead() ) { 834 final String gamenId = guiInfo.getKey() ; 835// final String gamenId = guiInfos[i].getKey() ; 836 if( match != null && !gamenId.matches( match ) ) { continue; } 837 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 838 // 6.4.5.0 (2016/04/08) 元のループを、拡張for文に変更しただけ。 839 final String[] guiGroups = StringUtil.csv2Array( guiInfo.getGroups() ); 840// final String[] guiGroups = StringUtil.csv2Array( guiInfos[i].getGroups() ); 841 for( final String grp : guiGroups ) { groupSet.add( grp ); } 842 } 843 } 844 845 // 6.4.5.0 (2016/04/08) groupsの削除は、後でまとめて行う。 846 if( groups != null ) { 847 for( final String grp : groups ) { groupSet.remove( grp ); } 848 } 849 850 // 5.0.0.3 (2009/09/22) 851 // 6.1.1.0 (2015/01/17) refactoring 。size()判定をisEmpty() にすると同時に、if...else を反転する。 852 if( groupSet.isEmpty() ) { 853 groupMenu = ""; 854 } 855 else { 856 int sideTmpCnt = 1; 857 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 858 rtn.append( "<tr>" ); 859 860 final String allMenu = getLabel( "ALL_MENU" ); // 4.2.2.0 (2008/05/15) ALLはラベルリソース使うように変更 861 rtn.append( makeTagMenuString( href,target,allMenu,"GUI_ALL",-1 ) ); 862 if( sideCount > 0 && sideTmpCnt % sideCount == 0 ) { rtn.append("</tr><tr>"); } 863 sideTmpCnt++ ; 864 865 final Iterator<String> ite = groupSet.iterator() ; 866 if( groupCode != null ) { 867 while( ite.hasNext() ) { 868 final String group = ite.next(); 869 final int cdAdrs = groupCode.getAddress( group ) ; 870 // 4.0.0.0 (2007/10/05) グループのコードリソースが存在しない場合 871 String groupLabel = ""; 872 if( cdAdrs >= 0 ) { groupLabel = groupCode.getLongLabel( cdAdrs ); } 873 874 // 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正 875 if( groupLabel.isEmpty() && group != null && group.length() > 0 ) { 876 groupLabel = group; 877 } 878 879// final String src = XHTMLTag.addUrlEncode( href,"group=" + group ); 880 final String src = XHTMLTag.addUrlEncode( href,"group=" + StringUtil.urlEncode( group ) ); // 5.10.15.2 (2019/09/20) 881 rtn.append( makeTagMenuString( src,target,groupLabel,group,-1 ) ); 882 if( sideCount > 0 && sideTmpCnt % sideCount == 0 ) { rtn.append("</tr><tr>"); } 883 sideTmpCnt++ ; 884 } 885 } 886 887 if( ! imageOnly && ! buttonRequest ) { // 4.2.2.0 (2008/05/14) ボタンメニュー時はトップメニュー 888 rtn.append( makeTagMenuString( JSP + "/index.jsp",target,"Top","GUI_TOP",-1 ) ); 889 } 890 rtn.append( "</tr>" ); 891 892 // 画面のグループメニューのキャッシュをセットします。 893 groupMenu = rtn.toString() ; 894 } 895 896 if( cache ) { 897 setSessionAttribute( cacheKey,groupMenu ); 898 } 899 900 return groupMenu; 901 } 902 903 /** 904 * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。 905 * 906 * @og.rev 4.0.0.0 (2005/01/31) GUIInfoの実アドレスのパラメータを考慮する。 907 * @og.rev 4.0.0.0 (2007/10/31) 一旦廃止 908 * @og.rev 5.5.2.3 (2012/05/15) useDivOneLevel 対応 909 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 910 * @og.rev 5.5.6.0 (2013/01/07) useDivOneLevelの折り返し方法変更 911 * @og.rev 6.2.6.0 (2015/06/19) QUERYに表示される1行メニュは、説明なしの画面名称のみ表示する。 912 * @og.rev 5.9.6.1 (2016/03/04) フレーム対応 913 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定 914 * 915 * @return メニュー 916 * @og.rtnNotNull 917 */ 918 private String makeOneLevelMenu() { 919 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 920 921 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 922 if( useDivOneLevel ) { rtn.append("<div id=\"design-onelevel\">"); } 923 924 final UserInfo userInfo = getUser(); 925 926 // 4.0.0 (2005/01/31) 927 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 928// String gamenId ; // 画面ID 929 int sideTmpCnt = 1; 930 931 boolean isInClassify = false; 932 933 // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop 934 for( final GUIInfo guiInfo : guiInfos ) { 935 final String gamenId = guiInfo.getKey() ; // 6.9.4.1 (2018/04/09) 936 final int level = guiInfo.getLevel(); 937// for( int i=0; i<guiInfos.length; i++ ) { 938// final String gamenId = guiInfos[i].getKey() ; // 6.9.4.1 (2018/04/09) 939// final int level = guiInfos[i].getLevel(); 940 941 if( level == 2 ) { 942// isInClassify = selClassify.equals( guiInfos[i].getKey() ); 943 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 944 // makeOneLevelMenu() メソッドが呼ばれる条件に、selClassify != null があるのだが。 945// isInClassify = selClassify.equals( gamenId ); 946 isInClassify = gamenId.equals( selClassify ); // 6.9.8.0 (2018/05/28) とりあえず比較方法を入れ替えます。 947 } 948 949 if( guiInfo.isRead() && level == 3 && isInClassify ) { // 4.0.0 (2005/01/31) 950// if( guiInfos[i].isRead() && level == 3 && isInClassify ) { // 4.0.0 (2005/01/31) 951// gamenId = guiInfos[i].getKey() ; 952 if( match != null && !gamenId.matches( match ) ) { continue; } 953 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 954 955 final String guiLabel = guiInfo.getLabel(); // 6.2.6.0 (2015/06/19) 画面名称(title無) 956// final String guiLabel = guiInfos[i].getLabel(); // 6.2.6.0 (2015/06/19) 画面名称(title無) 957 958 final String thisGamenId = getGUIInfoAttri( "KEY" ); 959 if( gamenId.equals( thisGamenId ) ) { 960 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 961 if( useDivOneLevel ) { 962 rtn.append("<span class=\"design-onelevel\">").append( guiLabel ).append( "</span>" ); 963 } 964 else { 965 rtn.append( '[' ).append( guiLabel ).append( "] " ); // 6.0.2.5 (2014/10/31) char を append する。 966 } 967 } 968 else { 969 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 970 if( useDivOneLevel ) { 971 // 5.5.2.5 (2012/05/21) イメージアイコン対応 972 rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfo,guiLabel,-5 ) ).append( "</span>" ); // 5.9.6.1 973// rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfos[i],guiLabel,-5 ) ).append( "</span>" ); // 5.9.6.1 974 } 975 else { 976 rtn.append( makeTagMenu( guiInfo,guiLabel,-2 ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 977// rtn.append( makeTagMenu( guiInfos[i],guiLabel,-2 ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 978 } 979 } 980 981 if( sideCount > 0 ) { 982 // 全件数をサイドカウント数で割った値が最大行数の場合は、終了する。 983 if( sideTmpCnt / sideCount >= maxCellCount ) { 984 // rtn.append("・・・"); 985 break; 986 } 987 // 全件数をサイドカウント数で割った余りがゼロの場合は、行ブレイクする。 988 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 989 if( sideTmpCnt % sideCount == 0 ) { 990 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 991 // 6.0.2.5 (2014/10/31) refactoring: findBugs対応。分岐もコメントアウトする。 992 // if( useDivOneLevel ) { 993 // rtn.append( BR ); // 5.6.0.0 (2013/01/07) BRにする(条件分岐は残しておく) 994 // // rtn.append("<span style=\"clear: both;\" />"); 995 // } 996 // else { 997 rtn.append( BR ); 998 // } 999 } 1000 sideTmpCnt++ ; 1001 } 1002 } 1003 } 1004 1005 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1006 if( useDivOneLevel ) { 1007 rtn.append("<span style=\"clear: both;\" ><!-- --></span></div>"); // 5.9.1.2 (2015/10/23) 1008 } 1009 1010 return rtn.toString(); 1011 } 1012 1013 /** 1014 * 既存のページの次にアクセスされる画面郡のリンクを作成します。 1015 * 1016 * これは、現時点の画面に対して、次にアクセスされる画面の候補を 1017 * ピックアップしておく機能です。 1018 * 実際には、過去にアクセスされた結果より取得しています。 1019 * これは、ONELEVEL と置き換えることになる機能です。 1020 * 1021 * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加 1022 * @og.rev 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1023 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 1024 * @og.rev 6.2.6.0 (2015/06/19) QUERYに表示される1行メニュは、説明なしの画面名称のみ表示する。 1025 * @og.rev 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。 1026 * @og.rev 5.9.6.1 (2016/03/04) フレーム対応 1027 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 1028 * 1029 * @return メニュー 1030 * @og.rtnNotNull 1031 */ 1032 private String makeNextguiMenu() { 1033 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 1034 1035 // 今、アクセスしている画面 1036 final GUIInfo thisGamen = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY ); 1037 final String[] nextGuis = thisGamen.getNextGuiArray(); 1038 1039 final UserInfo userInfo = getUser(); 1040 int sideTmpCnt = 1; 1041 1042 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1043 if( useDivOneLevel ) { rtn.append("<div id=\"design-onelevel\">"); } 1044 1045 GUIInfo guiInfo = null; 1046 // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop 1047 for( final String nxtGrp : nextGuis ) { 1048 guiInfo = userInfo.getGUIInfo( nxtGrp ); 1049// for( int i=0; i<nextGuis.length; i++ ) { 1050// guiInfo = userInfo.getGUIInfo( nextGuis[i] ); 1051 if( guiInfo == null ) { continue; } // 存在しない、またはアクセス拒否の場合は、無視する。 1052 1053 if( guiInfo.isRead() ) { 1054 final String guiLabel = guiInfo.getLabel(); // 6.2.6.0 (2015/06/19) 画面名称(title無) 1055 1056 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1057 if( useDivOneLevel ) { 1058 // 5.5.2.5 (2012/05/21) イメージアイコン対応 1059 rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfo,guiLabel,-5 ) ).append( "</span>" ); 1060 } 1061 else { 1062 rtn.append( makeTagMenu( guiInfo,guiLabel,-2 ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 1063 } 1064 1065 if( sideCount > 0 ) { 1066 // 全件数をサイドカウント数で割った値が最大行数の場合は、終了する。 1067 if( sideTmpCnt / sideCount >= maxCellCount ) { 1068 break; 1069 } 1070 // 全件数をサイドカウント数で割った余りがゼロの場合は、行ブレイクする。 1071 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1072 if( sideTmpCnt % sideCount == 0 ) { 1073 // 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。 1074 // if( useDivOneLevel ) { 1075 // rtn.append("<span style=\"clear: both;\" />"); 1076 // } 1077 // else { 1078 rtn.append( BR ); 1079 // } 1080 } 1081 sideTmpCnt++ ; 1082 } 1083 } 1084 } 1085 1086 // 5.5.2.3 (2012/05/15) useDivOneLevel 対応 1087 // 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。 1088 if( useDivOneLevel ) { 1089// rtn.append("<span style=\"clear: both;\" /></div>"); 1090 rtn.append("<span style=\"clear: both;\" ></span></div>"); // 7.0.1.0 (2018/10/15) 1091 } 1092 1093 return rtn.toString(); 1094 } 1095 1096 /** 1097 * メニューを表示する為のHTMLを作成します(マトリクスメニュー)。 1098 * 1099 * 分類まとめ、クラス色指定、最小行数設定、最大行数設定の機能があります。 1100 * 《分類まとめ》 最大行数設定(maxCellCount)に達したセルは、一つ右に新たにセルを作成 1101 * します。このとき、ヘッダーの CLASSIFY を同じにして、colspan でまとめます。 1102 * 《クラス色指定》ヘッダー毎に 順次 CLR0,CLR1,・・・・ というクラス属性を付与します。 1103 * ヘッダーには、MENU_H も出力されています。CLR0 は、大分類ごとに加算されていきますので、 1104 * 繰り返して同じ色を指定する場合は、CSSファイルでまとめて指定してください。 1105 * 《最小行数設定》minCellCount 属性を指定することで、1セルに含まれる最小行数を指定できます。 1106 * これは、セルに入れる <br /> の個数を指定することと同じです。 1107 * 《最大行数設定》maxCellCount 属性を指定することで、1セルに含まれる最大行数を指定できます。 1108 * 分類まとめでも説明しましたように、最大値をオーバーすると次のセルから書き始めます。 1109 * 1110 * @og.rev 4.0.0.0 (2005/11/30) 新規追加 1111 * @og.rev 4.0.0.0 (2007/10/05) 分類のコードリソースが存在しない場合 1112 * @og.rev 5.2.3.0 (2010/12/01) sideCount対応 1113 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 1114 * @og.rev 5.5.5.3 (2012/08/17) th,tdにヘッダの画面IDをクラスとして出力 1115 * @og.rev 6.8.2.3 (2017/11/10) minCellCountの数が、一つ足りない事の修正 1116 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定 1117 * 1118 * @return マトリクスメニュー 1119 * @og.rtnNotNull 1120 */ 1121 private String makeMatrixMenu() { 1122 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 1123 1124 final UserInfo userInfo = getUser(); 1125 1126 // 4.0.0 (2005/01/31) 1127 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 1128// String gamenId ; // 画面ID 1129 String bkClassifyKey = null; // 分類コード(旧) 1130 String bkClassifyName = null; // 分類名称(旧) 1131 int cellColorCnt = 0; // MENU_H に 追加する CLR クラス属性の連番 1132 1133 String headGuikey = ""; // 5.5.5.3 (2012/08/17) ヘッダのgamenId 1134 1135 final StringBuilder rtnH = new StringBuilder( BUFFER_LARGE ); 1136 final StringBuilder rtnB = new StringBuilder( BUFFER_LARGE ); 1137 1138 int level ; 1139 int preLevel = 0; 1140 1141 int lineTmpCnt = 0; // セル中の行カウント 1142 int cellTmpCnt = 0; // 1つの分類中のセルカウント 1143 int cellTmpAllCnt = 0; // 5.2.3.0 (2010/12/01) 該当行のセルカウント 1144 1145 boolean isInClassify = false; // 分類の中か? 1146 boolean isChangeLevel = false; // 直リンク用(無理やり通常画面の階層として扱うので) 1147 boolean isDummyMENU = false; // 5.2.3.0 (2010/12/01) sideCountブレーク時の大分類領域の出力可否 7.2.9.4 (2020/11/20) isDummyMENU_S → isDummyMENU 1148 1149 for( int i=0; i<guiInfos.length; i++ ) { 1150 if( guiInfos[i].isRead() ) { // 4.0.0 (2005/01/31) 1151 final String gamenId = guiInfos[i].getKey() ; 1152 if( match != null && !gamenId.matches( match ) ) { continue; } 1153 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 1154 1155 // 処理すべき画面かのチェック 1156 final int guiFlg = guiCheck( guiInfos, i ); 1157 if( guiFlg == 0 ) { continue; } 1158 1159 level = guiInfos[i].getLevel(); // 4.0.0 (2005/01/31) 1160 1161 // 大分類が来るまでは処理しない 1162 if( level > 1 && rtnH == null ) { continue; } 1163 1164 // 直リンクの場合、無理やり通常画面に変換 1165 if( level == 2 && guiInfos[i].getAddress() != null && guiInfos[i].getAddress().length() != 0 ) { 1166 level = 3; 1167 if( !isChangeLevel ) { 1168 isChangeLevel = true; 1169 isInClassify = false; 1170 } 1171 } 1172 else { 1173 isChangeLevel = false; 1174 } 1175 1176 // 分類のブレイク処理 1177 if( preLevel >= 3 && level < 3 || !isInClassify ) { // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 1178 if( lineTmpCnt != 0 ) { 1179 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1180 rtnB.append( "</td>" ).append( CR ); 1181 } 1182 1183 if( bkClassifyKey != null ) { 1184 rtnH.append( "<th colspan=\"" ).append( cellTmpCnt ).append( "\" class=\"MENU_H CLR" ) 1185 .append( cellColorCnt ).append( ' ' ).append( headGuikey ).append( "\">" ); // 5.5.5.3 (2012/08/17) 1186 if( "_SPACE".equals( bkClassifyKey ) ) { 1187 rtnH.append( ' ' ); // 6.0.2.5 (2014/10/31) char を append する。 1188 } 1189 else { 1190 rtnH.append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) ); 1191 } 1192 rtnH.append( "</th>" ); 1193 1194 // 5.2.3.0 (2010/12/01) sideCount によるセルの改行 1195 cellTmpAllCnt += cellTmpCnt; 1196 if( sideCount > 0 && cellTmpAllCnt >= sideCount ) { 1197 rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" ); 1198 1199 rtnH.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1200 rtnB.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1201 cellTmpAllCnt = 0; 1202 isDummyMENU = true; // 出力予約 1203 } 1204 } 1205 1206 bkClassifyKey = null; 1207 isInClassify = false; 1208 lineTmpCnt = 0; 1209 cellTmpCnt = 0; 1210 } 1211 1212 // 大分類(フィールドメニュー) 1213 if( level == 1 ) { 1214 headGuikey = gamenId; // 5.5.5.3 (2012/08/17) 1215 if( preLevel > 0 ) { 1216 cellColorCnt++ ; 1217 rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" ); 1218 } 1219 1220 rtn.append( "<tr><td rowspan=\"2\" class=\"MENU_S "+ headGuikey +"\">" ) // 5.5.5.3 (2012/08/17) 1221 .append( makeTagMenuString( null,null,guiInfos[i].getName(),gamenId,-3 ) ) 1222 .append( "</td>" ).append( CR ); 1223 1224 rtnH.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1225 rtnB.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1226 cellTmpAllCnt = 0; // 5.2.3.0 (2010/12/01) 1227 isDummyMENU = false; // 5.2.3.0 (2010/12/01) 出力予約解除 1228 } 1229 // 分類(直リンクの場合は、level=3で処理) 1230 else if( level == 2 ) { 1231 isInClassify = true; 1232// bkClassifyKey = guiInfos[i].getKey(); 1233 bkClassifyKey = gamenId; // 6.9.4.1 (2018/04/09) 1234 bkClassifyName = guiInfos[i].getName(); 1235 } 1236 // 通常メニュー・隠しメニュー 1237 else if( level >= 3 ) { 1238 1239 // 元のMENU_Sに戻り、rowspan を書き換える・・・のが邪魔くさいので、td のみ出力しておく。 1240 // 5.2.3.0 (2010/12/01) sideCount によるセルの改行 1241 if( isDummyMENU ) { 1242 rtn.append( "<tr><td rowspan=\"2\" class=\"MENU_S " ) 1243 .append( headGuikey ).append( "\"></td>" ) // 5.5.5.3 (2012/08/17) 1244 .append( CR ); 1245 isDummyMENU = false; // 出力予約解除 1246 } 1247 1248 // 画面ID="HYBS_BR"の場合は、セルを変える。 1249// if( "HYBS_BR".equals( guiInfos[i].getKey() ) ) { 1250 if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) { // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定 1251 if( lineTmpCnt != 0 ) { 1252 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1253 lineTmpCnt = 0; 1254 } 1255 } 1256 // 通常画面 1257 else { 1258 if( lineTmpCnt == 0 ) { 1259 rtnB.append( "<td class=\"MENU_B " + headGuikey + "\">" ); // 5.5.5.3 (2012/08/17) 1260 cellTmpCnt++; 1261 } 1262 1263 rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-3 ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 1264 lineTmpCnt++; 1265 1266 if( lineTmpCnt >= maxCellCount ) { 1267 rtnB.append( "</td>" ); 1268 lineTmpCnt = 0; 1269 } 1270 else { 1271 rtnB.append( BR ); 1272 } 1273 1274 // 分類の中に入っていない通常画面 1275 if( !isInClassify ) { 1276 bkClassifyKey = "_SPACE"; 1277 isInClassify = true; 1278 } 1279 } 1280 } 1281 1282 preLevel = level; 1283 } 1284 } 1285 1286 // 終了処理 1287 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1288 rtnB.append( "</td>" ).append( CR ); 1289 1290 if( bkClassifyKey != null ) { 1291 rtnH.append( "<th colspan=\"" ).append( cellTmpCnt ) 1292 .append( "\" class=\"MENU_H CLR" ) .append( cellColorCnt ) 1293 .append( ' ' ).append( headGuikey ).append( "\">" ) // 5.5.5.3 (2012/08/17) 1294 .append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) ) 1295 .append( "</th>" ); 1296 } 1297 1298 rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" ); 1299 1300 return rtn.toString(); 1301 } 1302 1303 /** 1304 * メニューを表示する為のHTMLを作成します(マトリクスメニュー2)。 1305 * 1306 * マトリクスメニューをベースとした特別バージョンです。 1307 * 通常のマトリクスメニューからの変更点は以下の通りです。 1308 * ①大分類が表示されない 1309 * ⇒ 変わりに、1行に表示されているセル数がsideCountで指定した数を超えた場合に 1310 * 自動的に改行されます。 1311 * ②画面リンクのターゲット 1312 * ⇒ 自分自身のフレームに対してリンク先を表示します。 1313 * リンク先は、通常メニュー構成ですが左メニューには該当する小分類の画面しか表示されません。 1314 * ③小分類でのリンク 1315 * ⇒ 小分類をクリックした際に、通常のメニュー構成画面にリンクします。 1316 * 但し、②と同様に左メニューには該当する小分類の画面しか表示されません。 1317 * 1318 * @og.rev 4.2.1.0 (2008/04/01) 新規追加 1319 * @og.rev 4.2.1.1 (2008/05/02) カテゴリーリンクで一番上の画面のモードが-wとなっている場合に、 1320 * その画面が立ち上がってしまうバグを修正 1321 * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をmakeTagMenuString()に変更 1322 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更) 1323 * @og.rev 5.5.5.3 (2012/08/17) ヘッダ部のgamenIdをth,tdのクラスに追加 1324 * @og.rev 6.8.2.3 (2017/11/10) minCellCountの数が、一つ足りない事の修正 1325 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定 1326 * 1327 * @return マトリクスメニュー 1328 * @og.rtnNotNull 1329 */ 1330 private String makeMatrixMenu2() { 1331 final StringBuilder rtn = new StringBuilder( BUFFER_LARGE ); 1332 1333 final UserInfo userInfo = getUser(); 1334 1335 final GUIInfo[] guiInfos = userInfo.getGUIInfos(); 1336// String gamenId ; // 画面ID 1337 String bkClassifyKey = null; // 分類コード(旧) 1338 String nextKey = null; // 分類ボタンを押した時に最初の画面が開くようにする 1339 String bkClassifyName = null; // 分類名称(旧) 1340 final int cellColorCnt = 0; // MENU_H に 追加する CLR クラス属性の連番 1341 1342 final StringBuilder rtnH = new StringBuilder( BUFFER_LARGE ); // 分類部分の出力用 1343 final StringBuilder rtnB = new StringBuilder( BUFFER_LARGE ); // 実画面のリンク部分の出力用 1344 1345 int level ; 1346 int preLevel = 0; 1347 1348 int lineTmpCnt = 0; // セル中の行カウント 1349 int cellTmpCnt = 0; // 1つの分類中のセルカウント 1350 int cellTmpAllCnt = 0; // 該当行のセルカウント 1351 1352 boolean isInClassify = false; // 分類の中か? 1353 boolean isChangeLevel = false; // 直リンク用(無理やり通常画面の階層として扱うので) 1354 1355 String headGuikey = "" ; // 5.5.5.3 (2012/08/17) 1356 1357 rtn.append( "<tr>" ).append( CR ); 1358 1359 for( int i=0; i<guiInfos.length; i++ ) { 1360 if( guiInfos[i].isRead() ) { // 4.0.0 (2005/01/31) 1361 final String gamenId = guiInfos[i].getKey() ; 1362 if( match != null && !gamenId.matches( match ) ) { continue; } 1363 if( unmatch != null && gamenId.matches( unmatch ) ) { continue; } 1364 1365 // 処理すべき画面かのチェック 1366 final int guiFlg = guiCheck( guiInfos, i ); 1367 if( guiFlg == 0 ) { continue; } 1368 1369 level = guiInfos[i].getLevel(); // 4.0.0 (2005/01/31) 1370 1371 // 直リンクの場合、無理やり通常画面に変換 1372 if( level == 2 && guiInfos[i].getAddress() != null && guiInfos[i].getAddress().length() != 0 ) { 1373 level = 3; 1374 if( !isChangeLevel ) { 1375 isChangeLevel = true; 1376 isInClassify = false; 1377 } 1378 } 1379 else { 1380 isChangeLevel = false; 1381 } 1382 1383 // 分類のブレイク処理 1384 if( preLevel >= 3 && level < 3 || !isInClassify ) { // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 1385 if( lineTmpCnt != 0 ) { 1386 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1387 //rtnB.append( "</td>" ).append( CR ); // 4.2.1.0 (2008/04/03) リスト 1388 rtnB.append( "</ul></div></td>" ).append( CR ); 1389 } 1390 1391 if( bkClassifyKey != null ) { 1392 // 6.0.2.5 (2014/10/31) char を append する。 1393 rtnH.append( "<th colspan=\"" ).append( cellTmpCnt ).append( "\" class=\"MENU_H CLR" ) 1394 .append( cellColorCnt ).append( ' ' ).append( headGuikey ).append( "\">" ); // 5.5.5.3 (2012/08/17) 1395 if( "_SPACE".equals( bkClassifyKey ) ) { 1396 rtnH.append( ' ' ); // 6.0.2.5 (2014/10/31) refactoring 1397 } 1398 else { 1399 // 6.4.2.1 (2016/02/05) PMD refactoring. 1400 final String classifyHref = JSP + "/index.jsp?classify=" + bkClassifyKey + "&GAMENID="+nextKey; // ボタンを押した場合に最初の画面が現れる 1401 rtnH.append( makeTagMenuString( classifyHref,"_self",bkClassifyName,bkClassifyKey,-3 ) ); 1402 } 1403 rtnH.append( "</th>" ); 1404 1405 cellTmpAllCnt += cellTmpCnt; 1406 1407 if( sideCount > 0 && cellTmpAllCnt >= sideCount ) { 1408 rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" ); 1409 1410 rtnH.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1411 rtnB.setLength(0); // 6.1.0.0 (2014/12/26) refactoring 1412 cellTmpAllCnt = 0; 1413 } 1414 } 1415 1416 bkClassifyKey = null; 1417 nextKey = null; 1418 isInClassify = false; 1419 lineTmpCnt = 0; 1420 cellTmpCnt = 0; 1421 } 1422 1423 // 5.5.5.3 (2012/08/17) 大分類(フィールドメニュー) 1424 if( level == 1 ) { 1425 headGuikey = gamenId; 1426 } 1427 // 分類(直リンクの場合は、level=3で処理) 1428 else if( level == 2 ) { 1429 isInClassify = true; 1430 if( guiInfos[i].isPulldown() ){ // 4.3.3.0 (2008/10/01) プルダウン化チェック 1431 excludeButton = true; 1432 } 1433 else{ 1434 excludeButton = false; 1435 } 1436// bkClassifyKey = guiInfos[i].getKey(); 1437 bkClassifyKey = gamenId; // 6.9.4.1 (2018/04/09) 1438 bkClassifyName = guiInfos[i].getName(); 1439 for( int j=i+1; j<guiInfos.length; j++ ) { 1440 if( guiInfos[j] != null && guiInfos[j].isRead() ) { 1441 nextKey = guiInfos[j].getKey(); 1442 break; 1443 } 1444 } 1445 } 1446 // 通常メニュー・隠しメニュー 1447 else if( level >= 3 ) { 1448 // 画面ID="HYBS_BR"の場合は、セルを変える。 1449// if( "HYBS_BR".equals( guiInfos[i].getKey() ) ) { 1450 if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) { // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定 1451 if( lineTmpCnt != 0 ) { 1452 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1453 lineTmpCnt = 0; 1454 } 1455 } 1456 // 通常画面 1457 else { 1458 if( lineTmpCnt == 0 ) { 1459 // rtnB.append( "<td class=\"MENU_B\">" ); 1460 // 4.2.1.0 (2008/04/03) リンクをリスト形式で出す案 1461 rtnB.append( "<td class=\"MENU_B "+ headGuikey +"\"> <div class=\"gamen-menu-wrap\"><ul class=\"gamen-menu\">" ); // 5.5.5.3 (2012/08/17) 1462 cellTmpCnt++; 1463 } 1464 1465 // 5.5.2.5 (2012/05/21) リストは、イメージを設定するので、メソッド側で付与します。 1466 rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-4 ) ); // 5.5.2.5 (2012/05/21) イメージアイコン対応 1467 lineTmpCnt++; 1468 1469 if( lineTmpCnt >= maxCellCount ) { 1470 // rtnB.append( "</td>" ); 1471 rtnB.append( " </ul> </div></td>" ); // 4.2.1.0 (008/04/03) リスト 1472 lineTmpCnt = 0; 1473 } 1474 // else { 1475 // rtnB.append( BR ); // 4.2.1.0 (2008/04/03) リスト。改行不要。 1476 // } 1477 1478 // 分類の中に入っていない通常画面 1479 if( !isInClassify ) { 1480 bkClassifyKey = "_SPACE"; 1481 isInClassify = true; 1482 } 1483 } 1484 } 1485 preLevel = level; 1486 } 1487 } 1488 1489 // 終了処理 1490 // 4.3.3.0 (2008/10/01) 終了処理は0の時行はない 1491 if( lineTmpCnt != 0){ 1492 for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); } // 6.8.2.3 (2017/11/10) 1493 rtnB.append( "</td>" ).append( CR ); 1494 } 1495 1496 if( bkClassifyKey != null ) { 1497 rtnH.append( "<th colspan=\"" + cellTmpCnt + "\" class=\"MENU_H CLR" + cellColorCnt + " " + headGuikey + "\">" ); // 5.5.5.3 (2012/08/17) 1498 1499 // 6.4.2.1 (2016/02/05) PMD refactoring. 1500 final String classifyHref = JSP + "/index.jsp?classify=" + bkClassifyKey + "&GAMENID="+nextKey; 1501 rtnH.append( makeTagMenuString( classifyHref,"_self",bkClassifyName,bkClassifyKey,-3 ) ); 1502 rtnH.append( "</th>" ); 1503 } 1504 1505 rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" ); 1506 1507 return rtn.toString(); 1508 } 1509 1510 /** 1511 * タイプに応じたメニューを表示する為の文字列を作成します。 1512 * 引数の GUIInfo より、アクセスすべきメニューのhrefと、targetを求めます。 1513 * type = -3 (マトリクスメニュー) の場合だけ、タグ属性の target を使用します。 1514 * 1515 * 0:フィールドセットメニュー 1516 * 1:トップ階層(【分類名称】) 1517 * 2:選択階層(通常の折りたたみメニュー) 1518 * 3:選択非表示(通常は、隠してあります) 1519 * -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます) 1520 * -2:ラインメニュー([画面名称] ) 1521 * -3:マトリクスメニュー(一覧) 1522 * -4:マトリクスメニュー2(一覧) 1523 * -5:1レベル表示(後続処理は-3と同じ) 1524 * -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ) 1525 * 1526 * @og.rev 4.0.0.0 (2005/01/31) 新規登録(makeTopMenu、makeSecondMenuの置き換え) 1527 * @og.rev 4.1.0.1 (2008/01/22) アドレスが[..]から始まる画面はマルチセッションチェックを行わない。 1528 * @og.rev 4.2.1.0 (2008/04/01) マトリクスメニュー2用のタグ作成処理追加 1529 * @og.rev 4.2.1.0 (2008/04/17) マトリクス2からの遷移先でボタンメニューにする処理 1530 * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をmakeTagMenuString()に変更 1531 * @og.rev 4.3.3.7 (2008/11/22) https対応 1532 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。) 1533 * @og.rev 5.7.8.1 (2014/07/18) realAddress の "/" 対応 1534 * @og.rev 6.3.8.4 (2015/10/09) KBLINK(リンク区分)を画面のイメージファイルに割り当てます。 1535 * @og.rev 5.9.6.1 (2016/03/04) -5を追加。-3との違いはresult.jspに飛ばない事 1536 * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 1537 * 1538 * @param guiInfo GUIInfoリンク 1539 * @param bodyIn BODY部(表示) 1540 * @param type タイプ 1541 * 1542 * @return 階層別メニュー文字列 1543 * @og.rtnNotNull 1544 */ 1545 private String makeTagMenu( final GUIInfo guiInfo, final String bodyIn, final int type ) { 1546 1547 String href = null; 1548 String tmpTarget = null; 1549 final String gamenId = guiInfo.getKey(); // 5.5.2.5 (2012/05/21) イメージアイコン対応 1550 int tmpType = type; // 5.9.6.1 1551 1552 if( guiInfo.getAddress() != null && guiInfo.getAddress().length() > 0 ) { 1553 final String readAdrs = guiInfo.getRealAddress( "index.jsp" ); 1554 final String reqParam = getRequestParameter( guiInfo.getParam() ); 1555 href = XHTMLTag.addUrlEncode( readAdrs,reqParam ); 1556 tmpTarget = guiInfo.getTarget(); 1557 1558 // 4.3.3.7 (2008/11/22) https対応 1559 // 5.7.8.1 (2014/07/18) realAddress の "/" 対応 1560 final String kblink = guiInfo.getKblink(); 1561 if( ! readAdrs.startsWith( "http://" ) && ! readAdrs.startsWith( "https://" ) && !"/".equals( kblink ) ) { 1562 if( type == -3 ) { 1563 tmpTarget = target; 1564 href = XHTMLTag.addUrlEncode( JSP + "/result.jsp",reqParam ); // 6.2.0.0 (2015/02/27) 1565 } 1566 else if( type == -4 ) { // 4.2.1.0 (2008/04/01) 1567 tmpTarget = "_self"; 1568 href = XHTMLTag.addUrlEncode( JSP + "/index.jsp",reqParam ); // 6.2.0.0 (2015/02/27) 1569 href = XHTMLTag.addUrlEncode( href,"classify=" + guiInfo.getClassify() ); 1570 } 1571 else if( type == -5 ){ // 5.9.6.1 (2016/03/04) 1572 tmpTarget = target; 1573 tmpType = -3; 1574 } 1575 href = XHTMLTag.addUrlEncode( href,"GAMENID=" + gamenId ); // 5.5.2.5 (2012/05/21) せっかくなので、利用する。 1576 1577 // 3.8.0.0 (2005/06/07) 同一セッションでのマルチ起動対策を行います。 1578 // 4.1.0.1 (2008/01/22) アドレスが[..]から始まる画面はマルチセッションチェックを行いません。 1579 // 4.1.0.1 (2008/04/01) マトリクスメニュー2はマルチセッションチェックを行いません。 1580// if( multiSessionCheck && !guiInfo.getAddress().startsWith( ".." ) && type != -4 ) { 1581 if( !guiInfo.getAddress().startsWith( ".." ) && type != -4 ) { // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 1582 href = XHTMLTag.addUrlEncode( href,mscKey ); 1583 } 1584 } 1585 } 1586 // 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。) 1587 final String imgKey = guiInfo.getImageKey() ; 1588 return makeTagMenuString( href,tmpTarget,bodyIn,gamenId,imgKey,tmpType ) ; // 5.9.6.1 1589 } 1590 1591 /** 1592 * タイプに応じたメニューを表示する為の文字列を作成します。 1593 * 従来からのメソッドの引数のままで、新しい gamenId は、imgKey をそのままセットします。 1594 * 1595 * 0:フィールドセットメニュー 1596 * 1:トップ階層(【分類名称】) 1597 * 2:選択階層(通常の折りたたみメニュー) 1598 * 3:選択非表示(通常は、隠してあります) 1599 * -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます) 1600 * -2:ラインメニュー([画面名称] ) 1601 * -3:マトリクスメニュー(一覧) 1602 * -4:マトリクスメニュー2(一覧) 1603 * -5:1レベル表示(後続処理は-3と同じだが、絶対パスの場合は、画面リソースのtargetを使用する。) 1604 * -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ) 1605 * 1606 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。) 1607 * 1608 * @param href リンク 1609 * @param target ターゲット 1610 * @param bodyIn BODY部(表示) 1611 * @param imgKey imageファイルの検索キー 1612 * @param type タイプ 1613 * 1614 * @return 階層別メニュー文字列 1615 * @og.rtnNotNull 1616 */ 1617 private String makeTagMenuString( final String href,final String target, final String bodyIn, 1618 final String imgKey,final int type ) { 1619 return makeTagMenuString( href,target,bodyIn,imgKey,imgKey,type ); // gamenId の代わりに、imgKey をセットする。 1620 } 1621 1622 /** 1623 * タイプに応じたメニューを表示する為の文字列を作成します。 1624 * 1625 * タイプは、階層別になっていますが、マイナスは、内部で処理するための記号です。 1626 * 1627 * 0:フィールドセットメニュー 1628 * 1:トップ階層(【分類名称】) 1629 * 2:選択階層(通常の折りたたみメニュー) 1630 * 3:選択非表示(通常は、隠してあります) 1631 * -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます) 1632 * -2:ラインメニュー([画面名称] ) 1633 * -3:マトリクスメニュー(一覧) 1634 * -4:マトリクスメニュー2(一覧) 1635 * -5:1レベル表示(後続処理は-3と同じだが、絶対パスの場合は、画面リソースのtargetを使用する。) 1636 * -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ) 1637 * 1638 * @og.rev 4.0.0.0 (2005/01/31) 新規登録(makeTopMenu、makeSecondMenuの置き換え) 1639 * @og.rev 4.0.0.0 (2007/11/28) switch文の中の二重コードを統一します。 1640 * @og.rev 4.2.1.0 (2008/04/01) ボタン形式のリンク対応、マトリクスメニュー2対応 1641 * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をここで行うようにする 1642 * @og.rev 4.3.5.0 (2009/02/01) switch の case で重複項目をまとめます。 1643 * @og.rev 5.1.4.0 (2010/03/01) onClick,onMouseOver,onMouseOutの処理は、外部のJavaScriptファイルで記述します。 1644 * @og.rev 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正 1645 * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応 1646 * @og.rev 5.4.4.4 (2012/02/15) ヘルプアイコンはimgKeyがnullでない場合のみとする 1647 * @og.rev 5.5.0.4 (2012/03/14) FAQ対応 1648 * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。) 1649 * @og.rev 5.5.4.2 (2012/07/13) JSP(/gf/jsp/) ではなく、CNTX(gf)+MENU_IMG(/jsp/menuImage/) で処理するように変更 1650 * @og.rev 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加 1651 * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。 1652 * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。 1653 * @og.rev 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。 1654 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加 1655 * @og.rev 6.8.0.1 (2017/06/30) -5:1レベル表示追加(元は、相対パスのみ対応していたが、絶対パスにも対応) 1656 * @og.rev 6.8.1.6 (2017/09/29) imageOnly="true" で、イメージにリンクが付かないバグ修正。 1657 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 1658 * @og.rev 7.2.9.4 (2020/11/20) spotbugs:switch 文の2つの case のために同じコードを使用しているメソッド 1659 * 1660 * @param href リンク 1661 * @param target ターゲット 1662 * @param bodyIn BODY部(表示) 1663 * @param gamenId 画面ID/グループIDなど 1664 * @param imgKey imageファイルの検索キー 1665 * @param type タイプ 1666 * 1667 * @return 階層別メニュー文字列 1668 * @og.rtnNotNull 1669 */ 1670 private String makeTagMenuString( final String href,final String target, final String bodyIn, 1671 final String gamenId,final String imgKey,final int type ) { 1672 1673 final String body ; 1674 final String img ; // 6.7.5.0 (2017/03/10) イメージを、【】の外に出す。 1675 String listStyle = "<li>"; 1676 // 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。 1677 // 最初に見つけたキーが優先されるので、画面IDのファイルを優先します。 1678 final String imgFile = imgFileMap.getFilename( gamenId,imgKey ); // 5.5.2.5 (2012/05/21) 属性名変更 1679 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 1680 if( imgFile == null ) { 1681 img = ""; 1682 if( imageOnly && bodyIn != null && bodyIn.length() > 0 ) { 1683 body = "<span title=\"" + StringUtil.htmlFilter( bodyIn,true ) + "\" >" + bodyIn.charAt(0) + "</span>" ; 1684 } 1685 else { 1686 body = bodyIn ; 1687 } 1688 } 1689 else { 1690 if( imageOnly ) { 1691 // 6.8.1.6 (2017/09/29) imageOnly="true" で、イメージにリンクが付かないバグ修正。リンクは、body に付く 1692 img = ""; 1693 body = "<img src=\"" + imgFile + "\" class=\"ICON1\" title=\"" 1694// + StringUtil.htmlFilter( bodyIn,true ) + "\" />" ; 1695 + StringUtil.htmlFilter( bodyIn,true ) + "\" >" ; // 7.0.1.0 (2018/10/15) 1696 } 1697 // 5.5.2.5 (2012/05/21) -4(MATRIX Menu2)の場合は、<li style="list-style:url(画像URL);"> で処理する。 1698 else if( type == -4 ) { 1699 listStyle = "<li style=\"list-style:url(" + imgFile + ");\">" ; 1700 body = bodyIn ; 1701 img = ""; 1702 } 1703 else { 1704 // 6.7.5.0 (2017/03/10) TILE表示のレベル-6では、イメージ直後に BR を入れる。(暫定処置) 1705 if( type == -6 ) { 1706// img = "<img src=\"" + imgFile + "\" class=\"ICON2\" /><br />" ; // ICON2 + BR 1707 img = "<img src=\"" + imgFile + "\" class=\"ICON2\" ><br>" ; // ICON2 + BR 7.0.1.0 (2018/10/15) 1708 } 1709 else { 1710// img = "<img src=\"" + imgFile + "\" class=\"ICON1\" />" ; // ICON1 1711 img = "<img src=\"" + imgFile + "\" class=\"ICON1\" >" ; // ICON1 7.0.1.0 (2018/10/15) 1712 } 1713 body = bodyIn; 1714 } 1715 } 1716 1717 final String in ; 1718 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 1719 if( href == null ) { 1720 in = body; 1721 } 1722 else { 1723 if( useButton ) { // 4.2.1.0 (2008/04/01) 1724 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 1725 in = new TagBuffer( "button" ) 1726 .add( "onclick" , "top."+target+".location.href=\'"+ href + "\';" ) // 5.1.4.0 (2010/03/01) 1727 .add( "class" , "buttonMenu" ) // 4.2.1.0 (2008/04/03) classを追加 1728 .add( "id" , gamenId ) // 5.5.2.5 (2012/05/21) idを本当の画面IDで設定 1729 .addBody( body ) 1730 .makeTag(); 1731 } 1732 else { 1733 // 4.2.2.0 (2008/05/14) ボタン式にする場合はリクエスト変数付加 1734 // 4.3.3.0 (2008/10/01) 強制プルダウン化の場合はfalseで渡す(excludeButton の値の反転) 1735 final String href2 = buttonRequest 1736 ? XHTMLTag.addUrlEncode( href,"buttonRequest=" + !excludeButton) 1737 : href ; 1738 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 1739 in = new TagBuffer( "a" ) 1740 .add( "class" , "buttonClassify" , buttonRequest ) 1741 .add( "href" , href2 ) 1742 .add( "target" , target ) 1743 .addBody( body ) 1744 .makeTag(); 1745 } 1746 } 1747 1748 // 6.7.5.0 (2017/03/10) イメージを、【】の外に出す。 1749 String rtn = null; 1750 switch( type ) { 1751 // 6.9.8.0 (2018/05/28) FindBugs:switch 文の2つの case のために同じコードを使用しているメソッド 1752 // 偶然同じになったのと、これを対応するとソースがみにくくなるので、このままとします。 1753 case 1: rtn = FIELD_IN + "<legend>" + img + in + "</legend>" ; break; // 大分類 1754 // case 2: rtn = img + "【" + in + "】" ; break; // 小分類・直リンク 1755 case 3: // 通常メニュー 1756 case 4: rtn = " " + img + in ; break; // 隠れメニュー 1757 case -1: rtn = "<td class=\"MENU_G " + gamenId + "\">" + img + in + "</td>" ; break; // 5.5.2.5 (2012/05/21) グループメニュー 1758 case -2: rtn = img + "[" + in + "] " ; break; // ラインメニュー 1759 // case -3: rtn = img + in ; break; // マトリクスメニュー 1760 case -4: rtn = listStyle + in + "</li>" ; break; // 4.2.1.0 (2008/04/03) リスト。リストのため■はいらない 1761 case -3: // 7.2.9.4 (2020/11/20) マトリクスメニュー 1762 case -5: rtn = img + in ; break; // 6.8.0.1 (2017/06/30) 1レベル表示絶対パス 1763 case 2: // 7.2.9.4 (2020/11/20) 小分類・直リンク 1764 case -6: rtn = img + "【" + in + "】" ; break; // 小分類・直リンク(TILE) 1765 default : 1766 rtn = "X_" + in ; break; // 6.0.2.5 (2014/10/31) break追記 1767 } 1768 1769 return rtn ; 1770 } 1771 1772 /** 1773 * 【TAG】作成するメニューの種類[NORMAL/GROUP/ONELEVEL/NEXTGUI/MATRIX/MATRIX2]を指定します(初期値:NORMAL)。 1774 * 1775 * @og.tag 1776 * 作成するメニューには、複数の種類があります。 1777 * <table class="plain"> 1778 * <caption>メニューの種類</caption> 1779 * <tr><th>種類 </th><th>説明 </th></tr> 1780 * <tr><td>NORMAL </td><td>通常の階層メニュー</td></tr> 1781 * <tr><td>GROUP </td><td>GROUPのみを取り出してリンクを作成します。(topMenuに利用)</td></tr> 1782 * <tr><td>ONELEVEL</td><td>指定のclassify のメニューのみを取り出してリンクを作成します。(lineMenuに利用)</td></tr> 1783 * <tr><td>NEXTGUI </td><td>既存のページの次にアクセスされる画面郡のリンクを作成します。</td></tr> 1784 * <tr><td>MATRIX </td><td>一覧表形式のメニューを作成します。(大分類付きマルチメニュー)</td></tr> 1785 * <tr><td>MATRIX2 </td><td>一覧表形式のメニューを作成します。(大分類なしボタンメニュー)</td></tr> 1786 * <tr><td>NONE </td><td>表示しない(ヘッダーメニューを表示しない時などに使用)</td></tr> 1787 * <tr><td>TILE </td><td>イメージを使った全面アイコン画面</td></tr> 1788 * </table> 1789 * 1790 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1791 * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加 1792 * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。 1793 * @og.rev 6.3.8.3 (2015/10/03) NONE(表示しない) 追加(JavaDoc追記のみ)。 1794 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 1795 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加 1796 * 1797 * @param type メニューの種類 [NORMAL/GROUP/ONELEVEL/NEXTGUI/MATRIX/MATRIX2/NONE/TILE] 1798 */ 1799 public void setMenuType( final String type ) { 1800 menuType = nval( getRequestParameter( type ),menuType ); 1801 if( ! check( menuType, MENU_TYPE_SET ) ) { 1802 final String errMsg = "menuType に、指定できない種類の文字が指定されました。" + CR 1803 + "menuType=[" + menuType + "] " + CR 1804 + "menuType List=" + String.join( ", " , MENU_TYPE_SET ) ; 1805 throw new HybsSystemException( errMsg ); 1806 } 1807 } 1808 1809 /** 1810 * 【TAG】折り返しメニューを構築するかどうかを指定します(初期値:true)。 1811 * 1812 * @og.tag 1813 * trueを設定すると、JavaScriptによる折り返しメニューを構築します。 1814 * false の場合は、通常のHTMLのみで、階層メニューを構築します。 1815 * 初期値は、true(折り返しメニュー)です。 1816 * 1817 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1818 * 1819 * @param flag 折り返しメニュー [true:する/false:しない] 1820 */ 1821 public void setExpand( final String flag ) { 1822 expand = nval( getRequestParameter( flag ),expand ); 1823 } 1824 1825 /** 1826 * 【TAG】表示対象となるグループをCSV形式で指定します。 1827 * 1828 * @og.tag 1829 * メニューの表示対象グループをCSV形式で複数指定できます。 1830 * 指定のグループのメニューだけが、表示対象になります。 1831 * メニューにも、複数のグループを指定できるため、1グループの指定で、 1832 * 複数のくくりを表示することも可能です。 1833 * グループを指定しない場合は、全グループが対象になります。 1834 * また、メニュー側にグループ指定がない場合は、グループ指定に 1835 * 関係なく、対象になります。 1836 * 初期値は、未指定(全メニューが対象)です。 1837 * 分解方法は、通常のパラメータ取得後に、CSV分解します。 1838 * 1839 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1840 * 1841 * @param menuGroups 表示対象グループ (CSV形式) 1842 */ 1843 public void setGroups( final String menuGroups ) { 1844 groups = StringUtil.csv2Array( getRequestParameter( menuGroups ) ); 1845 if( groups.length == 0 ) { groups = null; } 1846 } 1847 1848 /** 1849 * 【TAG】表示対象となる分類(classify)を指定します。 1850 * 1851 * @og.tag 1852 * メニューの表示対象となる分類(classify)を指定することで、一まとまりの 1853 * メニューを作成します。これは、3段階メニューの最終メニューを求める場合に 1854 * 指定します。 1855 * 最終メニューは、画面上部に設ける予定のメニューで、上下フレーム分割での 1856 * 運用時に使用します。 1857 * 分類の指定がない場合は、すべてが表示対象になります。 1858 * 初期値は、未指定(全メニューが対象)です。 1859 * 1860 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1861 * 1862 * @param classify 表示対象分類 (classify) 1863 */ 1864 public void setClassify( final String classify ) { 1865 selClassify = nval( getRequestParameter( classify ),selClassify ); 1866 } 1867 1868 /** 1869 * 【TAG】グループメニューの表示対象となるソース名(href)を指定します(初期値:menu.jsp)。 1870 * 1871 * @og.tag 1872 * GROUPメニューの表示対象となるソース名(href)を指定することで、 1873 * サブメニューを自分自身のフレームに対して割り当てるのか、フレームを分けて 1874 * 管理するのかを自由に設定できます。 1875 * 初期値は、menu.jspです。 1876 * 1877 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1878 * 1879 * @param inHref 表示対象ソース名 (href) 1880 */ 1881 public void setHref( final String inHref ) { 1882 href = nval( getRequestParameter( inHref ),href ); 1883 } 1884 1885 /** 1886 * 【TAG】グループメニューの表示対象となるフレーム名(target)を指定します(初期値:MENU)。 1887 * 1888 * @og.tag 1889 * GROUPメニューの表示対象となるフレーム名(target)を指定することで、 1890 * サブメニューを自分自身のフレームに対して割り当てるのか、フレームを分けて 1891 * 管理するのかを自由に設定できます。 1892 * フレーム分割を行うと、変更箇所は、サブメニューのみになる為、動きに無駄が 1893 * なくなりますが、グループメニューの大きさが固定されてしまいます。 1894 * 自分自身にすると、グループメニューとサブメニューを一つのフレームに 1895 * 入れることで、更新時の画面のちらつきは発生しますが、無駄なスペースは 1896 * 省くことが可能になります。 1897 * 初期値は、MENU(通常のメニューフレーム)です。 1898 * 1899 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1900 * 1901 * @param inTarget 表示対象フレーム名 (target) 1902 */ 1903 public void setTarget( final String inTarget ) { 1904 target = nval( getRequestParameter( inTarget ),target ); 1905 } 1906 1907 /** 1908 * 【TAG】グループメニューの表示に、画像のみかどうか[true:画像のみ/false:画像+ラベル]を指定します(初期値:false)。 1909 * 1910 * @og.tag 1911 * GROUPメニューの表示対象として、jsp/menuImage 以下に グループ名と同一の 1912 * 画像ファイルが存在する場合は、画像を使用します。 1913 * このフラグを、true に設定すると、画像のみを使用します。 1914 * false の場合は、画像+グループ名のラベルを使用します。 1915 * 画像のみの場合でも、title 属性にグループ名のラベルをセットしますので、 1916 * マウスカーソルをオーバーすれば、名称がTips表示されます。 1917 * 画像が存在しない場合に、true(画像のみ)に設定した場合は、ラベルの最初の1文字 1918 * のみを出力します。 1919 * 初期値は、false(画像+ラベル)です。 1920 * 1921 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1922 * 1923 * @param flag グループメニュー表示 [true:画像のみ/false:画像+ラベル] 1924 */ 1925 public void setImageOnly( final String flag ) { 1926 imageOnly = nval( getRequestParameter( flag ),imageOnly ); 1927 } 1928 1929 /** 1930 * 【TAG】グループメニューの表示対象となるメニューを横並びさせる数を指定します。 1931 * 1932 * @og.tag 1933 * GROUPメニューなどの表示を行う場合に、横方向に何個のメニューを表示させるかを 1934 * 指定します。例えば、画像のみのリンクと組み合わせれば、より、多くのグループを 1935 * 横方向に並べることで、小領域に多くの情報を詰めることが可能になります。 1936 * 0 を設定すると、横方向にのみ並べる(折り返さない)メニューを作ることが 1937 * 可能になります。 1938 * 初期値は、無制限です。 1939 * 1940 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1941 * 1942 * @param count 横並び数 1943 */ 1944 public void setSideCount( final String count ) { 1945 sideCount = nval( getRequestParameter( count ),sideCount ); 1946 } 1947 1948 /** 1949 * 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最小行数を指定します(初期値:8)。 1950 * 1951 * @og.tag 1952 * 表形式メニュー(MATRIX)では、一つのセルの高さを同一にする為、<br />タグを挿入します。 1953 * このタグの挿入する個数を指定します。 1954 * この個数だけ、メニューの数があろうとなかろうと行を確保します。 1955 * 指定の値が、実際の行数より少ない場合は、実際の行数分だけ拡張されます。 1956 * 初期値は、8 です。 1957 * 1958 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1959 * 1960 * @param count セル内最小行数 1961 * @see #setMaxCellCount( String ) 1962 */ 1963 public void setMinCellCount( final String count ) { 1964 minCellCount = nval( getRequestParameter( count ),minCellCount ); 1965 } 1966 1967 /** 1968 * 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最大行数を指定します(初期値:8)。 1969 * 1970 * @og.tag 1971 * 表形式メニュー(MATRIX)では、一つのセルの高さを同一にする為、指定の行数で 1972 * 新たな セルを作成して、セルを横方向に連結します。 1973 * 初期値は、8 です。 1974 * 1975 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 1976 * 1977 * @param count セル内最大行数 1978 * @see #setMinCellCount( String ) 1979 */ 1980 public void setMaxCellCount( final String count ) { 1981 maxCellCount = nval( getRequestParameter( count ),maxCellCount ); 1982 } 1983 1984 /** 1985 * 【TAG】グループメニューのキャッシュを使用するかどうか[true/false]を指定します(初期値:true)。 1986 * 1987 * @og.tag 1988 * GROUPメニューの表示は、一旦作成すると、ほとんど書き換えることがありません。 1989 * 作成は、使用できる全メニューをスキャンして、その中からグループ属性をピックアップ 1990 * するという処理を行っている為、明らかに無駄な処理です。 1991 * そこで、jsp/index.jsp が実行された場合のみキャッシュをクリアして、内部では 1992 * キャッシュがなければ作成し、あればキャッシュを使うロジックになっています。 1993 * ここでは、キャッシュを使用するのか、毎回作成しなおすのかを指定します。 1994 * 対象として、jsp/menuImage 以下に グループ名と同一の 1995 * 画像ファイルが存在する場合は、画像を使用します。 1996 * このフラグを、true に設定すると、画像のみを使用します。 1997 * false の場合は、画像+グループ名のラベルを使用します。 1998 * 画像のみの場合でも、title 属性にグループ名のラベルをセットしますので、 1999 * マウスカーソルをオーバーすれば、名称がTips表示されます。 2000 * 画像が存在しない場合は、たとえ、true(画像のみ)に設定しても、ラベルを出力します。 2001 * 初期値は、true(キャッシュする)です。 2002 * 2003 * @og.rev 4.0.0.0 (2005/01/31) 新規登録 2004 * 2005 * @param flag キャッシュ可否 [true:キャッシュする/false:キャッシュしない] 2006 */ 2007 public void setCache( final String flag ) { 2008 cache = nval( getRequestParameter( flag ),cache ); 2009 } 2010 2011 /** 2012 * 【TAG】正判定(マッチする場合に、メニューに出す)条件を設定します。 2013 * 2014 * @og.tag 2015 * メニューを表示する/しないの判定を、画面IDのマッチングで判断します。 2016 * これは、正規表現で表される引数と、画面IDがマッチする場合に、 2017 * メニューを表示させます。 2018 * マッチしない場合は、表示されません。 2019 * 何も指定しない場合は、ロールの判定みの行われます。 2020 * 2021 * @param mt 正判定条件 (マッチする場合に、メニューに出す) 2022 */ 2023 public void setMatch( final String mt ) { 2024 match = nval( getRequestParameter( mt ),match ); 2025 } 2026 2027 /** 2028 * 【TAG】逆判定(マッチする場合に、メニューに出さない)条件を設定します。 2029 * 2030 * @og.tag 2031 * メニューを表示する/しないの判定を、画面IDのマッチングで判断します。 2032 * これは、正規表現で表される引数と、画面IDがマッチする場合に、 2033 * メニューを表示させません。 2034 * マッチしない場合は、表示されます。 2035 * 何も指定しない場合は、ロールの判定みの行われます。 2036 * 2037 * @param umt 逆判定条件 (マッチする場合に、メニューに出さない) 2038 */ 2039 public void setUnmatch( final String umt ) { 2040 unmatch = nval( getRequestParameter( umt ),unmatch ); 2041 } 2042 2043 /** 2044 * 【TAG】メニューに使用する画像ファイルのフォルダを指定します(初期値:{@og.value #MENU_IMG})。 2045 * 2046 * @og.tag 2047 * メニューに使用する画像ファイルのフォルダを指定します。 2048 * 画面IDのキーと一致する画像ファイルを使用します。 2049 * 初期値は、{@og.value #MENU_IMG} です。 2050 * /jspからのフォルダ指定が必要です。 2051 * 2052 * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加) 2053 * 2054 * @param dir メニューに使用する画像ファイルのフォルダ 2055 */ 2056 public void setImageDir( final String dir ) { 2057 imageDir = nval( getRequestParameter( dir ),imageDir ); 2058 } 2059 2060 /** 2061 * 【TAG】画面リンクにボタンを使用するかどうか[true/false]を指定します(初期値:false)。 2062 * 2063 * @og.tag 2064 * 画面リンクをボタンリンク形式で表示するかを指定します。 2065 * falseの場合は、通常のリンクになります。 2066 * 初期値は、false(通常リンク)です。 2067 * 2068 * @og.rev 4.2.1.0 (2008/04/01) 新規登録 2069 * 2070 * @param flag ボタンリンク [true:ボタン形式リンク/false:通常リンク] 2071 */ 2072 public void setUseButton( final String flag ) { 2073 useButton = nval( getRequestParameter( flag ),useButton ); 2074 } 2075 2076 /** 2077 * 【TAG】マトリクスからの遷移先でボタンメニュー表示するかどうか[true/false]を指定します(初期値:false)。 2078 * 2079 * @og.tag 2080 * マトリクスメニューからの遷移先でボタンメニューを表示させるために 2081 * アドレスに付加するリクエスト変数を指定します。 2082 * trueにするとbuttonRequest=trueのリクエスト変数を付けます。 2083 * falseの場合はリクエスト変数を付けません。 2084 * 初期値は、false(プルダウン形式で表示)です。 2085 * 2086 * @og.rev 4.2.1.0 (2008/04/17) 新規登録 2087 * 2088 * @param flag メニュー形式 [true:ボタン形式/false:通常形式] 2089 */ 2090 public void setButtonRequest( final String flag ) { 2091 buttonRequest = nval( getRequestParameter( flag ),buttonRequest ); 2092 } 2093 2094 /** 2095 * 【TAG】標準画面を初期状態で開いた状態で表示するかどうか[true/false]を指定します(初期値:false)。 2096 * 2097 * @og.tag 2098 * 通常expand=trueの状態では、メニューが折りたたまれています。 2099 * このinlineStyle属性をtrueにすると標準画面のスタイルにdisplay:inlineを 2100 * 付加する事で、初期状態でメニューが開いた状態になります。 2101 * expand=falseとの違いは、隠しメニュー及び分類の折りたたみ機能が利用できる事です。 2102 * 初期値は、false(折りたたまれた状態)です。 2103 * 2104 * @og.rev 4.3.3.0 (2008/10/01) 新規 2105 * 2106 * @param flag メニュースタイル [true:開いた状態/false:閉じた状態] 2107 */ 2108 public void setInlineStyle( final String flag ) { 2109 inlineStyle = nval( getRequestParameter( flag ),inlineStyle ); 2110 } 2111 2112 /** 2113 * 【TAG】ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうか[true/false]を指定します(初期値:false)。 2114 * 2115 * @og.tag 2116 * ONELEVEL,NEXTGUI は、QUERY 画面の上部に表示される簡易メニューです。 2117 * この表記は、[画面リンク] 形式のテキスト表示されていますが、画面名称を固定長にするなどの処理を入れるため、 2118 * DIVでフォーマットします。 2119 * 作りは、出力される HTML を確認いただきたいと思います。 2120 * 全体を、<div id="design-onelevel" > で、囲い、画面名称は、<span clas="design-onelevel" > で、囲います。 2121 * これを、標準CSSで、固定幅と背景色、リンクの文字色など書き換えて、体裁を整えます。 2122 * 初期値は、false(従来と同じ)です。 2123 * 2124 * @og.rev 5.5.2.3 (2012/05/15) 新規追加 2125 * 2126 * @param flag DIVタグ処理するか [true:DIVタグ処理をする/false:しない] 2127 */ 2128 public void setUseDivOneLevel( final String flag ) { 2129 useDivOneLevel = nval( getRequestParameter( flag ),useDivOneLevel ); 2130 } 2131 2132 /** 2133 * 画面オブジェクト一覧より、指定されたインデックスより後に実体となる画面ID 2134 * (直リンク、通常メニュー、隠しメニュー※改行メニューは除く)が存在するかを判定します。 2135 * グループスが指定されている場合は、グループで絞り込まれた結果に対して判定を行います。 2136 * 2137 * @og.rev 4.0.0.0 (2007/10/30) 新規追加 2138 * @og.rev 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。 2139 * 2140 * @param guiInfos 画面オブジェクト一覧 2141 * @param idx 検索を開始するインデックス番号 2142 * 2143 * @return 0:実体画面が存在せず 1:全て隠しの分類 2:実体画面 or 通常画面を含む分類 2144 */ 2145 private int guiCheck( final GUIInfo[] guiInfos, final int idx ) { 2146 int flg = 0; 2147 2148 // 実態探し 2149 if( levelCheck( guiInfos[idx] ) > 0 ) { 2150 // グループメニューリンク時の処理 2151 // 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。 2152// if( groups == null ) { flg = 2; } 2153// else { flg = groupCheck( guiInfos[idx] ) ? 2 : 0; } 2154 flg = groupCheck( guiInfos[idx] ) ? 2 : 0; 2155 } 2156 else { 2157 for( int j=idx+1; j<guiInfos.length; j++ ) { 2158 if( !guiInfos[j].isRead() ) { continue; } 2159 if( flg > 1 || guiInfos[j].getLevel() <= guiInfos[idx].getLevel() ) { break; } 2160 2161 // 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。 2162// if( groups == null || groupCheck( guiInfos[j] ) ) { 2163 if( groupCheck( guiInfos[j] ) ) { 2164 if( levelCheck( guiInfos[j] ) > 0 ) { 2165 flg = levelCheck( guiInfos[j] ); 2166 } 2167 } 2168 } 2169 } 2170 2171 return flg; 2172 } 2173 2174 /** 2175 * 指定された画面IDが実体であるか(直リンク、通常メニュー、隠しメニュー※改行メニューは除く)を判定します。 2176 * 2177 * @og.rev 4.0.0.0 (2007/10/30) 新規追加 2178 * @og.rev 4.0.0.0 (2007/11/30) switch に default 追加 2179 * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 2180 * 2181 * @param guiInfo 画面オブジェクト 2182 * 2183 * @return 0:分類 1:実体画面(隠し) 2:実体画面(通常) or 直リンク 2184 */ 2185 private int levelCheck( final GUIInfo guiInfo ) { 2186 int flg = 0; 2187 2188 final String adrs = guiInfo.getAddress(); // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定 2189 2190 switch ( guiInfo.getLevel() ) { 2191 case 2: 2192// final String adrs = guiInfo.getAddress(); 2193 if( adrs != null && adrs.length() > 0 ) { 2194 flg = 2; 2195 } 2196 break; 2197 case 3: 2198// flg = "HYBS_BR".equals( guiInfo.getKey() ) ? flg : 2; break; 2199 flg = "HYBS_BR".equals( adrs ) ? flg : 2; break; 2200 case 4: 2201// flg = "HYBS_BR".equals( guiInfo.getKey() ) ? flg : 1; break; 2202 flg = "HYBS_BR".equals( adrs ) ? flg : 1; break; 2203 default : 2204 flg = 0; break; 2205 } 2206 2207 return flg; 2208 } 2209 2210 /** 2211 * 指定された画面IDが設定されたグループスに含まれるかを判定します。 2212 * 2213 * groups == null か、または、画面IDが設定されたグループスに含まれる場合、true を返します。 2214 * 2215 * @og.rev 4.0.0.0 (2007/10/30) 新規追加 2216 * @og.rev 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。 2217 * 2218 * @param guiInfo 画面オブジェクト 2219 * 2220 * @return groupsが nullか、グループスに含まれるかどうか 2221 */ 2222 private boolean groupCheck( final GUIInfo guiInfo ) { 2223 // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している 2224 if( groups == null ) { return true; } 2225 else { 2226 boolean flg = false; 2227 2228 // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop 2229 for( final String grp : groups ) { 2230 if( guiInfo.isGroupIn( grp ) ) { 2231// for( int k=0; k<groups.length; k++ ) { 2232// if( guiInfo.isGroupIn( groups[k] ) ) { 2233 flg = true; 2234 break; 2235 } 2236 } 2237 2238 return flg; 2239 } 2240 } 2241 2242 /** 2243 * このオブジェクトの文字列表現を返します。 2244 * 基本的にデバッグ目的に使用します。 2245 * 2246 * @return このクラスの文字列表現 2247 * @og.rtnNotNull 2248 */ 2249 @Override 2250 public String toString() { 2251 return ToString.title( this.getClass().getName() ) 2252 .println( "VERSION" ,VERSION ) 2253 .println( "menuType" ,menuType ) 2254 .println( "expand" ,expand ) 2255 .println( "groups" ,groups ) 2256 .println( "selClassify" ,selClassify ) 2257 .println( "href" ,href ) 2258 .println( "target" ,target ) 2259 .println( "imageOnly" ,imageOnly ) 2260 .println( "sideCount" ,sideCount ) 2261 .println( "minCellCount" ,minCellCount ) 2262 .println( "maxCellCount" ,maxCellCount ) 2263 .println( "cache" ,cache ) 2264 .println( "mscKey" ,mscKey ) 2265// .println( "multiSessionCheck" ,multiSessionCheck ) // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定) 2266 .println( "useButton" ,useButton ) 2267 .println( "buttonRequest" ,buttonRequest ) 2268 .println( "MENU_TYPE" ,MENU_TYPE_SET ) // 6.4.3.4 (2016/03/11) 2269 .println( "Other..." ,getAttributes().getAttribute() ) 2270 .fixForm().toString() ; 2271 } 2272}