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