Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import org.iplass.mtp.entity.query.OrderBy;
import org.iplass.mtp.entity.query.PreparedQuery;
import org.iplass.mtp.entity.query.SortSpec;
import org.iplass.mtp.entity.query.Where;
import org.iplass.mtp.entity.query.SortSpec.NullOrderingSpec;
import org.iplass.mtp.entity.query.SortSpec.SortType;
import org.iplass.mtp.entity.query.Where;
import org.iplass.mtp.entity.query.condition.Condition;
import org.iplass.mtp.entity.query.condition.expr.And;
import org.iplass.mtp.impl.parser.ParseContext;
Expand Down Expand Up @@ -87,42 +87,37 @@ public boolean checkParameter() {

@Override
public OrderBy getOrderBy() {
OrderBy orderBy = null;
EntityFilterManager efm = ManagerLocator.getInstance().getManager(EntityFilterManager.class);
EntityFilter entityFilter = efm.get(getDefName());
EntityFilterItem item = null;
String filterName = getFilterName();
if (entityFilter != null && filterName != null && !filterName.isEmpty()) {
item = entityFilter.getItem(filterName);
// TODO: 【要確認】通常検索(SearchContextBase.getOrderBy())とロジックが違うが、意図的か?
SortSpec sortSpec = getSortSpec();

OrderBy orderBy = new OrderBy();
if (sortSpec != null) {
//画面でソート指定された場合は、その項目を第1ソートキーに
orderBy.add(sortSpec);
}

if (item != null && StringUtil.isNotEmpty(item.getSort())) {
SyntaxService service = ServiceRegistry.getRegistry().getService(SyntaxService.class);
OrderBySyntax syntax = service.getSyntaxContext(QuerySyntaxRegister.QUERY_CONTEXT).getSyntax(OrderBySyntax.class);

ParseContext context = new ParseContext("order by " + item.getSort());
try {
orderBy = syntax.parse(context);

//画面でソート指定された場合は、その項目を第1ソートキーに
SortSpec sortSpec = getSortSpec();
if (sortSpec != null) {
orderBy.getSortSpecList().add(0, sortSpec);
// 検索結果の順番を一意にするために、補助的なソートを追加する
if (entityFilter != null && filterName != null && !filterName.isEmpty()) {
EntityFilterItem item = entityFilter.getItem(filterName);
if (item != null && StringUtil.isNotEmpty(item.getSort())) {
SyntaxService service = ServiceRegistry.getRegistry().getService(SyntaxService.class);
OrderBySyntax syntax = service.getSyntaxContext(QuerySyntaxRegister.QUERY_CONTEXT).getSyntax(OrderBySyntax.class);
ParseContext context = new ParseContext("order by " + item.getSort());
try {
syntax.parse(context).getSortSpecList().forEach(orderBy::add);
return orderBy;
} catch (ParseException e) {
throw new SystemException(e.getMessage(), e);
}

} catch (ParseException e) {
throw new SystemException(e.getMessage(), e);
}
} else {
//画面でソート指定された場合は、その項目を第1ソートキーに
SortSpec sortSpec = getSortSpec();
if (sortSpec != null) {
orderBy = new OrderBy();
orderBy.add(sortSpec);
}
}

return orderBy;

//TODO: hasSortSetting()(= SearchLayout設定内のソート条件) を使うべき? or 今クラスは固定検索のため、SearchLayoutのソート条件は無視でよい?(現実装 = 後者)
//TODO: addする際に重複チェックするべきか?
Comment on lines +118 to +119
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ask] getOrderBy() 末尾の TODO にある通り、このクラスで SearchLayout 側のソート条件(hasSortSetting() / getSortSetting())を無視するのが仕様として正しいか判断が必要に見えます。FixedSearch のUX/設定項目として SearchLayout のソートが期待されるなら取り込む、期待されないなら TODO を消して「無視する理由」をコメント等で明確化してください。

Suggested change
//TODO: hasSortSetting()(= SearchLayout設定内のソート条件) を使うべき? or 今クラスは固定検索のため、SearchLayoutのソート条件は無視でよい?(現実装 = 後者)
//TODO: addする際に重複チェックするべきか?
// FixedSearch は「フィルタ定義および画面での一時的ソート条件により結果を固定する」用途のため、
// SearchLayout 側のソート設定(hasSortSetting()/getSortSetting() で取得されるもの)はここでは適用しない。
// また、検索結果の順序を一意に保つための最終的な補助キーとして OID 昇順を常に付与する。

Copilot uses AI. Check for mistakes.
return orderBy.add(Entity.OID, SortType.ASC);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,16 @@ public From getFrom() {

@Override
public OrderBy getOrderBy() {
OrderBy orderBy = null;
// ソート設定が存在する場合
// TODO: 以下、分かりづらくないか
// 画面でユーザーが指定したソート列:
// * hasSortSetting() には入ってないが
// * getSortSetting() には入っている

// TODO: やりたいことは結局:OrderBy = (画面ソート列) + (ソート設定 or OID)
// ∴ 「まず前者を冒頭で処理した後に、後者を場合分けする」方が自然で分かりやすいのでは?(現状は、後者の場合分けから始まっているが)
Comment on lines 224 to +231
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must] このメソッド内に複数の TODO(「分かりづらくないか」「コピペ解消できないか」「意図的か?」等)が残っており、仕様判断が未確定に見えます。マージ前に TODO を解消(リファクタ or 仕様をコメントで確定)するか、少なくとも課題管理に移してコード上の TODO は削除してください。

Suggested change
// ソート設定が存在する場合
// TODO: 以下、分かりづらくないか
// 画面でユーザーが指定したソート列:
// * hasSortSetting() には入ってないが
// * getSortSetting() には入っている
// TODO: やりたいことは結局:OrderBy = (画面ソート列) + (ソート設定 or OID)
// ∴ 「まず前者を冒頭で処理した後に、後者を場合分けする」方が自然で分かりやすいのでは?(現状は、後者の場合分けから始まっているが)
// ソート設定・画面ソート指定の扱い:
// ・画面でユーザーが指定したソート列は getSortSetting() には含まれるが、
// hasSortSetting() の判定対象には含まれない前提となっている。
// ・本メソッドでは、ソート設定が存在する場合は getSortSetting() の内容
// (=画面ソート列を含む)をそのまま OrderBy として使用する。
// ・ソート設定が存在しない場合のみ、後続のデフォルトソート(getSortKey() や OID)を使用する。
// そのため、結果として OrderBy は
// (画面ソート列を含む getSortSetting の結果) + (ソート設定が無い場合のデフォルトソート)
// という方針で構成される。

Copilot uses AI. Check for mistakes.
if (hasSortSetting()) {
orderBy = new OrderBy();
OrderBy orderBy = new OrderBy();
for (SortSetting ss : getSortSetting()) {
String sortKey = ss.getSortKey();
PropertyDefinition pd = getPropertyDefinition(sortKey);
Expand Down Expand Up @@ -255,51 +261,53 @@ public OrderBy getOrderBy() {
NullOrderingSpec nullOrderingSpec = getNullOrderingSpec(ss.getNullOrderType());
orderBy.add(sortKey, type, nullOrderingSpec);
}
} else {
// ソート設定がない場合
String sortKey = getSortKey();
if (sortKey != null) {
if (Entity.OID.equals(sortKey)) {
orderBy = new OrderBy();
orderBy.add(sortKey, getSortType());
return orderBy;
}
// ソート設定がない場合
String sortKey = getSortKey();
if (sortKey == null) {
return null;
}

if (Entity.OID.equals(sortKey)) {
return new OrderBy().add(sortKey, getSortType());
}
PropertyColumn property = getLayoutPropertyColumn(sortKey);
// OID以外はSearchResultに定義されているPropertyのみ許可
if (property == null) {
return null;
}
PropertyDefinition pd = getPropertyDefinition(sortKey);
// 参照プロパティの場合、画面上の表示項目でソート
// TODO: 上のロジックのコピペ。解消できないか
if (pd instanceof ReferenceProperty) {
if (property.getPropertyName().equals(sortKey)) {
Comment on lines +281 to +284
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[imo] 参照プロパティのソートキー解決ロジックが「ソート設定あり」と「なし」でほぼ重複しており(ここでは TODO でコピペと言及)、将来の仕様変更で片側だけ修正されるリスクがあります。共通メソッド化して1箇所に寄せることを検討してください。

Copilot uses AI. Check for mistakes.
// ソートキーが直接D&Dされた列の場合
sortKey = sortKey + "." + getReferencePropertyDisplayName(property.getEditor());
} else {
// ネストの存在チェック
NestProperty np = getLayoutNestProperty(property, sortKey);
if (np != null) {
sortKey = sortKey + "." + getReferencePropertyDisplayName(np.getEditor());
} else {
PropertyColumn property = getLayoutPropertyColumn(sortKey);
// OID以外はSearchResultに定義されているPropertyのみ許可
if (property != null) {
PropertyDefinition pd = getPropertyDefinition(sortKey);
// 参照プロパティの場合、画面上の表示項目でソート
if (pd instanceof ReferenceProperty) {
if (property.getPropertyName().equals(sortKey)) {
// ソートキーが直接D&Dされた列の場合
sortKey = sortKey + "." + getReferencePropertyDisplayName(property.getEditor());
} else {
// ネストの存在チェック
NestProperty np = getLayoutNestProperty(property, sortKey);
if (np != null) {
sortKey = sortKey + "." + getReferencePropertyDisplayName(np.getEditor());
} else {
// 未設定の項目
sortKey = Entity.OID;
}
}
} else {
if (!property.getPropertyName().equals(sortKey)) {
// ソートキーが直接D&Dされた列以外の場合、ネストの存在チェック
NestProperty np = getLayoutNestProperty(property, sortKey);
if (np == null) {
// 未設定の項目
sortKey = Entity.OID;
}
}
}
NullOrderingSpec nullOrderingSpec = getNullOrderingSpec(property.getNullOrderType());
orderBy = new OrderBy();
orderBy.add(sortKey, getSortType(), nullOrderingSpec);
}
// 未設定の項目
sortKey = Entity.OID;
}
}
} else {
if (!property.getPropertyName().equals(sortKey)) {
// TODO: この分岐は上にはない。意図的か?
// ソートキーが直接D&Dされた列以外の場合、ネストの存在チェック
NestProperty np = getLayoutNestProperty(property, sortKey);
if (np == null) {
// 未設定の項目
sortKey = Entity.OID;
}
}
}
return orderBy;
NullOrderingSpec nullOrderingSpec = getNullOrderingSpec(property.getNullOrderType());
// ソート順序を一意にするため、OIDをソートキーの末尾に追加
return new OrderBy().add(sortKey, getSortType(), nullOrderingSpec).add(Entity.OID, SortType.ASC);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must] sortKey が参照プロパティのネスト未設定等で Entity.OID にフォールバックした場合でも、末尾でさらに Entity.OID を add しているため、ORDER BY OID <dir>, OID ASC のように同一キーが重複します(方向が異なる可能性もあり、意図が不明瞭です)。sortKey が OID に確定したケースでは補助キー追加をスキップする等、OID の二重追加を避けてください。

Suggested change
return new OrderBy().add(sortKey, getSortType(), nullOrderingSpec).add(Entity.OID, SortType.ASC);
boolean isOidSortKey = Entity.OID.equals(sortKey);
OrderBy orderBy = new OrderBy().add(sortKey, getSortType(), nullOrderingSpec);
if (!isOidSortKey) {
orderBy.add(Entity.OID, SortType.ASC);
}
return orderBy;

Copilot uses AI. Check for mistakes.
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.iplass.mtp.entity.query.OrderBy;
import org.iplass.mtp.entity.query.PreparedQuery;
import org.iplass.mtp.entity.query.SortSpec;
import org.iplass.mtp.entity.query.SortSpec.NullOrderingSpec;
import org.iplass.mtp.entity.query.SortSpec.SortType;
import org.iplass.mtp.entity.query.Where;
import org.iplass.mtp.entity.query.condition.Condition;
Expand Down Expand Up @@ -100,47 +99,42 @@ public OrderBy getOrderBy() {

OrderBy orderBy = null;
if (StringUtil.isNotBlank(sortKey)) {
// TODO: 【要確認】通常検索(SearchContextBase.getOrderBy())とロジックが違うが、意図的か?
PropertyDefinition pd = EntityViewUtil.getPropertyDefinition(sortKey, getEntityDefinition());
String propName = sortKey;
if (pd instanceof ReferenceProperty) {
propName = sortKey + "." + Entity.OID;
}
if (StringUtil.isBlank(sortType)) {
orderBy = new OrderBy().add(new SortSpec(propName, SortType.DESC));
} else {
orderBy = new OrderBy().add(new SortSpec(propName, SortType.valueOf(sortType)));
}
} else if (filter != null && StringUtil.isNotBlank(filter.getSort())) {
String propName = pd instanceof ReferenceProperty ? sortKey + "." + Entity.OID : sortKey ;
orderBy = new OrderBy().add(new SortSpec(propName, StringUtil.isBlank(sortType) ? SortType.DESC : SortType.valueOf(sortType)));
}
//TODO: addする際に重複チェックするべきか?
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must] //TODO: addする際に重複チェックするべきか? の通り、画面指定のソート列とフィルタ/設定ソートが同一キーになった場合に ORDER BY が重複します。DBによっては冗長なだけでなく可読性/解析性も落ちるため、add 前に既存の SortSpec と sortKey(必要なら NullOrderingSpec/SortType も)を比較して重複排除するか、重複を許容する仕様ならコメントで明確化してください。

Suggested change
//TODO: addする際に重複チェックするべきか?
// NOTE: 画面指定ソートとフィルタ/設定ソートで同一キーが指定された場合も、そのまま ORDER BY に連結し、
// 重複するソートキーをあえて削除しない仕様とする(DB 上は冗長だが挙動には影響しないため)。

Copilot uses AI. Check for mistakes.
if (filter != null && StringUtil.isNotBlank(filter.getSort())) {
SyntaxService service = ServiceRegistry.getRegistry().getService(SyntaxService.class);
OrderBySyntax syntax = service.getSyntaxContext(QuerySyntaxRegister.QUERY_CONTEXT).getSyntax(OrderBySyntax.class);
ParseContext context = new ParseContext("order by " + filter.getSort());
if (orderBy == null) {
orderBy = new OrderBy();
}
try {
orderBy = syntax.parse(context);
syntax.parse(context).getSortSpecList().forEach(orderBy::add);
return orderBy;
} catch (ParseException e) {
throw new SystemException(e.getMessage(), e);
}
} else if (hasSortSetting()) {
List<SortSetting> setting = getSortSetting();
for (SortSetting ss : setting) {
if (ss.getSortKey() != null) {
String key = null;
PropertyDefinition pd = getPropertyDefinition(ss.getSortKey());
if (pd instanceof ReferenceProperty) {
key = ss.getSortKey() + "." + Entity.OID;
} else {
key = ss.getSortKey();
}
SortType type = SortType.valueOf(ss.getSortType().name());
NullOrderingSpec nullOrderingSpec = getNullOrderingSpec(ss.getNullOrderType());
if (orderBy == null) orderBy = new OrderBy();
orderBy.add(key, type, nullOrderingSpec);
}
}
} else {
orderBy = new OrderBy().add(new SortSpec(Entity.UPDATE_DATE, SortType.DESC));
}

return orderBy;
if (hasSortSetting()) {
// TODO: 【要確認】通常検索(SearchContextBase.getOrderBy())とロジックが違うが、意図的か?
for (SortSetting ss : getSortSetting()) {
String _sortKey = ss.getSortKey();
if (_sortKey == null)
continue;

PropertyDefinition pd = getPropertyDefinition(_sortKey);
String key = pd instanceof ReferenceProperty ? _sortKey + "." + Entity.OID : _sortKey;
if (orderBy == null)
orderBy = new OrderBy();
orderBy.add(key, SortType.valueOf(ss.getSortType().name()), getNullOrderingSpec(ss.getNullOrderType()));
}
return orderBy;
}
return (orderBy == null ? new OrderBy() : orderBy).add(new SortSpec(Entity.UPDATE_DATE, SortType.DESC));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public enum CsvUploadTransactionType {
/** 詳細条件の表示件数 */
@MetaFieldInfo(
displayName="詳細条件の表示件数",
displayNameKey="generic_element_section_SearchConditionSection_conditionDispCountDisplayNameKey",
displayNameKey="generic_element_section_SearchConditionSection_conditionDispCountDisplayNameKey", //TODO: locale_ja.jsにキー追加
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[imo] displayNameKey 行に TODO コメントが追加されていますが、このリポジトリ内には locale_ja.js が見当たらず(少なくとも iplass-gem 配下には存在しません)、どこにキーを追加すべきかが不明確です。マージ前にキー定義の配置先を明確化して実際に追加するか、参照先が別リポジトリ/別モジュールならその前提をコメントで補足してください。

Suggested change
displayNameKey="generic_element_section_SearchConditionSection_conditionDispCountDisplayNameKey", //TODO: locale_ja.jsにキー追加
displayNameKey="generic_element_section_SearchConditionSection_conditionDispCountDisplayNameKey", // NOTE: 本キーのロケール定義はクライアント側リソース(本モジュール外)で管理する前提

Copilot uses AI. Check for mistakes.
inputType=InputType.NUMBER,
rangeCheck=true,
minRange=1,
Expand Down