/*******************************************************************************
* Copyright 2015 alladin-IT GmbH
*
* 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 at.alladin.rmbt.util.model.option;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class ServerOptionContainer implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private final String FUNCTION_DROP_PARAM = "drop_param";
public Map<ServerOption, ServerOption> selectedMap = new HashMap<>();
public List<ServerOption> rootOptionList;
private OptionFunctionCallback functionCallback;
public ServerOptionContainer(final List<ServerOption> serverOptionList) {
this.rootOptionList = new ArrayList<>();
this.rootOptionList.addAll(serverOptionList);
for (final ServerOption o : rootOptionList) {
this.selectedMap.put(o, null);
}
}
public void registerFunctionCallback(final OptionFunctionCallback functionCallback) {
this.functionCallback = functionCallback;
}
public void unregisterFunctionCallback() {
this.functionCallback = null;
}
public List<ServerOption> getRootOptions() {
checkDependencies();
return rootOptionList;
}
public ServerOption getDefault(final ServerOption option) {
return null;
}
public void setDefault() {
for (final ServerOption o : rootOptionList) {
setDefault(o);
}
}
private boolean setDefault(final ServerOption option) {
if (option.getOptionList() != null && !option.isDefault()) {
for (final ServerOption subOption : option.getOptionList()) {
if (setDefault(subOption)) {
return true;
}
}
}
else if (option.isDefault()) {
select(option);
ServerOption p = option.getParent();
while (p != null) {
p.setChecked(true);
p = p.getParent();
}
return true;
}
return false;
}
private ServerOption setSelected(final ServerOption option, final ServerOption parent) {
if (parent.getParent() != null) {
return setSelected(option, parent.getParent());
}
else {
selectedMap.put(parent, option);
return parent;
}
}
/**
* unselects given option and returns main parent
* @param option
* @return
*/
public ServerOption unselect(final ServerOption option) {
option.setChecked(false);
final ServerOption parent = setSelected(null, option);
checkDependencies();
return parent;
}
/**
* selects given option and returns a list of suboptions or null if selected option was last in hierarchy
* @param option
* @return
*/
public List<ServerOption> select(final ServerOption option) {
if (option.isEnabled()) {
if (!option.isChecked()) {
//if selected option not checked yet, unselect all other parent's options
if (option.getParent() != null && option.getParent().getOptionList() != null) {
for (final ServerOption o : option.getParent().getOptionList()) {
o.setChecked(false);
}
}
setSelected(option, option);
option.setChecked(true);
}
checkDependencies();
if (option.optionList != null && option.optionList.size() > 0) {
return option.getOptionList();
}
}
return null;
}
/**
*
* @return
*/
public Map<String, Object> getSelectedParams() {
return getSelectedParams(true);
}
/**
* returns all parameters from the current selected options
* @return
*/
private Map<String, Object> getSelectedParams(boolean isUserRequest) {
final Map<String, Object> paramMap = new HashMap<>();
for (Entry<ServerOption, ServerOption> e : selectedMap.entrySet()) {
if (e.getValue() != null && e.getKey().isEnabled()) {
generateSelectedParams(paramMap, e.getValue(), isUserRequest);
}
}
return paramMap;
}
private void generateSelectedParams(final Map<String, Object> paramMap, final ServerOption option, boolean isUserRequest) {
if (option.isEnabled()) {
fillSelectedParamsFromOption(paramMap, option);
runFunctionsAfterParamSet(option, paramMap, isUserRequest);
if (option.getParent() != null) {
generateSelectedParams(paramMap, option.getParent(), isUserRequest);
}
}
}
/**
*
* @param paramMap
* @param option
* @return
*/
private void fillSelectedParamsFromOption(final Map<String, Object> paramMap, final ServerOption option) {
if (option.getParameterMap() != null) {
for (final Entry<String, Object> e : option.getParameterMap().entrySet()) {
if (!paramMap.containsKey(e.getKey())) {
paramMap.put(e.getKey(), e.getValue());
}
}
}
}
/**
*
* @param option
* @param paramMap
*/
private void runFunctionsAfterParamSet(final ServerOption option, final Map<String, Object> paramMap, final boolean isUserRequest) {
if (option.getFunctionList() != null) {
for (final OptionFunction func : option.getFunctionList()) {
if (func.getName().equals(FUNCTION_DROP_PARAM) && isUserRequest) {
OptionFunctionUtil.funcDropParam(paramMap, func);
}
else if (isUserRequest) {
if (functionCallback != null) {
functionCallback.onCall(option, func);
}
}
}
}
}
/**
*
*/
private void checkDependencies() {
final Map<String, Object> paramMap = getSelectedParams(false);
for (final ServerOption o : selectedMap.keySet()) {
checkDependenciesRecursive(o, paramMap);
}
}
/**
*
* @param option
* @param paramMap
*/
private void checkDependenciesRecursive(final ServerOption option, final Map<String, Object> paramMap) {
option.setEnabled(checkOptionDependencies(option, paramMap));
if (option.isEnabled() && option.getOptionList() != null) {
for (final ServerOption subOption : option.getOptionList()) {
checkDependenciesRecursive(subOption, paramMap);
}
}
}
/**
*
* @param option
* @param paramMap
* @return
*/
private boolean checkOptionDependencies(final ServerOption option, final Map<String, Object> paramMap) {
if (option.getDependsOnMap() != null) {
for (Entry<String, Object> e : option.getDependsOnMap().entrySet()) {
if (!paramMap.containsKey(e.getKey()) || !paramMap.get(e.getKey()).equals(e.getValue())) {
return false;
}
}
}
return true;
}
/**
*
* @param option
* @return
*/
public boolean isAnyChildSelected(final ServerOption option) {
if (option.getOptionList() != null) {
for (final ServerOption o : option.getOptionList()) {
if (o.isChecked()) {
return true;
}
}
return false;
}
return true;
}
/**
*
* @param option
* @return
*/
public List<ServerOption> getSelectedSubOptions(final ServerOption option) {
return getSelectedSubOptionsRecursive(option, option);
}
/**
*
* @param parent
* @param option
* @return
*/
private List<ServerOption> getSelectedSubOptionsRecursive(final ServerOption parent, final ServerOption option) {
if (parent.getParent() != null) {
return getSelectedSubOptionsRecursive(parent.getParent(), option);
}
else {
final List<ServerOption> subList = new ArrayList<>();
ServerOption selectedOption = selectedMap.get(parent);
if (selectedOption != null) {
while (selectedOption.getParent() != null && !selectedOption.equals(option)) {
subList.add(selectedOption);
selectedOption = selectedOption.getParent();
}
}
return subList;
}
}
}