Skip to content
Merged
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
@@ -0,0 +1,50 @@
# Erlang code review — #2993 PSSearchDialog rawtypes

**Reviewer persona:** Erlang (independent of implementer)
**Change class:** Desktop Content Explorer Swing dialog rawtypes / generics cleanup (tech-debt)
**Date:** 2026-08-11
**Branch:** `fix/issue-2993-pssearchdialog-rawtypes`

## Scope reviewed

| Path | Role |
|------|------|
| `modules/DesktopContentExplorer/.../PSSearchDialog.java` | Parameterize ctor/field Maps + Iterators; extract pure helpers |
| `modules/DesktopContentExplorer/.../PSSearchDialogTest.java` | Behavioral unit tests for helpers |

**Explicitly out of scope:** `PSFolderAclEditorDialog` (#2439), `PSOptionManager` (next residual).

## Verdict

**PASS** — safe to commit / open PR.

## Checklist

| Gate | Result | Notes |
|------|--------|-------|
| Bugs / behavior change | Pass | Types only; display-format map and synonym char scan logic preserved |
| Unit tests for new/changed logic | Pass | 9 tests on package-private helpers |
| Cross-platform paths | N/A | No path/file I/O changes |
| Change-class companions | Pass | Prior peer #2939 pattern (typed dialog + helper tests); module suite green |
| Product docs | N/A | Pure compiler tech-debt |
| API / reverse-deps (C2) | Pass | Ctor Maps now typed; sole call sites in `PSActionManager` already pass `Map<?, ?>` + `Map<String, PSContentEditorFieldCataloger>` |
| Copyright on new files | Pass | 2026 Intersoft header on test |

## Findings

None (no bugs / missing behavioral tests / non-portable I/O).

## Build evidence

```text
cd modules/DesktopContentExplorer
../../mvnw.cmd clean install
→ BUILD SUCCESS
→ Tests run: 139, Failures: 0, Errors: 0, Skipped: 0
```

## Residual note

Module still has rawtypes elsewhere (e.g. `PSOptionManager`); not part of this PR-sized slice.

> Co-Authored by Grok Build using grok-4.5 with agent main.
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ public PSSearchDialog(
PSSearchViewActionManager mgr,
PSRemoteCataloger cataloger,
PSNode searchNode,
Map filterMap,
Map<?, ?> filterMap,
boolean isNewSearch,
boolean isRcSearch,
PSSearchConfig searchConfig,
Map searchableFieldsCache,
Map<String, PSContentEditorFieldCataloger> searchableFieldsCache,
URL codeBase)
throws PSCmsException {
super(parent, mgr.getApplet().getResourceString(PSSearchDialog.class, "Content Search"));
Expand Down Expand Up @@ -224,11 +224,12 @@ public PSSearchDialog(
* @throws PSCmsException if an error occurs.
*/
private void initFieldCatalog(
int controlflags, PSRemoteCataloger cataloger, Map searchableFieldsCache, URL codeBase)
int controlflags,
PSRemoteCataloger cataloger,
Map<String, PSContentEditorFieldCataloger> searchableFieldsCache,
URL codeBase)
throws PSCmsException {
Set<String> fieldNames = new HashSet<String>();
Iterator fields = m_search.getFields();
while (fields.hasNext()) fieldNames.add(((PSSearchField) (fields.next())).getFieldName());
Set<String> fieldNames = collectSearchFieldNames(m_search.getFields());

if (searchableFieldsCache == null) {
if (m_applet.isDebug()) log.debug("Load searchableFields no cache");
Expand All @@ -238,7 +239,7 @@ private void initFieldCatalog(
// key is the combination of "code base" and the "control flags"
String key = codeBase.toString() + "@" + controlflags;

m_fieldCatalog = (PSContentEditorFieldCataloger) searchableFieldsCache.get(key);
m_fieldCatalog = searchableFieldsCache.get(key);
if (m_fieldCatalog == null) {
if (m_applet.isDebug()) log.debug("Load searchableFields for key = " + key);

Expand All @@ -248,6 +249,66 @@ private void initFieldCatalog(
}
}

/**
* Collects field names from a search field iterator. Package-private for unit tests.
*
* @param fields may be {@code null}; treated as empty
* @return never {@code null}; may be empty
*/
static Set<String> collectSearchFieldNames(Iterator<PSSearchField> fields) {
Set<String> fieldNames = new HashSet<>();
if (fields == null) {
return fieldNames;
}
while (fields.hasNext()) {
fieldNames.add(fields.next().getFieldName());
}
return fieldNames;
}

/**
* Builds display-format id → name map for {@link PSSearchSimplePanel}. Package-private for unit
* tests.
*
* @param formats may be {@code null}; treated as empty
* @return never {@code null}; may be empty
*/
static Map<String, String> buildDisplayFormatIdNameMap(Iterator<PSDisplayFormat> formats) {
Map<String, String> map = new HashMap<>();
if (formats == null) {
return map;
}
while (formats.hasNext()) {
PSDisplayFormat format = formats.next();
map.put(Integer.toString(format.getDisplayId()), format.getDisplayName());
}
return map;
}

/**
* Finds Lucene special characters in a full-text query that are disallowed when synonym
* expansion is enabled. Package-private for unit tests.
*
* @param ftQueryText may be {@code null}
* @return comma-separated special characters found, or {@code null} if none
*/
static String findDisallowedSynonymExpansionChars(String ftQueryText) {
if (ftQueryText == null) {
return null;
}
String spChars = null;
for (String specialChar : ms_specialChars) {
if (ftQueryText.indexOf(specialChar) != -1) {
if (spChars == null) {
spChars = specialChar;
} else {
spChars += ", " + specialChar;
}
}
}
return spChars;
}

/*
* @see com.percussion.guitools.PSDialog#subclassHelpId(java.lang.String)
*/
Expand Down Expand Up @@ -282,12 +343,7 @@ private void initDialog() {
m_fieldCatalog);
setFieldEditorSize();

Map map = new HashMap();
Iterator iter = m_mgr.getDisplayFormats();
while (iter.hasNext()) {
PSDisplayFormat format = (PSDisplayFormat) iter.next();
map.put(Integer.toString(format.getDisplayId()), format.getDisplayName());
}
Map<String, String> map = buildDisplayFormatIdNameMap(m_mgr.getDisplayFormats());
m_searchSimplePanel =
new PSSearchSimplePanel(m_isEngineAvailable, map, m_searchConfig.getMaxSearchResult());
m_ftQuery = m_searchSimplePanel.getQueryText();
Expand Down Expand Up @@ -663,15 +719,15 @@ public void onOk() {
// updates the data objects.
if (!m_fieldEditorCtrl.save()) return;

Iterator iter = m_fieldEditorCtrl.getFields();
Iterator<PSSearchField> iter = m_fieldEditorCtrl.getFields();
String missingFieldNames = "";
/*If isRestrictToUserCommunity is true then check whether all fields
belongs to user community or not. If not warn the user about it.
*/
if (isRestrictToUserCommunity()) {
List<PSSearchField> missingFields = new ArrayList<PSSearchField>();
List<PSSearchField> missingFields = new ArrayList<>();
while (iter.hasNext()) {
PSSearchField field = (PSSearchField) iter.next();
PSSearchField field = iter.next();
/**
* @todo The field need to be checked in m_fieldCatalog.getAll(), but some reason it is not
* working that need to be fixed.
Expand Down Expand Up @@ -786,13 +842,7 @@ public void onOk() {
* false</code> otherwise.
*/
private boolean validateForSynonymExp(String ftQueryText) {
String spChars = null;
for (String specialChar : ms_specialChars) {
if (ftQueryText.indexOf(specialChar) != -1) {
if (spChars == null) spChars = specialChar;
else spChars += ", " + specialChar;
}
}
String spChars = findDisallowedSynonymExpansionChars(ftQueryText);

if (spChars != null) {
String message =
Expand All @@ -804,7 +854,7 @@ private boolean validateForSynonymExp(String ftQueryText) {
+ " "
+ spChars;

int selection = showErrorDialog(message);
showErrorDialog(message);
return false;
}

Expand Down Expand Up @@ -901,10 +951,10 @@ private int showErrorDialog(String message) {
private PSNode m_searchNode = null;

/**
* The Content Explorer search node, Never <code>null</code> after initailization of the dialog
* box.
* Search field filter map (field name → filter), may be {@code null} when no filters apply.
* Never modified after initialization of the dialog box.
*/
private Map m_searchFieldFilterMap = null;
private Map<?, ?> m_searchFieldFilterMap = null;

/** This dynamic fields panel */
private PSSearchFieldEditor m_fieldEditorCtrl = null;
Expand Down Expand Up @@ -1022,7 +1072,7 @@ private int showErrorDialog(String message) {
* Synonym expansion may not be used if any of these characters are included in a full text search
* query.
*/
private static final List<String> ms_specialChars = new ArrayList<String>();
private static final List<String> ms_specialChars = new ArrayList<>();

static {
ms_specialChars.add("+");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2026 Intersoft Data Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.percussion.cx;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.percussion.cms.PSCmsException;
import com.percussion.cms.objectstore.PSDisplayFormat;
import com.percussion.cms.objectstore.PSSearchField;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;

/**
* Behavioral tests for pure helpers on {@link PSSearchDialog} after rawtypes cleanup (#2993). Does
* not open the Swing dialog (requires live applet resources).
*/
public class PSSearchDialogTest {

@Test
public void collectSearchFieldNamesNullIteratorReturnsEmpty() {
Set<String> names = PSSearchDialog.collectSearchFieldNames(null);
assertTrue(names.isEmpty());
}

@Test
public void collectSearchFieldNamesEmptyIteratorReturnsEmpty() {
Set<String> names = PSSearchDialog.collectSearchFieldNames(Collections.emptyIterator());
assertTrue(names.isEmpty());
}

@Test
public void collectSearchFieldNamesCollectsDistinctNames() {
List<PSSearchField> fields = new ArrayList<>();
fields.add(field("sys_title"));
fields.add(field("sys_contentid"));
fields.add(field("sys_title")); // duplicate name — Set collapses

Set<String> names = PSSearchDialog.collectSearchFieldNames(fields.iterator());
assertEquals(2, names.size());
assertTrue(names.contains("sys_title"));
assertTrue(names.contains("sys_contentid"));
}

@Test
public void buildDisplayFormatIdNameMapNullIteratorReturnsEmpty() {
Map<String, String> map = PSSearchDialog.buildDisplayFormatIdNameMap(null);
assertTrue(map.isEmpty());
}

@Test
public void buildDisplayFormatIdNameMapEmptyIteratorReturnsEmpty() {
Map<String, String> map =
PSSearchDialog.buildDisplayFormatIdNameMap(Collections.emptyIterator());
assertTrue(map.isEmpty());
}

@Test
public void buildDisplayFormatIdNameMapMapsIdToDisplayName() throws PSCmsException {
PSDisplayFormat format = new PSDisplayFormat();
format.setDisplayName("Default Format");
// Default ctor leaves display id as -1 until persisted
Map<String, String> map =
PSSearchDialog.buildDisplayFormatIdNameMap(Collections.singletonList(format).iterator());
assertEquals(1, map.size());
assertEquals("Default Format", map.get(Integer.toString(format.getDisplayId())));
}

@Test
public void findDisallowedSynonymExpansionCharsNullReturnsNull() {
assertNull(PSSearchDialog.findDisallowedSynonymExpansionChars(null));
}

@Test
public void findDisallowedSynonymExpansionCharsPlainTextReturnsNull() {
assertNull(PSSearchDialog.findDisallowedSynonymExpansionChars("simple query text"));
}

@Test
public void findDisallowedSynonymExpansionCharsFindsSpecials() {
// Order follows ms_specialChars static init: + then - then && ...
assertEquals("+", PSSearchDialog.findDisallowedSynonymExpansionChars("a+b"));
assertEquals("*", PSSearchDialog.findDisallowedSynonymExpansionChars("star*"));
String multi = PSSearchDialog.findDisallowedSynonymExpansionChars("a+b*c");
assertTrue(multi.contains("+"));
assertTrue(multi.contains("*"));
}

private static PSSearchField field(String name) {
return new PSSearchField(name, name, null, PSSearchField.TYPE_TEXT, null);
}
}
Loading