Skip to content

Calendar filter user presets#396

Merged
rkrenn merged 4 commits intomasterfrom
calendar_filter_user_presets
Nov 21, 2025
Merged

Calendar filter user presets#396
rkrenn merged 4 commits intomasterfrom
calendar_filter_user_presets

Conversation

@rkrenn
Copy link
Copy Markdown
Collaborator

@rkrenn rkrenn commented Nov 21, 2025

image

closing #395

Summary by CodeRabbit

Release Notes

  • New Features
    • Users can now set and save calendar filter presets for duty roster and inventory booking calendars.
    • Calendar filters can be inherited from other users and synchronized across sessions.
    • Default calendar filter settings are now configurable with UI enhancements for filter selection and autocomplete support in user settings.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 21, 2025

Walkthrough

This PR introduces user-scoped calendar filter persistence through a new CATEGORY_PRESET database table. The changes extend user data management across domain, service, and web layers to synchronize duty roster and inventory booking calendar filters from database storage to user VOs and UI components.

Changes

Cohort / File(s) Summary
Database Schema Updates
core/db/schema-create.sql, core/db/schema-drop.sql, core/db/schema-up-master.sql, core/db/schema-set-version.sql
Created new CATEGORY_PRESET table with ID and CATEGORY columns plus two foreign key references to users. Added drop constraints and updated schema version from 010801104 to 010801105.
User Domain & DAO
common/src/main/java/org/phoenixctms/ctsms/util/CommonUtil.java, core/src/main/java/org/phoenixctms/ctsms/domain/UserDaoImpl.java
Modified copyInheritedUserToOut to reinitialize calendar filter collections from input. Extended UserDaoImpl with bidirectional conversion and persistence support for DutyRosterCalendarFilters and InventoryBookingCalendarFilters across multiple VO paths and inheritance handling.
User Service & Reflexion
core/src/main/java/org/phoenixctms/ctsms/service/user/UserServiceImpl.java, core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java
Added cleanup logic in user deletion to remove associated calendar filter presets. Introduced entityToValueCollection utility method and CATEGORY_PRESET_ID_COMPARATOR in reflexion graph for filter conversion.
Demo Data
core/src/exec/java/org/phoenixctms/ctsms/executable/DemoDataProvider.java
Added clearing of calendar filter collections during user assignment.
Web Session & Scheduling Models
web/src/main/java/org/phoenixctms/ctsms/web/model/SessionScopeBean.java, web/src/main/java/org/phoenixctms/ctsms/web/model/trial/DutyRosterLazyScheduleModel.java, web/src/main/java/org/phoenixctms/ctsms/web/model/inventory/InventoryBookingLazyScheduleModel.java
Added synchronized accessor methods in SessionScopeBean for calendar filters. Updated schedule model constructors to initialize calendars with session-scoped filter values instead of empty collections.
User Settings Base & Implementation
web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java, web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserSettingsBean.java, web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserBean.java
Added protected fields and public accessors/mutators for calendar filters in base class with abstract persistence layer. Implemented filter synchronization between in/out VOs and persistence logic in concrete beans.
Web Configuration & Constants
web/src/main/java/org/phoenixctms/ctsms/web/util/SettingCodes.java, web/src/main/java/org/phoenixctms/ctsms/web/util/DefaultSettings.java
Added four new public constants for calendar filter setting codes and default empty list instances.
Web Properties
web/src/main/resources/org/phoenixctms/ctsms/web/settings.properties, web/src/main/resources/org/phoenixctms/ctsms/web/user/labels.properties, web/src/main/resources/org/phoenixctms/ctsms/web/user/labels_de.properties
Added property keys for default and user-preset calendar filters, plus German and English localization labels and tooltips.
Web UI Templates
web/src/main/webapp/META-INF/includes/shared/userSettingsBaseInput.xhtml, web/src/main/webapp/META-INF/includes/user/userMain.xhtml, web/src/main/webapp/user/changeSettings.xhtml
Added UI blocks for duty roster and inventory booking calendar filter selection and inheritance toggles. Updated column CSS classes and added form keypress handler for autocomplete behavior.
UML Profile Normalization
mda/src/main/uml/UML_Standard_Profile.StandardProfileL3.profile.uml, mda/src/main/uml/andromda-*.profile.uml
Regenerated XMI identifiers and structural metadata across UML profiles; semantic functionality and public entities remain unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant UI as UI/Form
    participant SB as SessionScopeBean
    participant USB as UserSettingsBean
    participant DAO as UserDaoImpl
    participant DB as Database

    UI->>USB: Load user settings
    USB->>DAO: Load user from DB
    DAO->>DB: Query User + CategoryPreset
    DB-->>DAO: User + filters
    DAO->>DAO: Convert to UserInVO<br/>(entityToValueCollection)
    DAO-->>USB: UserInVO w/ filters
    USB->>USB: Initialize filter sets<br/>from UserInVO
    USB-->>UI: Display filters
    
    UI->>USB: User modifies filters
    USB->>USB: Update filter sets
    
    UI->>USB: Save settings
    USB->>DAO: sanitizeInVals()<br/>calls setUser*Filters
    DAO->>DAO: Convert filters to<br/>CategoryPreset entities
    DAO->>DB: Persist User + CategoryPreset
    DB-->>DAO: ✓ Saved
    DAO-->>USB: ✓ Complete
    SB->>SB: Cache filters for<br/>schedule models
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas requiring extra attention:

  • UserDaoImpl.java — Most substantial file with intricate multi-path VO conversion logic. Verify bidirectional synchronization of calendar filters across toUserInVO, userInVOToEntity, inheritance paths (toUserInheritedVO, setInheritedProperty), and all VO variants. Pay close attention to null-handling and the CategoryPreset reconstruction pattern.
  • UserSettingsBeanBase.java — Introduces new persistence layer abstraction with abstract accessors. Ensure lifecycle coordination between initialization (initSets), sanitization (sanitizeInVals), and tooltip rendering is sound.
  • Database schema files — Verify CATEGORY_PRESET foreign key constraints are correct and cascade semantics align with user deletion cleanup in UserServiceImpl.
  • UserReflexionGraph.entityToValueCollection — New utility for converting CategoryPreset collections; confirm the comparator and category string extraction are correct for inheritance scenarios.

Possibly related PRs

  • PR #337 — Adds autoCompleteForceSelectionPreventFormSubmission handler to form pages, same behavior added here in changeSettings.xhtml.
  • PR #376 — Modifies scheduling model calendar initialization and filter parameter handling for InventoryBookingLazyScheduleModel and DutyRosterLazyScheduleModel, overlapping scope.

Suggested reviewers

  • fladi
  • 01hasenberger

Poem

🐰 Hop, hop! A rabbit filters his way,
Calendar presets in SQL's display,
From DB to bean, from form to view,
Filters persist through and through!
UserInVO syncs both day and night,
Settings saved—oh, what a sight! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Calendar filter user presets' clearly and concisely describes the main change—adding user-configurable calendar filter presets across duty roster and inventory booking calendars, which is evident from the extensive changes to database schema, user service implementations, UI models, and resource properties.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch calendar_filter_user_presets

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.40.0)
core/src/exec/java/org/phoenixctms/ctsms/executable/DemoDataProvider.java

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/main/java/org/phoenixctms/ctsms/web/model/trial/DutyRosterLazyScheduleModel.java (1)

119-131: Guard calendars initialization against missing session or filters

Initializing

calendars = new LinkedHashSet<String>(WebUtil.getSessionScopeBean().getDutyRosterCalendarFilters());

will throw a NullPointerException if either WebUtil.getSessionScopeBean() returns null (e.g., no HTTP session / tests) or its getDutyRosterCalendarFilters() returns null.

Safer initialization that still seeds from the session could be:

- StaffOutVO identity = WebUtil.getUserIdentity();
+ StaffOutVO identity = WebUtil.getUserIdentity();
  if (identity != null) {
      ...
  }
- calendars = new LinkedHashSet<String>(WebUtil.getSessionScopeBean().getDutyRosterCalendarFilters());
+ calendars = new LinkedHashSet<String>();
+ Set<String> defaultCalendars = null;
+ if (WebUtil.getSessionScopeBean() != null) {
+     defaultCalendars = WebUtil.getSessionScopeBean().getDutyRosterCalendarFilters();
+ }
+ if (defaultCalendars != null) {
+     calendars.addAll(defaultCalendars);
+ }

This preserves behavior when defaults exist but avoids constructor‑time NPEs in edge cases.

🧹 Nitpick comments (12)
web/src/main/java/org/phoenixctms/ctsms/web/model/inventory/InventoryBookingLazyScheduleModel.java (1)

134-135: Guard against possible null SessionScopeBean when seeding calendars

WebUtil.getSessionScopeBean() can return null (see its overload taking HttpSession), so WebUtil.getSessionScopeBean().getInventoryBookingCalendarFilters() risks an NPE outside a fully initialized JSF session. A small guard keeps behavior but hardens the code.

-        calendars = new LinkedHashSet<String>(WebUtil.getSessionScopeBean().getInventoryBookingCalendarFilters());
+        org.phoenixctms.ctsms.web.model.SessionScopeBean sessionBean = WebUtil.getSessionScopeBean();
+        Collection<String> sessionCalendars = sessionBean != null
+                ? sessionBean.getInventoryBookingCalendarFilters()
+                : Collections.<String>emptyList();
+        calendars = new LinkedHashSet<String>(sessionCalendars);
core/db/schema-drop.sql (1)

17-22: CATEGORY_PRESET teardown is ordered correctly; ensure constraint names match creates

Dropping the two CATEGORY_PRESET_*_USER_FKC constraints before drop table CATEGORY_PRESET cascade fits the existing drop pattern and should avoid dependency issues.

It’s worth confirming the constraint names here are exactly the ones used in schema-create.sql / schema-up-master.sql for CATEGORY_PRESET, to avoid surprises on teardown.

Also applies to: 1028-1029

core/src/main/java/org/phoenixctms/ctsms/service/user/UserServiceImpl.java (1)

21-25: Calendar preset cleanup on user delete is consistent with existing patterns

The new CategoryPreset imports and the delete‑time cleanup of DutyRosterCalendarFilters and InventoryBookingCalendarFilters match how passwords, permission profiles, and table columns are handled and should prevent FK violations against CATEGORY_PRESET.

Two minor points to consider:

  • This assumes the two filter collections are always non‑null. If the mapping doesn’t guarantee that, adding a simple null check before iterating would be safer.
  • If more CategoryPreset‑based associations are added later, extracting this repeated removal logic into a small helper (similar to deleteDataTableColumns) would keep handleDeleteUser from growing further.

Also applies to: 273-287

web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserBean.java (1)

1176-1200: Make calendar filter setters tolerant of null to avoid potential NPEs

setUserDutyRosterCalendarFilters and setUserInventoryBookingCalendarFilters assume the incoming filters collection is non‑null. If UserSettingsBeanBase or UI binding ever passes null to mean “no filters”, addAll(filters) will throw an NPE.

A small guard keeps this safe without changing semantics (null just maps to an empty collection):

-    @Override
-    protected void setUserDutyRosterCalendarFilters(Collection<String> filters) {
-        if (in != null) {
-            in.getDutyRosterCalendarFilters().clear();
-            in.getDutyRosterCalendarFilters().addAll(filters);
-        }
-    }
+    @Override
+    protected void setUserDutyRosterCalendarFilters(Collection<String> filters) {
+        if (in != null) {
+            in.getDutyRosterCalendarFilters().clear();
+            if (filters != null) {
+                in.getDutyRosterCalendarFilters().addAll(filters);
+            }
+        }
+    }
@@
-    @Override
-    protected void setUserInventoryBookingCalendarFilters(Collection<String> filters) {
-        if (in != null) {
-            in.getInventoryBookingCalendarFilters().clear();
-            in.getInventoryBookingCalendarFilters().addAll(filters);
-        }
-    }
+    @Override
+    protected void setUserInventoryBookingCalendarFilters(Collection<String> filters) {
+        if (in != null) {
+            in.getInventoryBookingCalendarFilters().clear();
+            if (filters != null) {
+                in.getInventoryBookingCalendarFilters().addAll(filters);
+            }
+        }
+    }
core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java (1)

196-210: Tighten generics and simplify entityToValueCollection

The helper works but mixes raw collections and generics and relies on runtime type checks:

  • public static ArrayList entityToValueCollection(Collection items) and raw ArrayList result will generate unchecked warnings.
  • items.size() will NPE if items is ever null.
  • The manual instanceof guard becomes unnecessary if the API is typed to CategoryPreset.

A more type‑safe and compact version would be along these lines:

-	public static ArrayList entityToValueCollection(Collection items) {
-		ArrayList result = new ArrayList<String>(items.size());
-		items = new ArrayList(items);
-		Collections.sort((ArrayList) items, CATEGORY_PRESET_ID_COMPARATOR);
-		Iterator it = items.iterator();
-		while (it.hasNext()) {
-			Object item = it.next();
-			if (item instanceof CategoryPreset) {
-				result.add(((CategoryPreset) item).getCategory());
-			} else {
-				throw new UnsupportedOperationException("cannot convert " + item.getClass());
-			}
-		}
-		return result;
-	}
+	public static ArrayList<String> entityToValueCollection(Collection<? extends CategoryPreset> items) {
+		if (items == null || items.isEmpty()) {
+			return new ArrayList<String>(0);
+		}
+		ArrayList<CategoryPreset> sorted = new ArrayList<CategoryPreset>(items);
+		Collections.sort(sorted, CATEGORY_PRESET_ID_COMPARATOR);
+		ArrayList<String> result = new ArrayList<String>(sorted.size());
+		for (CategoryPreset preset : sorted) {
+			result.add(preset.getCategory());
+		}
+		return result;
+	}

This keeps the ID‑based sorting behavior while removing raw types and hardening against nulls.

core/db/schema-create.sql (1)

124-131: CATEGORY_PRESET table and FKs are coherent; consider encoding semantics

The table definition and foreign keys are syntactically correct and consistent with the rest of the schema (no cascades, nullable FKs referencing users).

If the intent is that a given preset belongs to exactly one “role” (duty‑roster calendar vs. inventory‑booking calendar), you might later consider a check constraint to enforce that at most one of DUTY_ROSTER_CALENDAR_FILTER_USER_FK / INVENTORY_BOOKING_CALENDAR_FILTER_USER_FK is non‑null, or split into two tables. Right now the DB allows rows with both or neither set, leaving enforcement purely to application code.

Also applies to: 2305-2313

web/src/main/resources/org/phoenixctms/ctsms/web/user/labels.properties (1)

170-177: Inventory preset label naming slightly inconsistent with duty roster label

The English duty roster label uses “calendar filter preset” while the inventory one uses just “calendar preset”. Consider aligning wording (e.g., “Inventory booking calendar filter preset”) for consistency with the duty roster and the German texts.

core/src/main/java/org/phoenixctms/ctsms/domain/UserDaoImpl.java (1)

294-321: Repeated remove/recreate logic for CategoryPreset collections and possible null filters

The three blocks converting VO filter strings back to CategoryPreset entities all duplicate the same pattern (remove old, clear, recreate each time). That’s correct but a bit brittle and noisy.

Two follow-ups to consider:

  • Extract a small private helper like updateCalendarFilterPresets(Collection<String> filters, Collection<CategoryPreset> target, Consumer<CategoryPreset> ownerSetter) to centralize this logic and avoid future drift between the three call sites.
  • Optionally guard against null filter collections on the VO side (if (filters != null && !filters.isEmpty())) to avoid surprises if a caller ever passes null instead of an empty collection.

Also applies to: 376-403, 448-475

web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserSettingsBean.java (1)

252-276: Make calendar filter setters more defensive against null collections

The new protected setters mutate in’s collections via clear() + addAll(filters). This matches existing patterns but will NPE if filters is ever null.

You could make them slightly more robust with an explicit null check:

-    if (in != null) {
-        in.getDutyRosterCalendarFilters().clear();
-        in.getDutyRosterCalendarFilters().addAll(filters);
-    }
+    if (in != null) {
+        in.getDutyRosterCalendarFilters().clear();
+        if (filters != null) {
+            in.getDutyRosterCalendarFilters().addAll(filters);
+        }
+    }

(and analogously for inventoryBookingCalendarFilters).

web/src/main/webapp/META-INF/includes/shared/userSettingsBaseInput.xhtml (1)

246-291: New calendar filter preset UI wiring looks correct; consider removing dead ajax handlers

The inherit checkboxes, tooltips, and p:autoComplete components for dutyRosterCalendarFilters and inventoryBookingCalendarFilters are wired consistently with existing settings (bindings, inheritedPropertiesMap, labels, and tooltips all line up).

You’ve left commented-out p:ajax itemSelect/itemUnselect handlers inside both autocompletes. If these callbacks are no longer needed, consider removing the commented blocks to keep the template easier to maintain.

Also applies to: 293-339

web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java (2)

297-298: Avoid raw Collection cast in tooltip handling for inherited collections

The Collection branch in getInheritedPropertyTooltip currently uses a raw cast:

} else if (inheritedValue instanceof Collection) {
    inheritedValue = String.join(", ", (Collection) inheritedValue);
}

This compiles with an unchecked warning and can throw a ClassCastException at runtime if the collection contains non‑CharSequence elements. A safer approach is to work with Collection<?> and convert elements to String explicitly:

-               } else if (inheritedValue instanceof Collection) {
-                   inheritedValue = String.join(", ", (Collection) inheritedValue);
+               } else if (inheritedValue instanceof Collection<?>) {
+                   Collection<?> collection = (Collection<?>) inheritedValue;
+                   ArrayList<String> values = new ArrayList<String>(collection.size());
+                   for (Object element : collection) {
+                       if (element != null) {
+                           values.add(String.valueOf(element));
+                       }
+                   }
+                   inheritedValue = String.join(", ", values);

This removes the raw-type warning and is robust even if future inherited properties expose collections of non‑String elements.


391-395: Consider removing commented‑out handler stubs

The commented handle*CalendarFilterSelect/Unselect methods look like unused stubs. If there’s no immediate plan to wire them into the UI, consider deleting them to keep the base class lean; otherwise, adding a brief comment about planned usage would clarify why they’re retained.

Also applies to: 427-431

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d2edd4 and 900f3f5.

📒 Files selected for processing (29)
  • common/src/main/java/org/phoenixctms/ctsms/util/CommonUtil.java (1 hunks)
  • core/db/schema-create.sql (2 hunks)
  • core/db/schema-drop.sql (2 hunks)
  • core/db/schema-set-version.sql (1 hunks)
  • core/db/schema-up-master.sql (1 hunks)
  • core/src/exec/java/org/phoenixctms/ctsms/executable/DemoDataProvider.java (1 hunks)
  • core/src/main/java/org/phoenixctms/ctsms/domain/UserDaoImpl.java (8 hunks)
  • core/src/main/java/org/phoenixctms/ctsms/service/user/UserServiceImpl.java (2 hunks)
  • core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java (4 hunks)
  • mda/src/main/uml/UML_Standard_Profile.StandardProfileL3.profile.uml (1 hunks)
  • mda/src/main/uml/andromda-common.andromda-service.profile.uml (6 hunks)
  • mda/src/main/uml/andromda-presentation.profile.uml (5 hunks)
  • mda/src/main/uml/andromda-process.profile.uml (4 hunks)
  • mda/src/main/uml/andromda-webservice.profile.uml (5 hunks)
  • mda/src/main/uml/andromda-xml.profile.uml (5 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/SessionScopeBean.java (1 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/inventory/InventoryBookingLazyScheduleModel.java (1 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java (7 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/trial/DutyRosterLazyScheduleModel.java (1 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserBean.java (4 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserSettingsBean.java (2 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/util/DefaultSettings.java (2 hunks)
  • web/src/main/java/org/phoenixctms/ctsms/web/util/SettingCodes.java (2 hunks)
  • web/src/main/resources/org/phoenixctms/ctsms/web/settings.properties (2 hunks)
  • web/src/main/resources/org/phoenixctms/ctsms/web/user/labels.properties (1 hunks)
  • web/src/main/resources/org/phoenixctms/ctsms/web/user/labels_de.properties (1 hunks)
  • web/src/main/webapp/META-INF/includes/shared/userSettingsBaseInput.xhtml (10 hunks)
  • web/src/main/webapp/META-INF/includes/user/userMain.xhtml (1 hunks)
  • web/src/main/webapp/user/changeSettings.xhtml (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
web/src/main/java/org/phoenixctms/ctsms/web/model/trial/DutyRosterLazyScheduleModel.java (1)
web/src/main/java/org/phoenixctms/ctsms/web/util/WebUtil.java (1)
  • WebUtil (75-5208)
web/src/main/java/org/phoenixctms/ctsms/web/model/SessionScopeBean.java (2)
web/src/main/java/org/phoenixctms/ctsms/web/util/Settings.java (1)
  • Settings (34-372)
web/src/main/java/org/phoenixctms/ctsms/web/util/DefaultSettings.java (1)
  • DefaultSettings (24-803)
core/src/main/java/org/phoenixctms/ctsms/domain/UserDaoImpl.java (2)
core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java (1)
  • UserReflexionGraph (34-274)
common/src/main/java/org/phoenixctms/ctsms/util/CommonUtil.java (1)
  • CommonUtil (113-2756)
web/src/main/java/org/phoenixctms/ctsms/web/model/inventory/InventoryBookingLazyScheduleModel.java (1)
web/src/main/java/org/phoenixctms/ctsms/web/util/WebUtil.java (1)
  • WebUtil (75-5208)
web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java (1)
web/src/main/java/org/phoenixctms/ctsms/web/util/WebUtil.java (1)
  • WebUtil (75-5208)
web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserBean.java (2)
web/src/main/java/org/phoenixctms/ctsms/web/util/Settings.java (1)
  • Settings (34-372)
web/src/main/java/org/phoenixctms/ctsms/web/util/DefaultSettings.java (1)
  • DefaultSettings (24-803)
core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java (1)
core/src/main/java/org/phoenixctms/ctsms/compare/UserComparator.java (1)
  • UserComparator (7-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build and Test
🔇 Additional comments (40)
web/src/main/webapp/META-INF/includes/user/userMain.xhtml (1)

664-666: Consistent use of *-top-column classes for user settings grid

Switching columnClasses here to the ctsms-*-top-column variants aligns the user settings layout with the modules grid above and should give consistent top-aligned checkbox/label/input/message rows. No functional impact, and the change looks correct as long as the corresponding CSS classes are defined (which they already appear to be in related usages).

mda/src/main/uml/UML_Standard_Profile.StandardProfileL3.profile.uml (1)

3-11: XMI/eAnnotation ID refresh only; semantic identifiers preserved

The updated xmi:id values on eAnnotations, contents, and Standard:ModelLibrary keep md_id and href targets unchanged, so the profile’s semantic identity and imports remain intact. No issues from a codegen/tooling perspective.

Also applies to: 265-265

mda/src/main/uml/andromda-xml.profile.uml (3)

4-88: Ecore package/enum/class IDs and nsURI regenerated; structure intact

The EPackage, EEnum, and EClass definitions are re‑emitted with new xmi:ids and an updated nsURI, but:

  • All classifier names, literals, and references to UML elements are preserved.
  • EAttributes/EReferences still point to the same UML metaclasses and enums.

Functionally the profile structure is unchanged. Please just confirm no external EMF tooling or serialized instances rely on the old nsURI string.


120-144: Extension memberEnd rewrites are consistent with existing stereotypes

The uml:Extension elements around the XmlSchema/NoXml/XmlAttribute stereotypes only adjust memberEnd ordering and IDs; the extension ends still reference the same stereotype and base UML metaclasses. No semantic change detected.


259-265: Profile application and ModelLibrary IDs updated safely

The new eAnnotations id on profileApplication and the Standard:ModelLibrary id simply refresh internal XMI identifiers while still targeting the same Standard profile and base package. Safe housekeeping.

mda/src/main/uml/andromda-webservice.profile.uml (3)

4-337: Ecore meta updated; stereotype semantics and mappings preserved

The regenerated EPackage content (enums like WebServiceStyle, ProviderMediaType, HttpRequestType, and classes like WebService, WebServiceOperation, WebServiceParam, WebServiceFeed, WSSecurity, etc.):

  • Keeps all classifier names and enum literals unchanged.
  • Maintains eAnnotations references to the same UML enumerations/stereotypes.
  • Keeps all EReferences pointing at the expected UML metaclasses (Class, Operation, Parameter, etc.).

Notably, andromda_REST_suspend in WebServiceOperation is explicitly typed as EInt with default 0, which better matches the UML Integer attribute and should improve generated typings.

Overall this looks like tooling‑driven ID/typing normalization. Please re‑run your MDA/codegen pipeline to ensure no EMF client was depending on the previous (possibly looser) Ecore typing.


743-767: Extension memberEnd adjustments remain consistent with their stereotypes

The uml:Extension elements for WebServiceParam, WebServiceFeed, WebService, WebServiceOperation, WebFault, WSCustomHeader, WSSecurity, WSAddressing, and WSPolicy only:

  • Reorder memberEnd entries and
  • Make the extension end the navigableOwnedEnd explicitly.

Each extension end still targets the correct stereotype and base UML metaclass, so extension semantics are unchanged.

Also applies to: 894-953


955-961: Profile application metadata and ModelLibrary ID refreshed safely

The new eAnnotations id on profileApplication and the updated Standard:ModelLibrary id keep the applied Standard profile and base_Package reference identical. This is harmless metadata cleanup.

mda/src/main/uml/andromda-process.profile.uml (4)

4-93: Process Ecore package regenerated; stereotype wiring still correct

The EPackage now defines EClasses for andromda_process_jbpm_task_blocking, BusinessProcess, NodeLeave, Timer, jbpm timer tags, signal hooks, Task, and assignment expressions, with:

  • EAttributes using appropriate Ecore types (EBoolean/EString) and defaults (e.g., blocking default false).
  • EReferences consistently targeting the intended UML metaclasses (CallEvent, UseCase, ActivityPartition, etc.).

Everything matches the corresponding UML stereotypes further down; this is safe metadata regeneration.


199-205: Extensions for Before Signal and jbpm assignment remain well-formed

The uml:Extension elements for Before Signal and andromda_process_jbpm_assignment_expression simply restate the extension ends and memberEnd ordering:

  • Extension ends still point to the right stereotypes.
  • Associations still bind to the same base UML elements (CallEvent, ActivityPartition).

No behavioral impact expected.


253-263: Timer transition/repeat extensions correctly reference their stereotypes

The timer‑related uml:Extension elements continue to associate:

  • andromda_process_jbpm_timer_transition and
  • andromda_process_jbpm_timer_repeat

with CallEvent via the same stereotype types and associations. Only internal memberEnd wiring changed; semantics are preserved.


272-278: Profile application and ModelLibrary identifiers updated only

The added eAnnotations id under profileApplication and the new Standard:ModelLibrary id maintain the same Standard profile reference and base_Package. This is benign XMI bookkeeping.

mda/src/main/uml/andromda-common.andromda-service.profile.uml (3)

4-92: Service-related EEnums re-emitted; literals and UML bindings unchanged

The regenerated Ecore enums (SpringRemotingProtocol, EjbTransactionManagement, EjbServiceType, TernaryBoolean, EjbTransactionType, SpringTransactionType, EjbViewType, EjbMdb*, EjbPersistenceUnitType, EjbServiceFlushMode) keep:

  • The same literal names and integer values.
  • eAnnotations references pointing at the same UML enumerations.

This keeps all tag semantics stable while normalizing internal IDs.


225-377: Service extensions: memberEnd/xmi:type clean-up with stable associations

The block of uml:Extension elements (Service, Timeout, Listener, Interceptor, PostConstruct, PreDestroy, ResourceRef, RunAs, PrePassivate, DataSource, PostActivate, PersistenceContext, UserTransaction, MessageDriven, ServiceRef, SecuredElement, InterceptorOperation) has:

  • Explicit uml:ExtensionEnd typing on the extension end memberEnd.
  • MemberEnd order adjusted but still pairing each stereotype in andromda-common with the correct base UML element.

No change in how these stereotypes apply; this is structural hygiene only.


379-385: Profile application metadata and ModelLibrary ID updated safely

The new eAnnotations id and Standard:ModelLibrary id leave the applied Standard profile and base_Package untouched. Pure metadata refresh.

mda/src/main/uml/andromda-presentation.profile.uml (3)

4-203: Presentation Ecore meta regenerated; FrontEnd stereotypes still align

Within the contents block, enums (WebActionFormScope, WebFieldType, WebActionType, WebExportType, ViewType, TernaryBoolean) and EClasses (FrontEndRegistration/Exception/Table/Field/Action/Application/Controller/UseCase/View/SessionObject/Message) are re‑emitted with new ids, but:

  • Classifier names and enum literals match the UML definitions further down.
  • Every eAnnotations references points to the same UML elements.
  • EAttributes and EReferences correspond one‑for‑one to the tagged values and base types on the UML stereotypes.

This is consistent with tooling‑driven regeneration. Recommend rerunning your MDA/presentation generation to confirm no EMF client depended on the old internal ids.


541-601: FrontEnd extensions: memberEnd/navigableOwnedEnd normalization only*

The uml:Extension elements for FrontEndAction, FrontEndRegistration, FrontEndApplication, FrontEndField (calendar), FrontEndTable (columns), FrontEndSessionObject, FrontEndException, and FrontEndUseCase now:

  • Use consistent memberEnd ordering, and
  • Make the appropriate extension end the navigableOwnedEnd.

Each extension end still targets the same stereotype and base UML element, so extension semantics and codegen behavior remain unchanged.


642-648: Profile application IDs updated; Standard profile linkage intact

The new eAnnotations id in profileApplication and the updated Standard:ModelLibrary id continue to reference the same Standard profile and presentation profile package. This is harmless XMI metadata cleanup.

web/src/main/webapp/user/changeSettings.xhtml (1)

14-28: Verify onkeypress EL resolves to the intended JavaScript snippet

The new onkeypress="#{autoCompleteForceSelectionPreventFormSubmission}" relies on EL to produce the JavaScript handler. If autoCompleteForceSelectionPreventFormSubmission is not a request/session/application‑scoped bean property (or a bundle string) that returns a valid JS snippet, this will no‑op and the autocomplete form‑submission guard won’t work. In that case you likely want a literal handler, e.g.:

<h:form id="changesettings_form"
       onkeypress="return autoCompleteForceSelectionPreventFormSubmission(event);">

The updated columnClasses look fine and are layout‑only.

Please double‑check how this is wired in other pages and that the expression actually yields the correct JS.

core/src/exec/java/org/phoenixctms/ctsms/executable/DemoDataProvider.java (1)

587-607: Verify null-safety of calendar filter getters in UserInVO

Could not locate the UserInVO class definition in the repository to verify whether getDutyRosterCalendarFilters() and getInventoryBookingCalendarFilters() are guaranteed to return non-null collections. However, the identical pattern (calling .clear() without null-checks) appears consistently throughout the codebase in UserBean, UserSettingsBean, CommonUtil, UserServiceImpl, and UserDaoImpl, suggesting these getters always return initialized collections rather than null.

Please confirm that UserInVO initializes these collections in its constructor or field declaration, and that the getters never return null. If they can return null, the flagged lines 605–606 should add null-guards as suggested in the original comment.

common/src/main/java/org/phoenixctms/ctsms/util/CommonUtil.java (1)

585-620: Add null-safety when copying new calendar filter collections (lines 616–619)

The method calls getDutyRosterCalendarFilters() and getInventoryBookingCalendarFilters() on both out and in objects, then immediately invokes .clear() and .addAll() without verifying the getters return non-null. If either getter returns null, a NullPointerException will be thrown at runtime.

While the codebase shows inconsistent patterns (line 567 has an unguarded getSelectionValues().clear(), but lines 787–789 guard with if (outValues != null)), the safer pattern should be applied here. Verify that UserOutVO and UserInheritedVO guarantee these getters always return non-null collections, or add null guards as suggested in the original review.

core/db/schema-set-version.sql (1)

14-14: Schema version bump looks consistent with new CATEGORY_PRESET changes

Updating to '010801105' is fine; just ensure the same version is used in schema-create and schema-up-master so migrations remain coherent.

Please double‑check other DDL/migration files reference 010801105 as the current schema version.

web/src/main/resources/org/phoenixctms/ctsms/web/settings.properties (1)

3-4: New calendar filter defaults/presets are correctly wired

The four new keys (default_*_calendar_filters and user_*_calendar_filters_preset) follow the existing settings naming pattern and align with the SettingCodes/DefaultSettings constants.

Leaving them empty by default is reasonable; operators can later configure comma‑separated filter IDs as needed.

Also applies to: 366-367

web/src/main/java/org/phoenixctms/ctsms/web/model/SessionScopeBean.java (1)

844-866: Calendar filter getters correctly fall back to global defaults; confirm empty‑list semantics

The new getDutyRosterCalendarFilters / getInventoryBookingCalendarFilters methods are consistent with other settings accessors: they use the inherited user value when present and non‑empty, otherwise fall back to DEFAULT_* from settings.properties.

One behavioral detail to confirm: an empty user list is currently treated as “no user override, use defaults”. If you ever need to distinguish “explicitly no filters” from “inherit defaults”, you’d need an additional flag or sentinel; otherwise this implementation looks solid.

web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserBean.java (2)

98-101: Symmetric propagation of calendar filters between UserInVO and UserOutVO

The new DutyRosterCalendarFilters / InventoryBookingCalendarFilters copy blocks in copyUserOutToIn and createUserOutFromIn (clear + addAll) are symmetric and match how inherited properties and permission groups are already handled. This should keep in/out VO state consistent across UI interactions.

Also applies to: 156-159


207-210: User default calendar filters correctly sourced from preset settings

initUserDefaultValues now initializes UserInVO’s two calendar filter collections from USER_DUTY_ROSTER_CALENDAR_FILTERS_PRESET and USER_INVENTORY_BOOKING_CALENDAR_FILTERS_PRESET via Settings.getStringList(...). This is consistent with how other user presets (theme, tab orientation, visible tabs) are wired.

core/src/main/java/org/phoenixctms/ctsms/vocycle/UserReflexionGraph.java (1)

192-194: Consider null‑safety for calendar filter collections

entityToValueCollection assumes source.getDutyRosterCalendarFilters() / getInventoryBookingCalendarFilters() are non‑null; if any mapping path ever leaves these as null you’ll get an NPE here. Either guarantee non‑null collections at the entity level or defensively treat null as an empty collection before calling the helper.

web/src/main/java/org/phoenixctms/ctsms/web/util/SettingCodes.java (2)

7-8: New default calendar filter keys look consistent

DEFAULT_DUTY_ROSTER_CALENDAR_FILTERS and DEFAULT_INVENTORY_BOOKING_CALENDAR_FILTERS follow the existing naming/value pattern for default settings and align with the property keys.


215-216: User preset keys for calendar filters are well‑placed

USER_DUTY_ROSTER_CALENDAR_FILTERS_PRESET and USER_INVENTORY_BOOKING_CALENDAR_FILTERS_PRESET fit the existing USER_*_PRESET convention and keep symmetry with the new default keys.

web/src/main/java/org/phoenixctms/ctsms/web/util/DefaultSettings.java (2)

26-29: Default calendar filter lists follow existing pattern

DEFAULT_DUTY_ROSTER_CALENDAR_FILTERS and DEFAULT_INVENTORY_BOOKING_CALENDAR_FILTERS mirror how other list‑type defaults are modeled (mutable ArrayList<String> constants) and are fine as empty defaults.


338-340: User preset calendar filter defaults are wired appropriately

USER_DUTY_ROSTER_CALENDAR_FILTERS_PRESET and USER_INVENTORY_BOOKING_CALENDAR_FILTERS_PRESET align with the other USER_*_PRESET defaults and give a natural home for per‑user calendar filter presets (empty by default).

core/db/schema-up-master.sql (1)

508-530: Migration for CATEGORY_PRESET matches base schema

The new 010801105 step correctly creates CATEGORY_PRESET and its two FKs to users, mirroring schema-create.sql, and updates the DB version. This keeps install and upgrade schemas aligned.

core/src/main/java/org/phoenixctms/ctsms/domain/UserDaoImpl.java (2)

179-180: VO mappings for calendar filter presets look consistent

The new mappings from User to UserInVO, UserSettingsInVO, and UserInheritedVO, plus the registration of dutyRosterCalendarFilters and inventoryBookingCalendarFilters in setInheritedProperty, are symmetric with the entity collections and reuse UserReflexionGraph.entityToValueCollection consistently. This should keep all three VO types aligned with the underlying CategoryPreset collections.

Also applies to: 413-414, 524-525, 552-553


572-579: Collection handling in setInheritedProperty assumes CategoryPreset-based collections

The new Collection branch in setInheritedProperty correctly:

  • Pulls the inherited Collection from the parent User,
  • Converts it via UserReflexionGraph.entityToValueCollection(...), and
  • Replaces the UserInheritedVO collection contents.

This is appropriate for the new calendar filter presets, but it implicitly assumes that any property passed with type == Collection.class corresponds to a Collection<CategoryPreset> on User. If you ever add another collection-typed inheritable property of a different element type, you’ll need a different conversion strategy (or an explicit discriminator) here.

Would you confirm that currently only the dutyRosterCalendarFilters and inventoryBookingCalendarFilters properties use Collection.class with CategoryPreset elements? If others are added later, this helper may need to be generalized.

web/src/main/resources/org/phoenixctms/ctsms/web/user/labels_de.properties (1)

169-176: German calendar preset labels are consistent and aligned with English

The new German labels/tooltips for both duty roster and inventory booking calendar filter presets look consistent with each other and correctly mirror the English texts.

web/src/main/java/org/phoenixctms/ctsms/web/model/user/UserSettingsBean.java (1)

43-46: Copying calendar filter presets from out to in is correct and symmetric

Clearing in.getDutyRosterCalendarFilters() / getInventoryBookingCalendarFilters() and then addAll from out keeps the settings-VO exactly in sync with the user-VO and matches how other mutable collections are handled.

web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java (4)

46-47: Calendar filter fields and initialization look appropriate

Using Set<String> with LinkedHashSet initialization gives uniqueness plus predictable iteration order, and keeps the in-memory representation non-null throughout the bean lifecycle. This is a good fit for user presets and aligns with later copying into List<String> for exposure.

Also applies to: 54-55


108-117: Loading and persisting calendar filters is consistent and null-safe

The pattern in initSets (clear, then populate from getUser* if non-null) and in sanitizeInVals (persisting the internal sets back via setUser*) is coherent, avoids stale state, and never exposes null to the abstract setters. This wiring should work well with the persistence layer.

Also applies to: 167-168


216-222: Abstract accessors for user calendar filters fit existing design

The added abstract getters/setters for duty roster and inventory booking calendar filters are consistent with the other user-scoped settings abstractions in this base class, and the use of Collection<String> gives implementations flexibility in storage.


386-402: Getter/setter implementations for calendar filter lists are fine

The new get*CalendarFilters methods returning copies of the internal sets, and the corresponding setters that clear then repopulate the sets from incoming lists, correctly encapsulate the internal Set while still exposing List<String> to the UI layer. This avoids external mutation of internal state and naturally de‑duplicates values via the underlying Set.

Also applies to: 422-438

Comment on lines +404 to +420
public List<String> completeDutyRosterCalendar(String query) {
Collection<String> calendars = null;
try {
calendars = WebUtil.getServiceLocator().getTrialService().getCalendars(WebUtil.getAuthentication(),
null, null, null, query, null); // let permission argument override decide...
} catch (ServiceException | AuthorisationException | IllegalArgumentException e) {
} catch (AuthenticationException e) {
WebUtil.publishException(e);
}
if (calendars != null) {
try {
return ((List<String>) calendars);
} catch (ClassCastException e) {
}
}
return new ArrayList<String>();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix fragile CollectionList cast in autocomplete methods

Both autocomplete helpers try to cast an arbitrary Collection<String> from the service layer directly to List<String> and silently swallow ClassCastException:

if (calendars != null) {
    try {
        return ((List<String>) calendars);
    } catch (ClassCastException e) {
    }
}
return new ArrayList<String>();

This is brittle:

  • It relies on getCalendars always returning a List, even though callers elsewhere (e.g. WebUtil.getDutyRosterTurnFilterCalendars) treat it as a generic Collection<String>.
  • If the implementation ever returns a Set or any non‑List collection, autocomplete will just return an empty list, with the exception fully swallowed and no signal.

A safer and simpler implementation is to always wrap the returned Collection in a new ArrayList:

-        if (calendars != null) {
-            try {
-                return ((List<String>) calendars);
-            } catch (ClassCastException e) {
-            }
-        }
-        return new ArrayList<String>();
+        if (calendars != null) {
+            return new ArrayList<String>(calendars);
+        }
+        return new ArrayList<String>();

Apply this pattern to both completeDutyRosterCalendar and completeInventoryBookingCalendar. This removes the unsafe cast, avoids silently dropping valid data, and matches how other code (e.g. WebUtil.getDutyRosterTurnFilterCalendars / getInventoryBookingFilterCalendars) handles the same service call.

Also applies to: 440-456

🤖 Prompt for AI Agents
In
web/src/main/java/org/phoenixctms/ctsms/web/model/shared/UserSettingsBeanBase.java
around lines 404-420 (and similarly lines 440-456), the code unsafely casts a
Collection<String> returned by getCalendars(...) to List<String> and swallows
ClassCastException, which can drop valid data; replace the cast with creating
and returning a new ArrayList<>(calendars) when calendars is non-null (and
remove the try/catch around ClassCastException), preserving returned items and
avoiding fragile casting and silent failures.

@rkrenn rkrenn merged commit 21bd3b5 into master Nov 21, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant