intra-mart Accel Platform テーマ仕様書 第9版 2021-08-01

ユーティリティプラグイン

ここではユーティリティプラグインの作成の概要と、サンプルプログラムについて説明します。

コラム

スマートフォン版のユーティリティメニューの設定に関しては「 設定ファイルリファレンス 」-「 SP版ユーティリティメニュー設定 」を参照してください。

ユーティリティプラグイン作成の概要

ここではユーティリティプラグインの作成の概要を説明します。

ユーティリティプラグインは、PluginManager が管理するプラグインとして実装します。 このプラグインは以下の要素で構成されます。

  • plugin.xml
  • プラグイン本体

この他に必要であれば、以下のような要素を追加します。

  • 処理を実行するサーバ側のプログラムを呼び出すための CSJS
  • 処理を実行するサーバ側のプログラム
    • Java
    • JSSP
  • 設定ファイル
    • ルータの設定ファイル
    • 多言語ファイル

プラグイン本体

プラグイン本体は、UtilityItemProvider インタフェースを実装したクラスとして作ります。

サブメニューを持つプラグインを作成する場合、UtilityItemProvider#getChildrenを実装し、UtilityItemProvider を実装したクラスのインスタンスを返します。

プラグインが呼び出されると、ul > li > a のような DOM が構築されます。 対象のリンクをクリックした際の動作は a タグの href で表現したり、a タグに id を割り振り、その id で何らかの処理を行うように実装します。

  • isVisible
  • getLabel
  • getUrl
  • scriptSource
  • getChildren
  • toListString

plugin.xml

PluginManager が管理する plugin.xml を作成します。

extension 要素の point 属性には jp.co.intra_mart.foundation.ui.theme.utility.item を指定してください。

その他の要素、属性については PluginManager の API リファレンス を参照してください。

処理を実行するサーバ側のプログラムを呼び出すための CSJS

ユーティリティメニューをクリックした際、クライアント側で動作するロジックを実装します。 オプショナルです。

処理を実行するサーバ側のプログラム

ユーティリティメニューをクリックした際、サーバ側で動作するロジックを実装します。 オプショナルです。

設定ファイル

必要であれば、以下のようなファイルを作成します。

  • ルータの設定ファイル
  • 多言語ファイル

サンプルプログラム

ここでは、ユーティリティプラグインのサンプルとして、ログインユーザのロケールを切り替えるプラグインを作成します。

このプラグインは、UtilityItemProvider を実装したクラスとして実装します。 メニューは、現在のロケールを表示する親メニューと、選択可能なロケールの一覧を表示するサブメニューとで構成します。

ロケール切り替えのサーバ側のプログラムは、既存のロケール切り替えの仕組みを流用します。

  • プラグイン本体
  • plugin.xml
  • 処理を実行するサーバ側のプログラムを呼び出すための CSJS
  • 処理を実行するサーバ側のプログラム
    • 既存のロケール切り替えの仕組みを流用します。

プラグイン本体

jp.co.intra_mart.sample.LocaleItemProvider として実装します。 以下の必要なメソッドを実装します。

  • isVisible
  • getLabel
  • getUrl
  • scriptSource
  • getChildren
  • toListString

isVisible

ここでは認証済ユーザであればこのプラグインを表示できるようにします。

public boolean isVisible() {
     AccountContext context = Contexts.get(AccountContext.class);
     return context.isAuthenticated();
}

getLabel

ここでは認証済ユーザのロケールを表示します。

アカウントコンテキストに格納されているロケールを表示します。 表示する際にエスケープを行います。

public String getLabel() throws JspException {
    AccountContext context = Contexts.get(AccountContext.class);
    Locale locale = context.getLocale();
    String name = locale.getDisplayName(locale);
    return Util.escape(name, Escaping.STRICT_HTML);
}

getUrl

ここでは表示だけを行い、処理はしないため null を返します。

public String getUrl() throws JspException {
    return null;
}

scriptSource

ここでは、CSJS のパスを返します。

UserUtilityTag、プラグインには CSJS の実装を直接 HTML に出力する方法がないため、外部ファイルに実装した関数を呼び出すという方法を採ります。 このメソッドが返すパスに、CSJS の実装を記述します。

public String scriptSource() {
    return "sample/js/changeLocale.js";
}

getChildren

ここでは、システムに登録されているロケールの一覧を返します。 また、返すクラスは UtilityItemProvider を実装したクラスとして実装します。

public List<UtilityItemProvider> getChildren() throws JspException {
    final List<UtilityItemProvider> children = new ArrayList<UtilityItemProvider>();
    // システムロケールの一覧を作成します。
    LocaleInfo[] localeInfos = SystemLocale.getLocaleInfos();
    for (LocaleInfo localeInfo: localeInfos) {
        children.add(new LocaleListItemProvider(localeInfo));
    }
    return children;
}

toListString

このプラグインが返す HTML を生成します。

ul > li > a となるように実装します。また、サブメニューを ul > li の 中の ul として返すように実装します。

public String toListString() throws JspException {
    final StringBuilder buf = new StringBuilder();
    final String url = getUrl() == null ? StringUtil.EMPTY_STRING : "href=\"" + getUrl() + "\"";
    buf.append("<li><a ").append(url).append(">").append(getLabel()).append("</a>");
    if (getChildren() != null) {
        buf.append("<ul>");
        for (final UtilityItemProvider item : getChildren()) {
            buf.append(item.toListString());
        }
        buf.append("</ul>");
    }
    buf.append("</li>");
    return buf.toString();
}

サブメニューの項目の一つ一つはこのクラスで実装します。

private static class LocaleListItemProvider implements UtilityItemProvider {
    private LocaleInfo localeInfo;
    public LocaleListItemProvider(final LocaleInfo localeInfo) {
        this.localeInfo = localeInfo;
    }
}

ラベルとして、システムロケールの一つを表示します。インスタンス化した際のロケールの値を表示します。

public String getLabel() throws JspException {
    return Util.escape(this.localeInfo.getDisplayName(), Escaping.STRICT_HTML);
}

クリックした際の URL を返します。ここで、CSJS の関数を呼び出します。

 public String getUrl() throws JspException {
    return String.format("javascript:changeLocale('%s');", this.localeInfo.getLocale());
}

HTML として、li タグを返します。

public String toListString() throws JspException {
    final StringBuilder buf = new StringBuilder();
    final String url = "href=\"" + getUrl() + "\"";
    buf.append("<li><a ").append(url).append(">");
    buf.append(getLabel()).append("</a>");
    buf.append("</li>");
    return buf.toString();
}

plugin.xml

プラグインの設定を記述します。

extension 要素の point 属性に jp.co.intra_mart.foundation.ui.theme.utility.item を指定します。 また、item 要素の classname 属性に、プラグイン本体のクラス名を指定します。

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <extension point="jp.co.intra_mart.foundation.ui.theme.utility.item">
      <item
        id="sample_localeitemprovider"
        name="localeitemprovider"
        classname="jp.co.intra_mart.sample.LocaleItemProvider"
        version="1.0"
        rank="1"
        enable="true"
        />
    </extension>
</plugin>

処理を実行するサーバ側のプログラムを呼び出すための CSJS

ここでは、簡単のため既存のロケール切り替えの仕組みを呼び出すような実装を行います。

プラグイン本体の、scriptSource メソッドが返す値である sample/js/changeLocale.js に下記の実装を記述します。 アクセス先の user/settings/locale/update_locale は、ルータの設定、サーバ側のロジックの実装などはテナント管理モジュールで実装されています。

function changeLocale(locale) {
    (function($, locale) {
        var form = $('<form/>')
            .attr('id', 'sampleform')
            // 既存のロジックを呼び出します。
            .attr('action', 'user/settings/locale/update_locale')
            .attr('method','POST');
        var locale = $('<input/>')
            .attr('type','hidden')
            .attr('name','locale')
            .attr('value',locale);
        form.append(locale);
        form.appendTo('body');
        imuiAjaxSubmit('#sampleform', 'POST', 'json', 'home', []);
    })(jQuery, locale);
}

処理を実行するサーバ側のプログラム

このサンプルでは実装を行いません。

サーバ側のロジックはテナント管理モジュールで実装されています。

実行例

このプラグインをデプロイすると以下のような画面が表示され、ロケールを切り替えることができます。

../../_images/plugin.png

サンプルプログラムの実装例

プラグイン本体

src/main/java/jp/co/intra_mart/sample/LocaleItemProvider.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package jp.co.intra_mart.sample;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.servlet.jsp.JspException;

import jp.co.intra_mart.common.aid.jdk.java.lang.StringUtil;
import jp.co.intra_mart.foundation.context.Contexts;
import jp.co.intra_mart.foundation.context.model.AccountContext;
import jp.co.intra_mart.foundation.i18n.locale.LocaleInfo;
import jp.co.intra_mart.foundation.i18n.locale.SystemLocale;
import jp.co.intra_mart.foundation.ui.tags.theme.UtilityItemProvider;
import jp.co.intra_mart.system.ui.util.Util;

import org.jamon.escaping.Escaping;

public class LocaleItemProvider implements UtilityItemProvider {
    private static class LocaleListItemProvider implements UtilityItemProvider {
        private LocaleInfo localeInfo;

        /**
         * コンストラクタ。
         * @param localeInfo ロケール情報
         */
        public LocaleListItemProvider(final LocaleInfo localeInfo) {
            this.localeInfo = localeInfo;
        }

        /**
         * サブメニューを返します。
         * @return null:サブメニューはありません。
         * @throws JspException
         */
        @Override
        public List<UtilityItemProvider> getChildren() throws JspException {
            return null;
        }

        /**
         * このメニューのラベルを返します。
         * @return ロケール名
         * @throws JspException エラーが発生したときにスローします。
         */
        @Override
        public String getLabel() throws JspException {
            return Util.escape(this.localeInfo.getDisplayName(), Escaping.STRICT_HTML);
        }

        /**
         * このメニューをクリックしたときの URL を返します。
         * <br/>
         * このメニューをクリックするとロケールを選択したことになるので、CSJS のロケール変更リクエストを送信するように実装します。
         * @throws JspException エラーが発生したときにスローします。
         */
        @Override
        public String getUrl() throws JspException {
            return String.format("javascript:changeLocale('%s');", this.localeInfo.getLocale());
        }

        /**
         * このUtilityItemProviderを表示するかどうかを返します。
         * @return true:表示する
         */
        @Override
        public boolean isVisible() {
            return true;
        }

        /**
         * このUtilityItemProviderが使用する外部CSJSのパスを返します。
         * @return null:外部CSJSを使用しません。
         */
        @Override
        public String scriptSource() {
            return null;
        }

        /**
         * このUtilityItemProviderのHTML表現を返します。
         * <br/>
         * 親メニューのリストの子要素とします。
         * @return メニュー項目とする liタグ
         * @throws JspException
         */
        @Override
        public String toListString() throws JspException {
            final StringBuilder buf = new StringBuilder();

            final String url = "href=\"" + getUrl() + "\"";
            buf.append("<li><a ").append(url).append(">");
            buf.append(getLabel()).append("</a>");
            buf.append("</li>");
            return buf.toString();
        }

    }

    /**
     * 子メニューのリストを返します。
     * @return List 子メニューのリスト
     * @throws JspException エラーが発生したときにスローします。
     */
    @Override
    public List<UtilityItemProvider> getChildren() throws JspException {
        final List<UtilityItemProvider> children = new ArrayList<UtilityItemProvider>();
        LocaleInfo[] localeInfos = SystemLocale.getLocaleInfos();

        for (LocaleInfo localeInfo: localeInfos) {
            children.add(new LocaleListItemProvider(localeInfo));
        }

        return children;
    }

    /**
     * このプラグインを表示したときのラベルを返します。
     * @return ラベル
     * @throws JspException エラーが発生したときにスローします。
     */
    @Override
    public String getLabel() throws JspException {
        AccountContext context = Contexts.get(AccountContext.class);
        Locale locale = context.getLocale();
        String name = locale.getDisplayName(locale);

        return Util.escape(name, Escaping.STRICT_HTML);
    }

    /**
     * クリックしたときの遷移先 URL を返します。
     * @return null
     * @throws JspException エラーが発生したときにスローします。
     */
    @Override
    public String getUrl() throws JspException {
        return null;
    }

    /**
     * ロケールの切り替え項目を表示するかどうかを決定します。
     * <br/>
     * 認証済ユーザであれば切り替え項目を表示します。
     * @return 切り替え項目を表示する場合は true, しない場合は false
     */
    @Override
    public boolean isVisible() {
        AccountContext context = Contexts.get(AccountContext.class);
        return context.isAuthenticated();
    }

    /**
     * このプラグインを動作させるのにCSJSが必要な場合そのパスを返します。
     */
    @Override
    public String scriptSource() {
        return "sample/js/changeLocale.js";
    }

    /**
     * このUtilityItemProviderのHTML表現を返します。
     * @return liタグ
     */
    @Override
    public String toListString() throws JspException {
        final StringBuilder buf = new StringBuilder();

        final String url = getUrl() == null ? StringUtil.EMPTY_STRING : "href=\"" + getUrl() + "\"";
        buf.append("<li><a ").append(url).append(">").append(getLabel()).append("</a>");
        if (getChildren() != null) {
            buf.append("<ul>");
            for (final UtilityItemProvider item : getChildren()) {
                buf.append(item.toListString());
            }
            buf.append("</ul>");
        }
        buf.append("</li>");
        return buf.toString();
    }
}

plugin.xml

src/main/plugin/jp.co.intra_mart.sample.locale_item_provider/plugin.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<extension point="jp.co.intra_mart.foundation.ui.theme.utility.item">
  <item
    id="sample_localeitemprovider"
    name="localeitemprovider"
    classname="jp.co.intra_mart.sample.LocaleItemProvider"
    version="1.0"
    rank="1"
    enable="true"
    />
</extension>
</plugin>

CSJS

src/main/public/sample/js/changeLocale.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function changeLocale(locale) {
    (function($, locale) {
        var form = $('<form/>')
            .attr('id', 'sampleform')
            .attr('action', 'user/settings/locale/update_locale')
            .attr('method','POST');
        var locale = $('<input/>')
            .attr('type','hidden')
            .attr('name','locale')
            .attr('value',locale);
        form.append(locale);

        form.appendTo('body');
        imuiAjaxSubmit('#sampleform', 'POST', 'json', 'home', []);
    })(jQuery, locale);
}

フォルダ構成

├── message.properties
├── message_en.properties
├── message_ja.properties
├── message_zh_CN.properties
├── module.xml
└── src
    ├── main
    │   ├── conf
    │   │   ├── message
    │   │   ├── routing-jssp-config
    │   │   └── routing-service-config
    │   ├── generated
    │   ├── java
    │   │   └── jp
    │   │       └── co
    │   │           └── intra_mart
    │   │               └── sample
    │   │                   └── LocaleItemProvider.java
    │   ├── jssp
    │   │   └── src
    │   ├── plugin
    │   │   └── jp.co.intra_mart.sample.locale_item_provider
    │   │       └── plugin.xml
    │   ├── public
    │   │   └── sample
    │   │       └── js
    │   │           └── changeLocale.js
    │   ├── resources
    │   ├── schema
    │   ├── storage
    │   │   ├── public
    │   │   └── system
    │   └── webapp
    └── test
        ├── conf
        │   ├── message
        │   ├── routing-jssp-config
        │   └── routing-service-config
        ├── generated
        ├── java
        ├── jssp
        │   └── src
        ├── plugin
        ├── public
        ├── resources
        ├── schema
        ├── storage
        │   ├── public
        │   └── system
        └── webapp