Skip to content
Open
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
1 change: 1 addition & 0 deletions cms-api/src/main/java/com/condation/cms/api/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public static class CacheNames {
public static final String TEMPLATE = "template";
public static final String CONTENT = "content";
public static final String MEDIA = "media";
public static final String MENU = "menu";
public static final String RESPONSE = "response";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.condation.cms.api.eventbus.events;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import com.condation.cms.api.eventbus.Event;

/**
* Signals that the persisted representation of a site menu has changed.
*/
public record MenuChangedEvent(String menuId) implements Event {
}
34 changes: 34 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/menu/Menu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.condation.cms.api.menu;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.util.List;

/**
* A named navigation menu. The id is also used as the YAML file name.
*/
public record Menu(String id, String name, List<MenuItem> items) {

public Menu {
items = items == null ? List.of() : List.copyOf(items);
}
}
53 changes: 53 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/menu/MenuItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.condation.cms.api.menu;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.util.List;

/**
* A single, potentially nested entry in a navigation menu.
*/
public record MenuItem(
String id,
String type,
String label,
String url,
String target,
boolean enabled,
List<MenuItem> children,
boolean current) {

public MenuItem {
children = children == null ? List.of() : List.copyOf(children);
}

public MenuItem(
String id,
String type,
String label,
String url,
String target,
boolean enabled,
List<MenuItem> children) {
this(id, type, label, url, target, enabled, children, false);
}
}
42 changes: 42 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/menu/MenuService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.condation.cms.api.menu;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
* Storage abstraction for site navigation menus.
*/
public interface MenuService {

List<Menu> list() throws IOException;

Optional<Menu> get(String id) throws IOException;

Menu create(Menu menu) throws IOException;

Menu update(Menu menu) throws IOException;

boolean delete(String id) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.condation.cms.core.menu;

/*-
* #%L
* CMS Core
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import com.condation.cms.api.cache.ICache;
import com.condation.cms.api.eventbus.EventBus;
import com.condation.cms.api.eventbus.events.MenuChangedEvent;
import com.condation.cms.api.menu.Menu;
import com.condation.cms.api.menu.MenuService;
import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
* Site-local menu service decorator that caches loaded menu documents.
*/
public class CachingMenuService implements MenuService {

private final MenuService delegate;
private final ICache<String, Menu> cache;
private final EventBus eventBus;

public CachingMenuService(MenuService delegate, ICache<String, Menu> cache, EventBus eventBus) {
this.delegate = delegate;
this.cache = cache;
this.eventBus = eventBus;
eventBus.register(MenuChangedEvent.class, event -> cache.invalidate(event.menuId()));
}

@Override
public synchronized List<Menu> list() throws IOException {
List<Menu> menus = delegate.list();
menus.forEach(menu -> cache.put(menu.id(), menu));
return menus;
}

@Override
public synchronized Optional<Menu> get(String id) throws IOException {
Menu cachedMenu = cache.get(id);
if (cachedMenu != null) {
return Optional.of(cachedMenu);
}

Optional<Menu> menu = delegate.get(id);
menu.ifPresent(value -> cache.put(id, value));
return menu;
}

@Override
public Menu create(Menu menu) throws IOException {
Menu created = delegate.create(menu);
eventBus.syncPublish(new MenuChangedEvent(created.id()));
return created;
}

@Override
public Menu update(Menu menu) throws IOException {
Menu updated = delegate.update(menu);
eventBus.syncPublish(new MenuChangedEvent(updated.id()));
return updated;
}

@Override
public boolean delete(String id) throws IOException {
boolean deleted = delegate.delete(id);
if (deleted) {
eventBus.syncPublish(new MenuChangedEvent(id));
}
return deleted;
}
}
Loading
Loading