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