/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.cursorservice;
import java.util.HashSet;
import java.util.Set;
import org.csstudio.platform.model.pvs.IProcessVariableAddress;
import org.csstudio.platform.simpledal.ProcessVariableConnectionServiceFactory;
import org.csstudio.platform.simpledal.SettableState;
import org.csstudio.sds.model.AbstractWidgetModel;
import org.csstudio.sds.model.ActionData;
/**
* The cursor selection rule used at DESY. This rule selects a cursor based on
* the enablement of the widget and, if the widget has any ouput channels, based
* on write access permissions for the output channels.
*
* @author swende, Joerg Rathlev
*/
public final class DesyRule extends CursorSelectionRule {
/**
* Cursor state ID of the default cursor state.
*/
private static final String DEFAULT = "default";
/**
* Cursor state ID for disabled widgets.
*/
private static final String WIDGET_DISABLED = "widgetDisabled";
/**
* Cursor state ID for widgets with an output channel which they cannot
* access.
*/
private static final String ACCESS_DENIED = "accessDenied";
/**
* Cursor state ID for widgets with a writable output channel.
*/
private static final String ACCESS_ALLOWED = "accessAllowed";
/**
* Cursor state ID for widgets with an output channel whose access
* permission are unknown.
*/
private static final String ACCESS_UNKNOWN = "accessUnknwon";
/**
* Cursor state ID for widgets which are disabled by the CSS security
* system.
*/
private static final String NO_PERMISSION = "noPermission";
/**
* Cursor state ID for widgets which have a configureed output channel, but
* access to it is denied by preference.
*/
private static final String WRITE_ACCESS_DENIED = "writeAccessDenied";
private static final String ACTION_AVAILABLE = "actionDataAvailable";
/**
* Returns the cursor state this rule associates with the given widget.
*
* @param widget
* the widget.
* @return the cursor state this rule associates with the given widget.
*/
@Override
public String determineState(final AbstractWidgetModel widget) {
// Default
String state = ACCESS_ALLOWED;
// Priority 1: Is the widget enabled/disabled ?
if(!widget.isLive()) {
state = widget.getCursorId();
}else if (widget.isAccesible()) {
// Is there any write access to a channel configured and is the user
// allowed to set a value for that channel ?
Set<SettableState> settableStates = getSettableStates(widget.getPvAdressesWithWriteAccess());
if (settableStates.size() == 0) {
state = calculateStateForActionData(widget, DEFAULT);
} else if (settableStates.size() == 1) {
state = calculateAccessibleState(widget, settableStates.iterator().next());
} else if (settableStates.size() > 1) {
// We may have a mix of pvs (possibly some are settable, some not)
state = calculateStateForPvSet(widget, settableStates);
}
} else {
state = calculateStateForWidget(widget);
}
assert state != null : "state must not be null";
return state;
}
/**
* @param widget
* @param settableStates
* @return
*/
private String calculateStateForPvSet(final AbstractWidgetModel widget,
final Set<SettableState> settableStates) {
String state = null;
for (SettableState settableState : settableStates) {
String tmp = calculateAccessibleState(widget, settableState);
if(state==null) {
state = tmp;
}
if(!state.equals(tmp)) {
state = ACCESS_UNKNOWN;
break;
}
}
return state;
}
/**
* @param widget
* @param settableState
* @return
*/
private String calculateAccessibleState(final AbstractWidgetModel widget,
final SettableState settableState) {
String state = ACCESS_ALLOWED;
if (settableState.equals(SettableState.UNKNOWN)) {
state = calculateStateForActionData(widget, ACCESS_UNKNOWN);
} else if (settableState.equals(SettableState.NOT_SETTABLE)) {
state = ACCESS_DENIED;
}
return state;
}
/*
* Check if the widget has a permission id. If yes, check if the widget is disabled
* because the user does not have the required permission.
*/
private String calculateStateForWidget(final AbstractWidgetModel widget) {
String state = WIDGET_DISABLED;
if (!widget.isAccessGranted()) {
state = NO_PERMISSION;
} else if (!widget.isWriteAccessAllowed()) {
state = WRITE_ACCESS_DENIED;
}
return state;
}
/**
* @param widget
* @param state
* @return
*/
private String calculateStateForActionData(final AbstractWidgetModel widget, final String state) {
ActionData actionData = widget.getActionData();
if((actionData!=null) && !actionData.getWidgetActions().isEmpty()) {
return ACTION_AVAILABLE;
}
return state;
}
/**
* @param pvs
* @return
*/
private Set<SettableState> getSettableStates(final Set<IProcessVariableAddress> pvs) {
Set<SettableState> settableStates = new HashSet<SettableState>();
for (IProcessVariableAddress pv : pvs) {
settableStates.add(ProcessVariableConnectionServiceFactory.getDefault()
.createProcessVariableConnectionService()
.checkWriteAccessSynchronously(pv));
}
return settableStates;
}
}