/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * 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 * Affero 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/. */ package com.rapidminer.gui.properties; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.logging.Level; import com.rapidminer.RapidMiner; import com.rapidminer.parameter.ParameterType; import com.rapidminer.tools.I18N; import com.rapidminer.tools.LogService; import com.rapidminer.tools.ParameterService; /** * An instance of this class represents either a group, a sub-group or a parameter of the * {@link SettingsDialog}. * * Parent/child relations are completely handled in the constructors. * * @author Adrian Wilke */ public class SettingsItem { /** * Regarding the {@link SettingsDialog}, this represents either a tab (GROUP), a heading in a * tab (SUB_GROUP), or a setting by a parameter (PARAMETER) */ public enum Type { GROUP, SUB_GROUP, PARAMETER } public final static String DEFAULT_PARAMETER_PREFIX = "rapidminer."; /** Key of properties file */ private String key; /** The type of this item */ private Type type; /** Parent of current element */ private SettingsItem parent; /** Children of current element */ private List<SettingsItem> children = new LinkedList<>(); /** Indicates, if this item has been used in the settings dialog */ private boolean usedInDialog = false; /** * Sets object variables and updates parent/child relations. * * @param key * The elements key * @param parent * Parent SettingsItem or <code>null</code>, if there is none * @param type * The type of the item */ public SettingsItem(String key, SettingsItem parent, Type type) { if (key == null || key.isEmpty()) { throw new IllegalArgumentException( "Settings item has no Key." + (parent == null ? "" : " Parent: " + parent.toString())); } if (type == null) { throw new IllegalArgumentException( "Settings item has no type." + (parent == null ? "" : " Parent: " + parent.toString())); } this.key = key; this.parent = parent; this.type = type; if (parent != null) { parent.addChild(this); } } /** * Adds item to the list of children. */ public void addChild(SettingsItem child) { children.add(child); } /** * Returns all children of this item. */ public List<SettingsItem> getChildren() { return children; } /** * Returns all children of the specified type. */ public List<SettingsItem> getChildren(Type type) { return getChildren(type, null); } /** * Returns all children in regard of the specified type and filter. */ public List<SettingsItem> getChildren(Type type, String filter) { List<SettingsItem> childs = new LinkedList<>(); for (SettingsItem child : children) { if (child.type.equals(type) && isInFilter(child, filter)) { childs.add(child); } } return childs; } /** * Checks if the given child matches the filter. */ public boolean isInFilter(SettingsItem child, String filter) { if (!child.type.equals(Type.PARAMETER)) { return true; } if (filter != null && !filter.trim().isEmpty()) { String trimmedFilter = filter.trim(); String[] filterTokens = trimmedFilter.split(" "); for (String token : filterTokens) { String unifiedToken = token.toLowerCase(Locale.ENGLISH); if (!child.type.equals(Type.PARAMETER)) { return true; } else if (child.getKey().toLowerCase(Locale.ENGLISH).contains(unifiedToken)) { return true; } else if (child.getTitle() != null && child.getTitle().toLowerCase(Locale.ENGLISH).contains(unifiedToken)) { return true; } else if (child.getDescription() != null && child.getDescription().toLowerCase(Locale.ENGLISH).contains(unifiedToken)) { return true; } } return false; } else { return true; } } /** * Returns the corresponding i18n string if the key was found or an empty String, if the key was * not found. * * Logs a warning message, if the i18n description could not be found. */ public String getDescription() { String description = I18N.getSettingsMessage(key, I18N.SettingsType.DESCRIPTION); if (description.equals(key + I18N.SettingsType.DESCRIPTION)) { // If the strings are equal, no description is available. // Show warning, if in debug mode if (Boolean.parseBoolean(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_DEBUGMODE))) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsItem.no_i18n_description_error", key); } return ""; } else { return description; } } /** * Returns the group key. Or <code>null</code>, if the group key is not known. */ public String getGroupKey() { return ParameterService.getGroupKey(getKey()); } /** * Returns the hierarchy of the current item and its children. Contains one item per line. */ public String getHierarchy() { return getHierarchy(0).toString(); } /** * Returns the hierarchy of the current item and its children. Contains one item per line. * * @param indent * The indent in number of white spaces */ private StringBuilder getHierarchy(int indent) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < indent; i++) { sb.append(" "); } if (type.equals(Type.PARAMETER)) { sb.append("["); } sb.append(getKey()); sb.append(" | "); sb.append(getTitle()); if (type.equals(Type.PARAMETER)) { sb.append("]"); } sb.append(System.lineSeparator()); for (SettingsItem settingsItem : children) { sb.append(settingsItem.getHierarchy(indent + 1)); } return sb; } /** * Returns the properties key. This identifies the current item. */ public String getKey() { return key; } /** * Returns the type of the defined parameter identified by its ID. Returns <code>null</code> if * its key is unknown. */ public ParameterType getParameterType() { return ParameterService.getParameterType(key); } /** * Returns the parent of this item or <code>null</code>, if no parent item exists. */ public SettingsItem getParent() { return parent; } /** * Returns a i18n string if found or the key if not found. * * Logs a warning message, if a i18n string could not be found and the debug mode is activated. * * If this item is of type group and there is no i18n specified, the group-key is used and * formatted. */ public String getTitle() { String title = I18N.getSettingsMessage(key, I18N.SettingsType.TITLE); if (title.equals(key + I18N.SettingsType.TITLE)) { // Show warning, if in debug mode if (Boolean.parseBoolean(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_DEBUGMODE))) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsItem.no_i18n_title_error", key); } // Do not use the '.title' suffix title = key; if (getType().equals(Type.GROUP)) { title = title.replace("_", " "); title = new String(new char[] { title.charAt(0) }).toUpperCase() + title.substring(1, title.length()); } else if (getType().equals(Type.SUB_GROUP)) { // Remove 'rapidminer.settings.subgroup.' int prefixLength = SettingsXmlHandler.SUBGROUP_PREFIX.length(); if (title.length() > prefixLength) { title = title.substring(prefixLength); } // Remove group name int index = title.indexOf("."); if (index != -1) { title = title.substring(index); } // Replacements title = title.replace(".", " "); title = title.replace("_", " "); title = title.trim(); if (!title.isEmpty()) { title = new String(new char[] { title.charAt(0) }).toUpperCase() + title.substring(1, title.length()); } } else { // Remove 'rapidminer.' if (title.startsWith(DEFAULT_PARAMETER_PREFIX)) { title = title.substring(DEFAULT_PARAMETER_PREFIX.length()); } // Remove group prefix if (getGroupKey() != null) { String groupPrefix = getGroupKey() + "."; if (title.startsWith(groupPrefix)) { title = title.substring(groupPrefix.length()); } } title = title.replace("_", " "); title = title.replace(".", " "); title = title.trim(); if (!title.isEmpty()) { title = new String(new char[] { title.charAt(0) }).toUpperCase() + title.substring(1, title.length()); } } } return title; } /** * Returns the type of this items. */ public Type getType() { return type; } /** * Returns <code>true</code> if this item has already been added to the settings dialog. This is * useful to check, if a sub-group (represented by an heading in a dialog tab) has already been * added. */ public boolean isUsedInDialog() { return usedInDialog; } /** Sets if this item has been added to the settings dialog. */ public void setUsedInDialog(boolean usedInDialog) { this.usedInDialog = usedInDialog; } /** * Returns the settings hierarchy of the current element. Every element is represented by its * key. */ @Override public String toString() { StringBuffer sb = new StringBuffer(); if (parent != null) { sb.append(parent.toString()); sb.append(" | "); } if (type.equals(Type.PARAMETER)) { sb.append("["); } sb.append(key); if (type.equals(Type.PARAMETER)) { sb.append("]"); } return sb.toString(); } }