/*
* (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id: ActionRegistry.java 20637 2007-06-17 12:37:03Z sfermigier $
*/
package org.nuxeo.ecm.platform.actions;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class ActionRegistry implements Serializable {
private static final Log log = LogFactory.getLog(ActionRegistry.class);
private static final long serialVersionUID = 8425627293154848041L;
private final Map<String, Action> actions;
private final Map<String, List<String>> categories;
private List<TypeCompatibility> typeCategoryRelations;
public ActionRegistry() {
actions = new HashMap<String, Action>();
categories = new HashMap<String, List<String>>();
typeCategoryRelations = new ArrayList<TypeCompatibility>();
}
public synchronized void addAction(Action action) {
String id = action.getId();
if (log.isDebugEnabled()) {
if (actions.containsKey(id)) {
log.debug("Overriding action: " + action);
} else {
log.debug("Registering action: " + action);
}
}
// add a default label if not set
if (action.getLabel() == null) {
action.setLabel(action.getId());
}
actions.put(id, action);
for (String category : action.getCategories()) {
List<String> acts = categories.get(category);
if (acts == null) {
acts = new ArrayList<String>();
}
if (!acts.contains(id)) {
acts.add(id);
}
categories.put(category, acts);
}
}
public synchronized Action removeAction(String id) {
if (log.isDebugEnabled()) {
log.debug("Unregistering action: " + id);
}
Action action = actions.remove(id);
if (action != null) {
for (String category : action.getCategories()) {
List<String> acts = categories.get(category);
if (acts != null) {
acts.remove(id);
}
}
}
return action;
}
public synchronized Collection<Action> getActions() {
return Collections.unmodifiableCollection(sortActions(actions.values()));
}
public List<Action> getActions(String category) {
List<Action> result = new LinkedList<Action>();
Collection<String> ids;
synchronized (this) {
ids = categories.get(category);
}
if (ids != null) {
for (String id : ids) {
Action action = actions.get(id);
if (action != null && action.isEnabled()) {
// UI type action compat check
Action finalAction = getClonedAction(action);
applyCompatibility(category, finalAction);
// return only enabled actions
result.add(finalAction);
}
}
}
result = sortActions(result);
return result;
}
protected void applyCompatibility(Action finalAction) {
if (finalAction != null && finalAction.getType() == null) {
// iterate over all categories to apply compat
String[] cats = finalAction.getCategories();
if (cats != null) {
for (String cat : cats) {
if (applyCompatibility(cat, finalAction)) {
break;
}
}
}
}
}
protected boolean applyCompatibility(String category, Action finalAction) {
if (finalAction != null && finalAction.getType() == null) {
for (TypeCompatibility compat : typeCategoryRelations) {
for (String compatCategory : compat.getCategories()) {
if (StringUtils.equals(compatCategory, category)) {
finalAction.setType(compat.getType());
if (applyCustomCompatibility(compat.getType(), finalAction)) {
return true;
}
}
}
}
}
return false;
}
/**
* Displays specific help messages for migration of actions.
*
* @since 6.0
*/
protected boolean applyCustomCompatibility(String compatType, Action action) {
// 6.0 BBB: home/admin tab actions migrated to widgets
if ("admin_rest_document_link".equals(compatType) || "home_rest_document_link".equals(compatType)) {
boolean applied = false;
String link = action.getLink();
if (link != null && !link.startsWith("/")) {
action.setLink("/" + link);
applied = true;
}
if (applied) {
log.warn(String.format("Applied compatibility to action '%s', its configuration "
+ "should be reviewed: make sure the link references an " + "absolute path", action.getId()));
return true;
}
}
return false;
}
public synchronized Action getAction(String id) {
Action action = actions.get(id);
Action finalAction = getClonedAction(action);
applyCompatibility(finalAction);
return finalAction;
}
protected Action getClonedAction(Action action) {
if (action == null) {
return null;
}
return action.clone();
}
protected static List<Action> sortActions(Collection<Action> actions) {
List<Action> sortedActions = new ArrayList<Action>();
if (actions != null) {
sortedActions.addAll(actions);
Collections.sort(sortedActions);
}
return sortedActions;
}
public List<TypeCompatibility> getTypeCategoryRelations() {
return typeCategoryRelations;
}
public void setTypeCategoryRelations(List<TypeCompatibility> typeCategoryRelations) {
this.typeCategoryRelations = typeCategoryRelations;
}
}