diff --git a/build.gradle b/build.gradle index 354151cd0..3504a3e5b 100644 --- a/build.gradle +++ b/build.gradle @@ -20,10 +20,10 @@ repositories { dependencies { // belt project for new data core - compile 'com.rapidminer:belt:0.2.0' + compile 'com.rapidminer:belt:0.3' // belt adapter for conversion between old and new core - compile ('com.rapidminer:belt-adapter:0.1.0'){ + compile ('com.rapidminer:belt-adapter:0.2'){ exclude group: 'com.rapidminer.studio', module: 'rapidminer-studio-core' } @@ -38,13 +38,13 @@ dependencies { } // RapidMiner API - compile 'com.rapidminer:rapidminer-api:0.2.1' + compile 'com.rapidminer:rapidminer-api:0.2.2' // Alphanumeric sorting compile 'com.rapidminer.external:alphanumeric-sorting:1.0.1' // VLDocking as docking framework (https://code.google.com/p/vldocking/) - compile 'com.rapidminer.external:vldocking:1.2.2' + compile 'com.rapidminer.external:vldocking:9.0.1' // Freehep for vector graphic export (http://java.freehep.org/) compile('org.freehep:freehep-graphicsio-ps:2.3') { @@ -155,7 +155,7 @@ dependencies { compile 'org.jsoup:jsoup:1.8.3' // access to windows registry - compile 'net.java.dev.jna:jna-platform:4.5.1' + compile 'net.java.dev.jna:jna-platform:4.5.2' // tests require mockito testCompile 'org.mockito:mockito-core:2.13.0' diff --git a/gradle.properties b/gradle.properties index 6f68a3e73..ac2ac9190 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version=9.0.0 +version=9.1.0 group=com.rapidminer.studio diff --git a/src/main/java/com/rapidminer/Process.java b/src/main/java/com/rapidminer/Process.java index 06d3adf0a..a6f04283f 100644 --- a/src/main/java/com/rapidminer/Process.java +++ b/src/main/java/com/rapidminer/Process.java @@ -844,10 +844,12 @@ public void removeBreakpointListener(final BreakpointListener listener) { /** Fires the event that the process was paused. */ private void fireBreakpointEvent(final Operator operator, final IOContainer ioContainer, final int location) { + LinkedList l; synchronized (breakpointListeners) { - for (BreakpointListener l : breakpointListeners) { - l.breakpointReached(this, operator, ioContainer, location); - } + l = new LinkedList<>(breakpointListeners); + } + for (BreakpointListener listener : l) { + listener.breakpointReached(this, operator, ioContainer, location); } } diff --git a/src/main/java/com/rapidminer/RapidMiner.java b/src/main/java/com/rapidminer/RapidMiner.java index 7e1ecd5e3..f4537a0a1 100644 --- a/src/main/java/com/rapidminer/RapidMiner.java +++ b/src/main/java/com/rapidminer/RapidMiner.java @@ -28,13 +28,13 @@ import java.io.PrintWriter; import java.security.AccessControlException; import java.security.AccessController; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Scanner; +import java.util.Locale; import java.util.Set; -import java.util.Vector; import java.util.logging.Level; import com.rapidminer.core.license.ActionStatisticsLicenseManagerListener; @@ -63,6 +63,7 @@ import com.rapidminer.parameter.ParameterTypeInt; import com.rapidminer.parameter.ParameterTypePassword; import com.rapidminer.parameter.ParameterTypeString; +import com.rapidminer.parameter.conditions.EqualTypeCondition; import com.rapidminer.repository.RepositoryManager; import com.rapidminer.security.PluginSandboxPolicy; import com.rapidminer.settings.Telemetry; @@ -87,6 +88,7 @@ import com.rapidminer.tools.cipher.KeyGeneratorTool; import com.rapidminer.tools.config.ConfigurationManager; import com.rapidminer.tools.plugin.Plugin; +import com.rapidminer.tools.update.internal.MigrationManager; import com.rapidminer.tools.usagestats.ActionStatisticsCollector; import com.rapidminer.tools.usagestats.UsageStatistics; @@ -225,7 +227,12 @@ public boolean isLoadingManagedExtensions() { public static final String PROPERTY_RAPIDMINER_INIT_OPERATORS = "rapidminer.init.operators"; public static final String PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE = "rapidminer.general.locale.language"; + private static final String[] PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE_VALUES = {Locale.ENGLISH.getLanguage()}; + /** @deprecated since 9.1 */ + @Deprecated public static final String PROPERTY_RAPIDMINER_GENERAL_LOCALE_COUNTRY = "rapidminer.general.locale.country"; + /** @deprecated since 9.1 */ + @Deprecated public static final String PROPERTY_RAPIDMINER_GENERAL_LOCALE_VARIANT = "rapidminer.general.locale.variant"; /** @@ -393,10 +400,15 @@ public boolean isLoadingManagedExtensions() { public static final String PROPERTY_RAPIDMINER_GENERAL_TIME_ZONE = "rapidminer.general.timezone"; /** - * The maximum number of working threads that should be used by processes. + * The maximum number of working threads that should be used by the foreground process. */ public static final String PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS = "rapidminer.general.number_of_threads"; + /** + * The maximum number of working threads that should be used by background processes. + */ + public static final String PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS_BACKGROUND = "rapidminer.general.number_of_threads_background"; + /** * The maximum number of working threads that should be used by processes. */ @@ -408,7 +420,7 @@ public boolean isLoadingManagedExtensions() { * have to be adjusted as well. */ public static final String PROPERTY_RAPIDMINER_UPDATE_BETA_FEATURES = "rapidminer.update.beta_features.v2"; - + /** * The name of the property indicating whether or not additional permissions should be enabled */ @@ -420,7 +432,7 @@ public boolean isLoadingManagedExtensions() { * this property can be used to limit the maximum amount of memory RM Studio will use (in MB) */ public static final String PROPERTY_RAPIDMINER_MAX_MEMORY = "maxMemory"; - + /** * The name of the property indicating whether the row based legacy data management should be used. */ @@ -451,7 +463,7 @@ public boolean isLoadingManagedExtensions() { public static final String PROPERTY_RAPIDMINER_SOCKS_PROXY_HOST = "rapidminer.proxy.socksProxyHost"; public static final String PROPERTY_RAPIDMINER_SOCKS_PROXY_PORT = "rapidminer.proxy.socksProxyPort"; public static final String PROPERTY_RAPIDMINER_SOCKS_VERSION = "rapidminer.proxy.socksProxyVersion"; - public final static String[] RAPIDMINER_SOCKS_VERSIONS = { "Version 4", "Version 5" }; + public static final String[] RAPIDMINER_SOCKS_VERSIONS = { "Version 4", "Version 5" }; /** * Set this parameter to {@code true} to allow https to http redirects @@ -493,41 +505,7 @@ public boolean isLoadingManagedExtensions() { parameterTypesDescription = new HashSet<>(); - // set default language to english - String[] default_language = new String[1]; - default_language[0] = "eng"; - - // scan language definitions. skip comments - Vector languages = new Vector<>(); - Scanner scanLanguageDefs = new Scanner( - RapidMiner.class.getResourceAsStream("/com/rapidminer/resources/i18n/language_definitions.txt")); - try { - while (scanLanguageDefs.hasNextLine()) { - String nextLine = scanLanguageDefs.nextLine(); - if (!nextLine.contains("#")) { - languages.add(nextLine); - } - } - } finally { - scanLanguageDefs.close(); - } - - // if there is less then one language, take default language - if (languages.size() < 1) { - registerParameter( - new ParameterTypeCategory(PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE, "", default_language, 0)); - - } else { - // save vector as array - int idx = 0; - String[] languageArray = new String[languages.size()]; - for (String lang : languages) { - languageArray[idx] = lang; - ++idx; - } - registerParameter(new ParameterTypeCategory(PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE, "", languageArray, 0)); - } - + registerParameter(new ParameterTypeCategory(PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE, "", PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE_VALUES, 0)); registerParameter( new ParameterTypeInt(PROPERTY_RAPIDMINER_GENERAL_FRACTIONDIGITS_NUMBERS, "", 0, Integer.MAX_VALUE, 3)); registerParameter( @@ -545,6 +523,7 @@ public boolean isLoadingManagedExtensions() { registerParameter( new ParameterTypeBoolean(CapabilityProvider.PROPERTY_RAPIDMINER_GENERAL_CAPABILITIES_WARN, "", false)); registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS, "", 0, Integer.MAX_VALUE, 0)); + registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS_BACKGROUND, "", 0, Integer.MAX_VALUE, 0)); registerParameter( new ParameterTypeInt(PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_PROCESSES, "", 0, Integer.MAX_VALUE, 0)); registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_EDITOR, "", true)); @@ -555,15 +534,24 @@ public boolean isLoadingManagedExtensions() { registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_TOOLS_MAIL_DEFAULT_PROCESS_DURATION_FOR_MAIL, "", 0, Integer.MAX_VALUE, 30)); - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SENDMAIL_COMMAND, "", true)); - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_HOST, "", true)); - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_PORT, "", true)); - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_USER, "", true)); - registerParameter(new ParameterTypePassword(PROPERTY_RAPIDMINER_TOOLS_SMTP_PASSWD, "")); - registerParameter(new ParameterTypeCategory(PROPERTY_RAPIDMINER_TOOLS_SMTP_SECURITY, "", - PROPERTY_RAPIDMINER_TOOLS_SMTP_SECURITY_VALUES, 0)); - registerParameter(new ParameterTypeCategory(PROPERTY_RAPIDMINER_TOOLS_SMTP_AUTHENTICATION, "", - PROPERTY_RAPIDMINER_TOOLS_SMTP_AUTHENTICATION_VALUES, 0)); + ParameterType type = new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SENDMAIL_COMMAND, "", true); + type.registerDependencyCondition(new EqualTypeCondition(null, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD_VALUES, false, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD_SENDMAIL)); + registerParameter(type); + ParameterType[] smtpTypes = { + new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_HOST, "", true), + new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_PORT, "", true), + new ParameterTypeString(PROPERTY_RAPIDMINER_TOOLS_SMTP_USER, "", true), + new ParameterTypePassword(PROPERTY_RAPIDMINER_TOOLS_SMTP_PASSWD, ""), + new ParameterTypeCategory(PROPERTY_RAPIDMINER_TOOLS_SMTP_SECURITY, "", + PROPERTY_RAPIDMINER_TOOLS_SMTP_SECURITY_VALUES, 0), + new ParameterTypeCategory(PROPERTY_RAPIDMINER_TOOLS_SMTP_AUTHENTICATION, "", + PROPERTY_RAPIDMINER_TOOLS_SMTP_AUTHENTICATION_VALUES, 0), + }; + EqualTypeCondition useSmtp = new EqualTypeCondition(null, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD_VALUES, false, PROPERTY_RAPIDMINER_TOOLS_MAIL_METHOD_SMTP); + for (ParameterType smtpType : smtpTypes) { + smtpType.registerDependencyCondition(useSmtp); + registerParameter(smtpType); + } registerParameter(new ParameterTypeBoolean(PROPERTY_RAPIDMINER_TOOLS_DB_ONLY_STANDARD_TABLES, "", true)); registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_TOOLS_DB_LOGIN_TIMEOUT, "", 0, Integer.MAX_VALUE, @@ -574,7 +562,7 @@ public boolean isLoadingManagedExtensions() { // System parameter types registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_MAX_MEMORY, "", 384, Integer.MAX_VALUE, true), "system"); - + registerParameter(new ParameterTypeBoolean(PROPERTY_RAPIDMINER_SYSTEM_LEGACY_DATA_MGMT, "", false), "system"); registerParameter(new ParameterTypeInt(WebServiceTools.WEB_SERVICE_TIMEOUT, "", 1, Integer.MAX_VALUE, 20000), @@ -740,7 +728,7 @@ public static void init(final Product product, final LicenseLocation licenseLoca RepositoryManager.init(); // parse settings xml (before plugins are initialized) - SettingsItems.INSTANCE.parseStudioXml(); + SettingsItems.INSTANCE.loadGrouping(); // generate encryption key if necessary if (!CipherTools.isKeyAvailable()) { @@ -865,52 +853,34 @@ private static void performInitialSettings() { if (performedInitialSettings) { return; } - boolean firstStart = false; - boolean versionChanged = false; + VersionNumber lastVersionNumber = null; - VersionNumber currentVersionNumber = new VersionNumber(getLongVersion()); + VersionNumber currentVersionNumber = getVersion(); File lastVersionFile = new File(FileSystemService.getUserRapidMinerDir(), "lastversion"); - if (!lastVersionFile.exists()) { - firstStart = true; - } else { - String versionString = null; - BufferedReader in = null; - try (FileReader fr = new FileReader(lastVersionFile)) { - in = new BufferedReader(fr); - versionString = in.readLine(); - } catch (IOException e) { - LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), - "com.rapidminer.RapidMiner.reading_global_version_file_error"), e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), - "com.rapidminer.RapidMiner.closing_stream_error", lastVersionFile), e); - } - } - } - - if (versionString != null) { + if (lastVersionFile.exists()) { + try (BufferedReader in = new BufferedReader(new FileReader(lastVersionFile))) { + String versionString = in.readLine(); lastVersionNumber = new VersionNumber(versionString); - if (currentVersionNumber.compareTo(lastVersionNumber) > 0) { - firstStart = true; - } - if (currentVersionNumber.compareTo(lastVersionNumber) != 0) { - versionChanged = true; - } - } else { - firstStart = true; + } catch (IOException e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.RapidMiner.reading_global_version_file_error", e); + } catch (VersionNumber.VersionNumberException e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.RapidMiner.parsing_global_version_file_error", e); } } + boolean firstStart = lastVersionNumber == null || currentVersionNumber.isAbove(lastVersionNumber); + boolean versionChanged = lastVersionNumber != null && !currentVersionNumber.equals(lastVersionNumber); + // init this version (workspace etc.) if (firstStart) { performFirstInitialization(lastVersionNumber, currentVersionNumber); } + if (versionChanged) { + MigrationManager.doMigrate(lastVersionNumber, currentVersionNumber); + } + if (firstStart || versionChanged) { // write version file writeLastVersion(lastVersionFile); @@ -931,7 +901,7 @@ private static void writeLastVersion(final File versionFile) { private static void performFirstInitialization(final VersionNumber lastVersion, final VersionNumber currentVersion) { if (currentVersion != null) { LogService.getRoot().log(Level.INFO, "com.rapidminer.RapidMiner.performing_upgrade", - new Object[] { lastVersion != null ? " from version " + lastVersion : "", currentVersion }); + new Object[] { lastVersion != null ? "from version " + lastVersion : "", currentVersion }); } } @@ -1132,22 +1102,30 @@ private static void initializeProxy() { // parameters for proxy settings registerParameter(new ParameterTypeCategory(RapidMiner.PROPERTY_RAPIDMINER_PROXY_MODE, "", RapidMiner.RAPIDMINER_PROXY_MODES, 0), "proxy"); - // Global exclusion list (applies on all NON_PROXY_HOSTS) - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_PROXY_EXCLUDE, "", true), "proxy"); - // HTTP - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_HTTP_PROXY_HOST, "", true), "proxy"); - registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_HTTP_PROXY_PORT, "", 0, 65535, true), "proxy"); - // HTTPS - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_HTTPS_PROXY_HOST, "", true), "proxy"); - registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_HTTPS_PROXY_PORT, "", 0, 65535, true), "proxy"); - // FTP - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_FTP_PROXY_HOST, "", true), "proxy"); - registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_FTP_PROXY_PORT, "", 0, 65535, true), "proxy"); - - registerParameter(new ParameterTypeString(PROPERTY_RAPIDMINER_SOCKS_PROXY_HOST, "", true), "proxy"); - registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_SOCKS_PROXY_PORT, "", 0, 65535, true), "proxy"); - registerParameter(new ParameterTypeCategory(PROPERTY_RAPIDMINER_SOCKS_VERSION, "", RAPIDMINER_SOCKS_VERSIONS, 1), - "proxy"); + ParameterType[] manualTypes = { + // Global exclusion list (applies on all NON_PROXY_HOSTS) + new ParameterTypeString(PROPERTY_RAPIDMINER_PROXY_EXCLUDE, "", true), + // HTTP + new ParameterTypeString(PROPERTY_RAPIDMINER_HTTP_PROXY_HOST, "", true), + new ParameterTypeInt(PROPERTY_RAPIDMINER_HTTP_PROXY_PORT, "", 0, 65535, true), + // HTTPS + new ParameterTypeString(PROPERTY_RAPIDMINER_HTTPS_PROXY_HOST, "", true), + new ParameterTypeInt(PROPERTY_RAPIDMINER_HTTPS_PROXY_PORT, "", 0, 65535, true), + // FTP + new ParameterTypeString(PROPERTY_RAPIDMINER_FTP_PROXY_HOST, "", true), + new ParameterTypeInt(PROPERTY_RAPIDMINER_FTP_PROXY_PORT, "", 0, 65535, true), + // SOCKS + new ParameterTypeString(PROPERTY_RAPIDMINER_SOCKS_PROXY_HOST, "", true), + new ParameterTypeInt(PROPERTY_RAPIDMINER_SOCKS_PROXY_PORT, "", 0, 65535, true), + new ParameterTypeCategory(PROPERTY_RAPIDMINER_SOCKS_VERSION, "", RAPIDMINER_SOCKS_VERSIONS, 1) + }; + // register dependency to manual proxy mode + int manualIndex = Arrays.asList(RapidMiner.RAPIDMINER_PROXY_MODES).indexOf(RAPIDMINER_PROXY_MODE_MANUAL); + EqualTypeCondition manualSelected = new EqualTypeCondition(null, RapidMiner.PROPERTY_RAPIDMINER_PROXY_MODE, RapidMiner.RAPIDMINER_PROXY_MODES, false, manualIndex); + for (ParameterType type : manualTypes) { + type.registerDependencyCondition(manualSelected); + registerParameter(type, "proxy"); + } ProxySettings.apply(); } @@ -1171,7 +1149,7 @@ public static Set getRapidMinerProperties() { } /** - * @deprecated Use {@link #ParameterService.registerParameter(ParameterType)} instead + * @deprecated Use {@link ParameterService#registerParameter(ParameterType)} instead */ @Deprecated public static void registerYaleProperty(final ParameterType type) { diff --git a/src/main/java/com/rapidminer/adaption/belt/CompatibilityTools.java b/src/main/java/com/rapidminer/adaption/belt/CompatibilityTools.java index 745069cfc..fdd1a6aa3 100644 --- a/src/main/java/com/rapidminer/adaption/belt/CompatibilityTools.java +++ b/src/main/java/com/rapidminer/adaption/belt/CompatibilityTools.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import com.rapidminer.belt.Builders; import com.rapidminer.belt.Column; import com.rapidminer.belt.ColumnTypes; import com.rapidminer.belt.Context; @@ -72,12 +73,11 @@ public static Table convertDatetimeToMilliseconds(Table table, Context context) } // Replace datetime columns by numeric columns containing the epoch milliseconds - TableBuilder builder = Table.from(table); + TableBuilder builder = Builders.newTableBuilder(table); for (String label : datetimeLabels) { - Column replacement = table.transform(label) + Column replacement = table.transform(label).workload(Workload.SMALL) .applyObjectToReal(Instant.class, v -> v != null ? v.toEpochMilli() : Double.NaN, - Workload.SMALL, context).toColumn(); builder.replace(label, replacement); } diff --git a/src/main/java/com/rapidminer/adaption/belt/IOTable.java b/src/main/java/com/rapidminer/adaption/belt/IOTable.java index 39cb6ec5f..7bf0a107a 100644 --- a/src/main/java/com/rapidminer/adaption/belt/IOTable.java +++ b/src/main/java/com/rapidminer/adaption/belt/IOTable.java @@ -74,7 +74,7 @@ public String toString() { str.append(table.height()).append(" examples,").append(Tools.getLineSeparator()); str.append(table.width()).append(" attributes,").append(Tools.getLineSeparator()); - List withRoles = table.withMetaData(ColumnRole.class); + List withRoles = table.select().withMetaData(ColumnRole.class).labels(); boolean first = true; for (String label : withRoles) { if (first) { diff --git a/src/main/java/com/rapidminer/core/license/ProductLinkRegistry.java b/src/main/java/com/rapidminer/core/license/ProductLinkRegistry.java new file mode 100644 index 000000000..dd8a781b7 --- /dev/null +++ b/src/main/java/com/rapidminer/core/license/ProductLinkRegistry.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2001-2018 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.core.license; + +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessControlException; +import java.security.AccessController; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import com.rapidminer.license.StudioLicenseConstants; +import com.rapidminer.license.product.Product; +import com.rapidminer.security.PluginSandboxPolicy; + + +/** + * Registry for custom product links + * + * @author Jonas Wilms-Pfau + * @since 9.1.0 + */ +public enum ProductLinkRegistry { + /** + * Links used for purchase + */ + PURCHASE; + + private final Map productLinkMap = new HashMap<>(0); + + /** + * Registers a link for a product. Any existing mapping for the same productId is overwritten. + * + *

Internal, do not use. + * + * @param productId + * the {@link Product#getProductId() product id} + * @param link + * the link for the product + * @throws NullPointerException + * if one of the parameters is {@code null} + * @throws UnsupportedOperationException + * if used by 3rd parties, or if {@link StudioLicenseConstants#PRODUCT_ID} is used as a product id + * @throws IllegalArgumentException + * if the link is not a valid url + */ + public void register(String productId, String link) { + checkAccess(); + Objects.requireNonNull(productId, "productId must not be null"); + Objects.requireNonNull(link, "link must not be null"); + try { + new URL(link); + } catch (MalformedURLException mue) { + throw new IllegalArgumentException(mue.getMessage(), mue); + } + if (StudioLicenseConstants.PRODUCT_ID.equals(productId)) { + throw new UnsupportedOperationException("Modifications of " + StudioLicenseConstants.PRODUCT_ID + " links are not allowed."); + } + productLinkMap.put(productId, link); + } + + /** + * Returns the link to which the specified licenseProductKey is mapped, or defaultUrl if this registry contains no + * mapping for the key. + * + * @param productId + * the {@link Product#getProductId() product id} + * @param defaultLink + * the default link + * @return the link for the product, or the {@code defaultLink} + **/ + public String get(String productId, String defaultLink) { + if (productId == null || StudioLicenseConstants.PRODUCT_ID.equals(productId)) { + return defaultLink; + } + return productLinkMap.getOrDefault(productId, defaultLink); + } + + /** + * Checks if the caller has the {@link PluginSandboxPolicy#RAPIDMINER_INTERNAL_PERMISSION} + * + * @throws UnsupportedOperationException + * if the caller is not signed + */ + private static void checkAccess() { + try { + if (System.getSecurityManager() != null) { + AccessController.checkPermission(new RuntimePermission(PluginSandboxPolicy.RAPIDMINER_INTERNAL_PERMISSION)); + } + } catch (AccessControlException e) { + throw new UnsupportedOperationException("Internal API, cannot be called by unauthorized sources."); + } + } +} diff --git a/src/main/java/com/rapidminer/example/AttributeWeight.java b/src/main/java/com/rapidminer/example/AttributeWeight.java index 4ea1baf72..f7c823f40 100644 --- a/src/main/java/com/rapidminer/example/AttributeWeight.java +++ b/src/main/java/com/rapidminer/example/AttributeWeight.java @@ -18,6 +18,8 @@ */ package com.rapidminer.example; +import java.util.Objects; + import com.rapidminer.tools.math.Averagable; @@ -111,17 +113,20 @@ public int compareTo(AttributeWeight o) { /** Returns true if both objects have the same name and the same weight. */ @Override public boolean equals(Object o) { - if (!(o instanceof AttributeWeight)) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { return false; } - AttributeWeight w = (AttributeWeight) o; - return this.name.equals(w.name) && (this.weight == w.weight); + AttributeWeight that = (AttributeWeight) o; + return Objects.equals(name, that.name) && + Objects.equals(weight, that.weight); } @Override public int hashCode() { - long bits = Double.doubleToLongBits(this.weight); - return this.name.hashCode() ^ ((int) (bits ^ bits >>> 32)); + return Objects.hash(weight, name); } /** Builds the sum of weights and counters. */ diff --git a/src/main/java/com/rapidminer/example/table/DatabaseDataRow.java b/src/main/java/com/rapidminer/example/table/DatabaseDataRow.java index e3876b339..239ab6752 100644 --- a/src/main/java/com/rapidminer/example/table/DatabaseDataRow.java +++ b/src/main/java/com/rapidminer/example/table/DatabaseDataRow.java @@ -21,6 +21,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.sql.Clob; +import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; @@ -141,11 +142,21 @@ public static double readColumn(ResultSet resultSet, Attribute attribute) throws int valueType = attribute.getValueType(); double value; if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.DATE_TIME)) { - Timestamp timestamp = resultSet.getTimestamp(name); - if (resultSet.wasNull()) { - value = Double.NaN; - } else { - value = timestamp.getTime(); + try { + Timestamp timestamp = resultSet.getTimestamp(name); + if (resultSet.wasNull()) { + value = Double.NaN; + } else { + value = timestamp.getTime(); + } + } catch (ClassCastException e) { + // DBase JDBC driver is a bit special and returns an SQL date here. So try that one as well + Date date = resultSet.getDate(name); + if (resultSet.wasNull()) { + value = Double.NaN; + } else { + value = date.getTime(); + } } } else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.NUMERICAL)) { value = resultSet.getDouble(name); diff --git a/src/main/java/com/rapidminer/gui/ConditionalAction.java b/src/main/java/com/rapidminer/gui/ConditionalAction.java index 11dc0fa82..fc8251cdf 100644 --- a/src/main/java/com/rapidminer/gui/ConditionalAction.java +++ b/src/main/java/com/rapidminer/gui/ConditionalAction.java @@ -76,6 +76,9 @@ public abstract class ConditionalAction extends LoggedAbstractAction { public static final int PROCESS_IS_ON_REMOTE_REPOSITORY = 10; + /** + * Process is stored and editable + */ public static final int PROCESS_SAVED = 11; public static final int PROCESS_RENDERER_IS_VISIBLE = 12; @@ -86,7 +89,13 @@ public abstract class ConditionalAction extends LoggedAbstractAction { public static final int PROCESS_HAS_BREAKPOINTS = 15; - public static final int NUMBER_OF_CONDITIONS = 16; + /** + * Process has a repository location + * @since 9.0.2 + */ + public static final int PROCESS_HAS_REPOSITORY_LOCATION = 16; + + public static final int NUMBER_OF_CONDITIONS = 17; private final int[] conditions = new int[NUMBER_OF_CONDITIONS]; diff --git a/src/main/java/com/rapidminer/gui/DockableMenu.java b/src/main/java/com/rapidminer/gui/DockableMenu.java index 3084acdbd..4a9c08c4a 100644 --- a/src/main/java/com/rapidminer/gui/DockableMenu.java +++ b/src/main/java/com/rapidminer/gui/DockableMenu.java @@ -37,6 +37,7 @@ import com.rapidminer.gui.tools.ResourceDockKey; import com.rapidminer.gui.tools.ResourceMenu; import com.rapidminer.gui.tools.ScrollableJPopupMenu; +import com.rapidminer.tools.I18N; import com.rapidminer.tools.LogService; import com.rapidminer.tools.SystemInfoUtilities; import com.rapidminer.tools.SystemInfoUtilities.OperatingSystem; @@ -188,6 +189,7 @@ void fill() { if ((PerspectiveModel.RESULT.equals(perspectiveName) && ResultDisplay.RESULT_DOCK_KEY.equals(keyName)) || (PerspectiveModel.DESIGN.equals(perspectiveName) && ProcessPanel.PROCESS_PANEL_DOCK_KEY.equals(keyName))) { item.setEnabled(false); + item.setToolTipText(I18N.getGUIMessage("gui.label.dockable.unclosable.tip")); } add(item); ensurePopupHeight(); diff --git a/src/main/java/com/rapidminer/gui/ExampleVisualizer.java b/src/main/java/com/rapidminer/gui/ExampleVisualizer.java index 2be77a2ab..4a79421be 100644 --- a/src/main/java/com/rapidminer/gui/ExampleVisualizer.java +++ b/src/main/java/com/rapidminer/gui/ExampleVisualizer.java @@ -65,9 +65,10 @@ public ExampleVisualizer(ExampleSet exampleSet) { public void startVisualization(final Object objId) { remapIds(); - double idValue = Double.NaN; JComponent main; + int dialogSize = ButtonDialog.MESSAGE; if (idAttribute != null) { + final double idValue; if (idAttribute.isNominal()) { idValue = objId instanceof String ? idAttribute.getMapping().mapString((String) objId) : (Double) objId; } else { @@ -76,6 +77,7 @@ public void startVisualization(final Object objId) { Example example = exampleSet.getExampleFromId(idValue); if (example != null) { main = makeMainVisualizationComponent(example); + dialogSize = ButtonDialog.NARROW; } else { main = new JLabel("No information available for object '" + objId + "'."); } @@ -84,8 +86,8 @@ public void startVisualization(final Object objId) { } ButtonDialogBuilder builder = new ButtonDialogBuilder("example_visualizer_dialog"); - JDialog dialog = builder.setI18nArguments(objId).setContent(main, ButtonDialog.NARROW) - .setButtons(DefaultButtons.CLOSE_BUTTON).build(); + JDialog dialog = builder.setI18nArguments(objId).setContent(main, dialogSize) + .setButtons(DefaultButtons.CLOSE_BUTTON).setOwner(ApplicationFrame.getApplicationFrame()).build(); dialog.setVisible(true); } diff --git a/src/main/java/com/rapidminer/gui/MainFrame.java b/src/main/java/com/rapidminer/gui/MainFrame.java index 43d0b5e9b..03da13dbc 100644 --- a/src/main/java/com/rapidminer/gui/MainFrame.java +++ b/src/main/java/com/rapidminer/gui/MainFrame.java @@ -21,10 +21,9 @@ import java.awt.BorderLayout; import java.awt.Component; import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; +import java.io.File; import java.net.InetAddress; import java.net.URI; import java.net.UnknownHostException; @@ -50,7 +49,6 @@ import com.rapidminer.ProcessLocation; import com.rapidminer.ProcessStorageListener; import com.rapidminer.RapidMiner; -import com.rapidminer.RapidMiner.ExitMode; import com.rapidminer.core.io.data.source.DataSourceFactoryRegistry; import com.rapidminer.core.license.ProductConstraintManager; import com.rapidminer.gui.actions.AboutAction; @@ -524,19 +522,14 @@ public List getFactories() { // check all ConditionalActions on perspective switch getActions().enableActions(); - // toggle result display and process panels properties depending on shwon perspective - boolean isDesign = PerspectiveModel.DESIGN.equals(perspective.getName()); - boolean isResult = PerspectiveModel.RESULT.equals(perspective.getName()); - processPanel.getDockKey().setCloseEnabled(!isDesign); - processPanel.getDockKey().setAutoHideEnabled(!isDesign); - resultDisplay.getDockKey().setCloseEnabled(!isResult); - resultDisplay.getDockKey().setAutoHideEnabled(!isResult); - - // try to request focus for the process renderer so actions are enabled after - // perspective switch and ProcessRenderer is visible - if (getProcessPanel().getProcessRenderer().isShowing()) { - getProcessPanel().getProcessRenderer().requestFocusInWindow(); - } + SwingTools.invokeLater(() -> { + + // try to request focus for the process renderer so actions are enabled after + // perspective switch and ProcessRenderer is visible + if (getProcessPanel().getProcessRenderer().isShowing()) { + getProcessPanel().getProcessRenderer().requestFocusInWindow(); + } + }); }; private long lastUpdate = 0; @@ -685,6 +678,8 @@ public void quit() { toolBarContainer.add(dockingDesktop, BorderLayout.CENTER); systemMonitor.startMonitorThread(); + processPanel.getDockKey().setCloseEnabled(false); + resultDisplay.getDockKey().setCloseEnabled(false); resultDisplay.init(this); // menu bar @@ -1233,8 +1228,20 @@ public void setTitle() { // location string exceeding arbitrary number will be cut into repository name + // /.../ + process name if (locString.length() > MAX_LOCATION_TITLE_LENGTH) { - locString = RepositoryLocation.REPOSITORY_PREFIX + process.getRepositoryLocation().getRepositoryName() - + RepositoryLocation.SEPARATOR + "..." + RepositoryLocation.SEPARATOR + loc.getShortName(); + if (process.getRepositoryLocation() != null) { + locString = RepositoryLocation.REPOSITORY_PREFIX + process.getRepositoryLocation().getRepositoryName() + + RepositoryLocation.SEPARATOR + "..." + RepositoryLocation.SEPARATOR + loc.getShortName(); + } else { + // build a string like /home/jdoe/.../processes/process.rmp + int maxPartLength = MAX_LOCATION_TITLE_LENGTH / 2; + // determine length of the first part + int firstPartEnd = locString.lastIndexOf(File.separator, maxPartLength); + // + 1 to include the separator char + firstPartEnd = firstPartEnd == -1 ? maxPartLength : firstPartEnd + 1; + int secondPartStart = locString.indexOf(File.separator, locString.length() - maxPartLength); + secondPartStart = secondPartStart == -1 ? locString.length() - maxPartLength : secondPartStart; + locString = new StringBuilder().append(locString, 0, firstPartEnd).append("...").append(locString, secondPartStart, locString.length()).toString(); + } } } else { locString = " { perspectiveName = perspective.getName(); - updateSelection(); - + SwingTools.invokeLater(this::updateSelection); }); updatePerspectivePanel(perspectiveController, perspectiveController.getModel().getAllPerspectives()); addComponentListener(new MainToolBarResizer(perspectiveController)); diff --git a/src/main/java/com/rapidminer/gui/OperatorDocumentationBrowser.java b/src/main/java/com/rapidminer/gui/OperatorDocumentationBrowser.java index e90d2f37c..71e569b4d 100644 --- a/src/main/java/com/rapidminer/gui/OperatorDocumentationBrowser.java +++ b/src/main/java/com/rapidminer/gui/OperatorDocumentationBrowser.java @@ -29,6 +29,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Level; @@ -66,11 +67,12 @@ import com.rapidminer.gui.tools.components.FeedbackForm; import com.rapidminer.gui.tools.dialogs.ConfirmDialog; import com.rapidminer.io.process.ProcessOriginProcessXMLFilter; -import com.rapidminer.io.process.ProcessOriginProcessXMLFilter.ProcessOriginState; import com.rapidminer.io.process.XMLTools; import com.rapidminer.operator.Operator; +import com.rapidminer.operator.OperatorCreationException; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.tools.LogService; +import com.rapidminer.tools.OperatorService; import com.rapidminer.tools.WebServiceTools; import com.rapidminer.tools.XMLException; import com.rapidminer.tools.plugin.Plugin; @@ -97,13 +99,10 @@ public class OperatorDocumentationBrowser extends JPanel implements Dockable, Pr public static final String OPERATOR_HELP_DOCK_KEY = "operator_help"; - private JEditorPane editor; private Operator displayedOperator = null; - private URL currentResourceURL = null; - private boolean ignoreSelections = false; private final DockKey DOCK_KEY = new ResourceDockKey(OPERATOR_HELP_DOCK_KEY); @@ -204,10 +203,8 @@ public void setSelection(List selection) { * indicates the corresponding documentation XML file. */ private void assignDocumentation(Operator operator) { - URL resourceURL = getDocResourcePath(operator); changeDocumentation(operator); displayedOperator = operator; - currentResourceURL = resourceURL; } @Override @@ -234,83 +231,12 @@ private class OperatorHelpLinkListener implements HyperlinkListener { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType().equals(EventType.ACTIVATED)) { if (e.getDescription().startsWith("tutorial:")) { - // ask for confirmation before stopping the currently running process and - // opening another one! - if ((RapidMinerGUI.getMainFrame().getProcessState() == Process.PROCESS_STATE_RUNNING - || RapidMinerGUI.getMainFrame().getProcessState() == Process.PROCESS_STATE_PAUSED) - && SwingTools.showConfirmDialog("close_running_process", ConfirmDialog.YES_NO_OPTION) != ConfirmDialog.YES_OPTION) { - return; - } - - // ask user if he wants to save his current process because the example process - // will replace his current process - if (RapidMinerGUI.getMainFrame().isChanged()) { - // current process is flagged as unsaved - int returnVal = SwingTools.showConfirmDialog("save_before_show_tutorial_process", - ConfirmDialog.YES_NO_CANCEL_OPTION); - if (returnVal == ConfirmDialog.CANCEL_OPTION) { - return; - } else if (returnVal == ConfirmDialog.YES_OPTION) { - SaveAction.saveAsync(RapidMinerGUI.getMainFrame().getProcess()); - } - } else { - // current process is not flagged as unsaved - if (SwingTools.showConfirmDialog("show_tutorial_process", - ConfirmDialog.OK_CANCEL_OPTION) == ConfirmDialog.CANCEL_OPTION) { - return; - } - } - + int index = Integer.parseInt(e.getDescription().substring("tutorial:".length())) - 1; try { - if (currentResourceURL == null) { - // should not happen, because then there would be no link in the first - // place - return; - } - Document document = XMLTools.parse(WebServiceTools.openStreamFromURL(currentResourceURL)); - - int index = Integer.parseInt(e.getDescription().substring("tutorial:".length())); - - NodeList nodeList = document.getElementsByTagName("tutorialProcess"); - Node processNode = nodeList.item(index - 1); - Node process = null; - int i = 0; - while (i < processNode.getChildNodes().getLength()) { - if (processNode.getChildNodes().item(i).getNodeName().equals("process")) { - process = processNode.getChildNodes().item(i); - } - i++; - } - - StringWriter buffer = new StringWriter(); - DOMSource processSource = new DOMSource(process); - Transformer t = TransformerFactory.newInstance().newTransformer(); - t.transform(processSource, new StreamResult(buffer)); - Process exampleProcess = new Process(buffer.toString()); - ProcessOriginProcessXMLFilter.setProcessOriginState(exampleProcess, ProcessOriginState.GENERATED_TUTORIAL); - Operator formerOperator = displayedOperator; ignoreSelections = true; - RapidMinerGUI.getMainFrame().setProcess(exampleProcess, true); - Collection displayedOperators = RapidMinerGUI.getMainFrame().getProcess() - .getAllOperators(); - for (Operator item : displayedOperators) { - if (item.getClass().equals(formerOperator.getClass())) { - RapidMinerGUI.getMainFrame().selectOperator(item); - ignoreSelections = false; - } - } - } catch (TransformerException e1) { - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.tools.documentation.ExampleProcess.creating_example_process_error", e1); - } catch (SAXException e1) { - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.tools.documentation.ExampleProcess.parsing_xml_error", e1); - } catch (IOException e1) { - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.tools.documentation.ExampleProcess.reading_file_error", e1); - } catch (XMLException e1) { - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.tools.documentation.ExampleProcess.parsing_xml_error", e1); + openTutorialProcess(displayedOperator.getOperatorDescription().getKey(), index); + } finally { + ignoreSelections = false; } } else if (e.getDescription().startsWith("#")) { @@ -413,6 +339,12 @@ public void setDisplayedOperator(Operator operator) { } } + /** + * Returns the resource path to the operator_name.xml of the given operator + * + * @param op the operator + * @return the resource path + */ public static URL getDocResourcePath(Operator op) { Plugin provider = op.getOperatorDescription().getProvider(); boolean isExtension = provider != null; @@ -424,12 +356,12 @@ public static URL getDocResourcePath(Operator op) { && groupPath.startsWith(OperatorDescription.EXTENSIONS_GROUP_IDENTIFIER)) { // remove extension group identifier - groupPath = groupPath.substring(groupPath.indexOf('/') + 1, groupPath.length()); + groupPath = groupPath.substring(groupPath.indexOf('/') + 1); // remove extension name int firstIndexOfSlash = groupPath.indexOf('/'); if (firstIndexOfSlash != -1) { - groupPath = groupPath.substring(firstIndexOfSlash + 1, groupPath.length()) + "/"; + groupPath = groupPath.substring(firstIndexOfSlash + 1) + "/"; } else { groupPath = ""; } @@ -442,4 +374,131 @@ public static URL getDocResourcePath(Operator op) { return Plugin.getMajorClassLoader().getResource(opDescXMLResourcePath); } + /** + * Tries to open the given tutorial, if the tutorial process exists a confirm dialog is shown + * + * @param operatorKey + * the operator key + * @param tutorialIndex + * index of the tutorial + */ + public static void openTutorialProcess(String operatorKey, int tutorialIndex) { + String[] tutorialProcesses = OperatorDocumentationBrowser.getTutorialProcesses(operatorKey); + if (tutorialIndex < 0 || tutorialIndex >= tutorialProcesses.length) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.documentation.ExampleProcess.invalid_index", new Object[]{operatorKey, tutorialIndex}); + return; + } + + Process exampleProcess; + try { + exampleProcess = new Process(tutorialProcesses[tutorialIndex]); + } catch (IOException | XMLException e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.documentation.ExampleProcess.reading_file_error", e); + return; + } + + ProcessOriginProcessXMLFilter.setProcessOriginState(exampleProcess, ProcessOriginProcessXMLFilter.ProcessOriginState.GENERATED_TUTORIAL); + if (permissionToOpen()) { + RapidMinerGUI.getMainFrame().setProcess(exampleProcess, true); + Collection displayedOperators = RapidMinerGUI.getMainFrame().getProcess() + .getAllOperators(); + for (Operator item : displayedOperators) { + if (operatorKey.equals(item.getOperatorDescription().getKey())) { + RapidMinerGUI.getMainFrame().selectOperator(item); + break; + } + } + } + } + + /** + * Returns the tutorial process xml for the given operator key + * + * @param operatorKey + * the operator key + * @return the tutorial processes + */ + private static String[] getTutorialProcesses(String operatorKey) { + Operator operator; + try { + operator = OperatorService.createOperator(operatorKey); + } catch (OperatorCreationException e) { + LogService.log(LogService.getRoot(), Level.WARNING, e, "com.rapidminer.tools.documentation.ExampleProcess.operator_not_found", operatorKey); + return new String[0]; + } + URL currentResourceURL = OperatorDocumentationBrowser.getDocResourcePath(operator); + Document document = null; + try { + document = XMLTools.parse(WebServiceTools.openStreamFromURL(currentResourceURL)); + } catch (SAXException | IOException e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.documentation.ExampleProcess.parsing_xml_error", e); + return new String[0]; + } + + NodeList nodeList = document.getElementsByTagName("tutorialProcess"); + if (nodeList.getLength() == 0) { + // no tutorial process + return new String[0]; + } + Node process = null; + List processes = new ArrayList<>(); + for (int tutorialPos = 0; tutorialPos < nodeList.getLength(); tutorialPos++) { + Node processNode = nodeList.item(tutorialPos); + for (int i = 0; i < processNode.getChildNodes().getLength(); i++) { + if ("process".equals(processNode.getChildNodes().item(i).getNodeName())) { + process = processNode.getChildNodes().item(i); + break; + } + } + + StringWriter buffer = new StringWriter(); + DOMSource processSource = new DOMSource(process); + try { + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.transform(processSource, new StreamResult(buffer)); + } catch (TransformerException e) { + LogService.getRoot().log(Level.WARNING, + "com.rapidminer.tools.documentation.ExampleProcess.creating_example_process_error", e); + return new String[0]; + } + processes.add(buffer.toString()); + } + + return processes.toArray(new String[0]); + + } + + /** + * Shows a confirmation dialog if needed + * + * @return {@code true} if the user want's to open the tutorial process + */ + private static boolean permissionToOpen() { + // ask for confirmation before stopping the currently running process and + // opening another one! + if ((RapidMinerGUI.getMainFrame().getProcessState() == Process.PROCESS_STATE_RUNNING + || RapidMinerGUI.getMainFrame().getProcessState() == Process.PROCESS_STATE_PAUSED) + && SwingTools.showConfirmDialog("close_running_process", ConfirmDialog.YES_NO_OPTION) != ConfirmDialog.YES_OPTION) { + return false; + } + + // ask user if he wants to save his current process because the example process + // will replace his current process + if (RapidMinerGUI.getMainFrame().isChanged()) { + // current process is flagged as unsaved + int returnVal = SwingTools.showConfirmDialog("save_before_show_tutorial_process", + ConfirmDialog.YES_NO_CANCEL_OPTION); + if (returnVal == ConfirmDialog.CANCEL_OPTION) { + return false; + } else if (returnVal == ConfirmDialog.YES_OPTION) { + SaveAction.saveAsync(RapidMinerGUI.getMainFrame().getProcess()); + } + } else { + // current process is not flagged as unsaved + return SwingTools.showConfirmDialog("show_tutorial_process", + ConfirmDialog.OK_CANCEL_OPTION) != ConfirmDialog.CANCEL_OPTION; + } + return true; + } } + diff --git a/src/main/java/com/rapidminer/gui/Perspective.java b/src/main/java/com/rapidminer/gui/Perspective.java index 12619d5b0..025e402ab 100644 --- a/src/main/java/com/rapidminer/gui/Perspective.java +++ b/src/main/java/com/rapidminer/gui/Perspective.java @@ -21,7 +21,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.logging.Level; @@ -44,7 +43,7 @@ public class Perspective { private final String name; private final Workspace workspace = new Workspace(); - private boolean userDefined = false;; + private boolean userDefined = false; private final ApplicationPerspectives owner; private final PerspectiveModel model; private final PerspectiveProperties properties = new PerspectiveProperties(); @@ -134,17 +133,19 @@ public void delete() { } } - protected void apply(DockingContext dockingContext) { + protected boolean apply(DockingContext dockingContext) { try { workspace.apply(dockingContext); if (model != null) { model.notifyChangeListener(); } + properties.apply(); + return true; } catch (WorkspaceException e) { LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), - "com.rapidminer.gui.Perspective.applying_workspace_error", e), e); + "com.rapidminer.gui.Perspective.applying_workspace_error", name), e); + return false; } - properties.apply(); } /** diff --git a/src/main/java/com/rapidminer/gui/PerspectiveChangeListener.java b/src/main/java/com/rapidminer/gui/PerspectiveChangeListener.java index c9a5982e4..61cf6fd27 100644 --- a/src/main/java/com/rapidminer/gui/PerspectiveChangeListener.java +++ b/src/main/java/com/rapidminer/gui/PerspectiveChangeListener.java @@ -26,7 +26,16 @@ */ public interface PerspectiveChangeListener { - /** will be called if the current perspective changes */ + /** + * Will be called if the current perspective changes. + *

+ * This method is not called on the EDT. + * Use {@link com.rapidminer.gui.tools.SwingTools#invokeLater(Runnable) SwingTools.invokeLater} for any GUI manipulation. + *

+ * + * @param perspective + * The new perspective + */ public void perspectiveChangedTo(Perspective perspective); } diff --git a/src/main/java/com/rapidminer/gui/PerspectiveController.java b/src/main/java/com/rapidminer/gui/PerspectiveController.java index f28926394..462d5b7aa 100644 --- a/src/main/java/com/rapidminer/gui/PerspectiveController.java +++ b/src/main/java/com/rapidminer/gui/PerspectiveController.java @@ -56,8 +56,6 @@ public class PerspectiveController { private final PerspectiveModel model; - /** @since 8.2.1 */ - private final Object switchLock = new Object(); /** @since 8.2.1 */ private volatile Perspective switchTo; /** @since 8.2.1 */ @@ -86,15 +84,8 @@ public PerspectiveController(final DockingContext context) { } }); this.model.makePredefined(); - switchTimer = new Timer(1, e -> changePerspective()){ - - @Override - public boolean isRepeats() { - synchronized (switchLock) { - return switchTo != null; - } - } - }; + switchTimer = new Timer(10, e -> changePerspective()); + switchTimer.setRepeats(false); } /** @@ -103,7 +94,7 @@ public boolean isRepeats() { * @param perspectiveName * the perspective which should be shown. */ - public synchronized void showPerspective(final String perspectiveName) { + public void showPerspective(final String perspectiveName) { queuePerspective(perspectiveName); } @@ -114,7 +105,7 @@ public synchronized void showPerspective(final String perspectiveName) { * the name of the perspective to be shown * @since 8.2.1 */ - private synchronized void queuePerspective(String perspectiveName) { + private void queuePerspective(String perspectiveName) { queuePerspective(model.getPerspective(perspectiveName)); } @@ -124,7 +115,7 @@ private synchronized void queuePerspective(String perspectiveName) { * @param perspective * the perspective which should be shown. */ - public synchronized void showPerspective(final Perspective perspective) { + public void showPerspective(final Perspective perspective) { queuePerspective(perspective); } @@ -135,51 +126,56 @@ public synchronized void showPerspective(final Perspective perspective) { * the perspective to bw shown * @since 8.2.1 */ - private synchronized void queuePerspective(Perspective perspective) { + private void queuePerspective(Perspective perspective) { // add this perspective to the queue and restart timer if necessary - synchronized (switchLock) { - boolean startTimer = switchTo == null; - switchTo = perspective; - if (startTimer) { - switchTimer.start(); - } - } + switchTo = perspective; + switchTimer.restart(); } /** * Actually changes the perspective. This should only be called by the {@link #switchTimer} to prevent breaking views. * The timer switches the views that are queued and stops if there are no more switches left in the queue. The timer * will be restarted when a new switch is queued. - * + * * @since 8.2.1 */ - private synchronized void changePerspective() { - synchronized (switchLock) { - if (switchTo == null) { - return; - } - Perspective oldPerspective = model.getSelectedPerspective(); - if (oldPerspective == switchTo) { - switchTo = null; - return; - } - if (!model.getAllPerspectives().contains(switchTo)) { - switchTo = null; + private void changePerspective() { + final Perspective target = switchTo; + if (target == null) { + return; + } + Perspective oldPerspective = model.getSelectedPerspective(); + if (oldPerspective == target) { + switchTo = null; + return; + } + if (!model.getAllPerspectives().contains(target)) { + switchTo = null; + return; + } + model.setSelectedPerspective(target); + if (oldPerspective != null) { + oldPerspective.store(context); + ActionStatisticsCollector.getInstance().stopTimer(oldPerspective); + } + if (!target.apply(context)) { + // retry if switching did not work the first time + if (!target.apply(context)) { + if (oldPerspective != null) { + ActionStatisticsCollector.getInstance().startTimer(oldPerspective, ActionStatisticsCollector.TYPE_PERSPECTIVE, + oldPerspective.getName(), null); + } + // rollback if changing did not work, will be collected by the PerspectiveController switchTimer. + switchTo = oldPerspective; return; } - model.setSelectedPerspective(switchTo); - if (oldPerspective != null) { - oldPerspective.store(context); - ActionStatisticsCollector.getInstance().stopTimer(oldPerspective); - } - switchTo.apply(context); - RapidMinerGUI.getMainFrame().RESTORE_PERSPECTIVE_ACTION.setEnabled(!switchTo.isUserDefined()); - ActionStatisticsCollector.getInstance().startTimer(switchTo, ActionStatisticsCollector.TYPE_PERSPECTIVE, - switchTo.getName(), null); - ActionStatisticsCollector.getInstance().log(ActionStatisticsCollector.TYPE_PERSPECTIVE, switchTo.getName(), - "show"); - switchTo = null; } + RapidMinerGUI.getMainFrame().RESTORE_PERSPECTIVE_ACTION.setEnabled(!target.isUserDefined() && (PerspectiveModel.DESIGN.equals(target.getName()) || PerspectiveModel.RESULT.equals(target.getName()))); + ActionStatisticsCollector.getInstance().startTimer(target, ActionStatisticsCollector.TYPE_PERSPECTIVE, + target.getName(), null); + ActionStatisticsCollector.getInstance().log(ActionStatisticsCollector.TYPE_PERSPECTIVE, target.getName(), + "show"); + switchTo = null; } /** @@ -203,7 +199,7 @@ public void removePerspective(String name) { * @param perspective * the perspective which should be deleted */ - public synchronized void removePerspective(Perspective perspective) { + public void removePerspective(Perspective perspective) { if (!perspective.isUserDefined()) { return; } @@ -329,8 +325,11 @@ public Perspective createUserPerspective(final String name, final boolean show) public void restoreDefaultPerspective() { if (!getModel().getSelectedPerspective().isUserDefined()) { - getModel().restoreDefault(getModel().getSelectedPerspective().getName()); + String viewName = getModel().getSelectedPerspective().getName(); + getModel().restoreDefault(viewName); getModel().getSelectedPerspective().apply(context); + + LogService.getRoot().log(Level.INFO, "com.rapidminer.gui.PerspectiveController.restore_default", viewName); } } diff --git a/src/main/java/com/rapidminer/gui/PerspectiveMenu.java b/src/main/java/com/rapidminer/gui/PerspectiveMenu.java index 787345b1c..fb15576c6 100644 --- a/src/main/java/com/rapidminer/gui/PerspectiveMenu.java +++ b/src/main/java/com/rapidminer/gui/PerspectiveMenu.java @@ -28,6 +28,7 @@ import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceMenu; import com.rapidminer.tools.Observable; +import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.tools.Observer; @@ -66,7 +67,12 @@ public void update(Observable> observable, List p public void perspectiveChangedTo(Perspective perspective) { perspectiveName = perspective.getName(); if (perspectiveMap.containsKey(perspectiveName)) { - perspectiveMap.get(perspectiveName).setSelected(true); + SwingTools.invokeLater(() -> { + JMenuItem item = perspectiveMap.get(perspectiveName); + if (item != null) { + item.setSelected(true); + } + }); } } }; diff --git a/src/main/java/com/rapidminer/gui/PerspectiveModel.java b/src/main/java/com/rapidminer/gui/PerspectiveModel.java index 83d2ef95f..c81ffff86 100644 --- a/src/main/java/com/rapidminer/gui/PerspectiveModel.java +++ b/src/main/java/com/rapidminer/gui/PerspectiveModel.java @@ -31,7 +31,6 @@ import com.rapidminer.gui.properties.OperatorPropertyPanel; import com.rapidminer.repository.gui.RepositoryBrowser; import com.rapidminer.tools.AbstractObservable; -import com.vlsolutions.swing.docking.DockKey; import com.vlsolutions.swing.docking.DockingConstants; import com.vlsolutions.swing.docking.ws.WSDesktop; import com.vlsolutions.swing.docking.ws.WSDockKey; @@ -133,13 +132,6 @@ public void restoreDefault(String perspectiveName) { WSDockKey repositoryKey = new WSDockKey(RepositoryBrowser.REPOSITORY_BROWSER_DOCK_KEY); WSDockKey newOperatorEditorKey = new WSDockKey(NewOperatorEditor.NEW_OPERATOR_DOCK_KEY); WSDockKey operatorHelpKey = new WSDockKey(OperatorDocumentationBrowser.OPERATOR_HELP_DOCK_KEY); - MainFrame mainFrame = RapidMinerGUI.getMainFrame(); - DockKey resultDockKey = null; - DockKey processPanelDockKey = null; - if (mainFrame != null) { - resultDockKey = mainFrame.getResultDisplay().getDockKey(); - processPanelDockKey = mainFrame.getProcessPanel().getDockKey(); - } if (DESIGN.equals(perspectiveName)) { Perspective designPerspective = getPerspective(DESIGN); @@ -150,24 +142,12 @@ public void restoreDefault(String perspectiveName) { designDesktop.split(propertyTableKey, operatorHelpKey, DockingConstants.SPLIT_BOTTOM, .66); designDesktop.split(processPanelKey, repositoryKey, DockingConstants.SPLIT_LEFT, 0.25); designDesktop.split(repositoryKey, newOperatorEditorKey, DockingConstants.SPLIT_BOTTOM, 0.5); - if (mainFrame != null) { - resultDockKey.setCloseEnabled(true); - resultDockKey.setAutoHideEnabled(true); - processPanelDockKey.setCloseEnabled(false); - processPanelDockKey.setAutoHideEnabled(false); - } } else if (RESULT.equals(perspectiveName)) { Perspective resultPerspective = getPerspective(RESULT); WSDesktop resultsDesktop = resultPerspective.getWorkspace().getDesktop(0); resultsDesktop.clear(); resultsDesktop.addDockable(resultsKey); resultsDesktop.split(resultsKey, repositoryKey, DockingConstants.SPLIT_RIGHT, 0.8); - if (mainFrame != null) { - resultDockKey.setCloseEnabled(false); - resultDockKey.setAutoHideEnabled(false); - processPanelDockKey.setCloseEnabled(true); - processPanelDockKey.setAutoHideEnabled(true); - } } else { throw new IllegalArgumentException("Not a predefined view: " + perspectiveName); } diff --git a/src/main/java/com/rapidminer/gui/RapidMinerGUI.java b/src/main/java/com/rapidminer/gui/RapidMinerGUI.java index 119993a25..15b0ba178 100644 --- a/src/main/java/com/rapidminer/gui/RapidMinerGUI.java +++ b/src/main/java/com/rapidminer/gui/RapidMinerGUI.java @@ -161,7 +161,6 @@ public class RapidMinerGUI extends RapidMiner { public static final String PROPERTY_OPEN_IN_FILEBROWSER = "rapidminer.gui.entry_open_in_filebrowser"; public static final String PROPERTY_CLOSE_ALL_RESULTS_NOW = "rapidminer.gui.close_all_results_without_confirmation"; public static final String PROPERTY_FETCH_DATA_BASE_TABLES_NAMES = "rapidminer.gui.fetch_data_base_table_names"; - public static final String PROPERTY_DISCONNECT_ON_DISABLE = "rapidminer.gui.disconnect_on_disable"; /** determines if a warning notification bubble is shown when no result ports are connected */ public static final String PROPERTY_SHOW_NO_RESULT_WARNING = "rapidminer.gui.no_result_port_connected"; public static final String PROPERTY_FONT_CONFIG = "rapidminer.gui.font_config"; @@ -185,6 +184,15 @@ public class RapidMinerGUI extends RapidMiner { public static final String PROPERTY_RAPIDMINER_DISALLOW_REMEMBER_PASSWORD = "rapidminer.disallow.remember.password"; public static final String PROPERTY_RAPIDMINER_DISALLOW_STUDIO_UPDATE = "rapidminer.disallow.studio.update"; + // different behavior for disconnecting deleted and disabled operators + public static final String PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR = "rapidminer.gui.disable_op_conn_behavior"; + public static final String[] PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_VALUES = { "removed", "bridged", "kept" }; + public static final String PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR = "rapidminer.gui.delete_op_conn_behavior"; + public static final String[] PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_VALUES = { "removed", "bridged" }; + public static final int PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE = 1; + public static final int PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE = 1; + + static { // GUI Parameters @@ -208,7 +216,10 @@ public class RapidMinerGUI extends RapidMiner { RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_CLOSE_ALL_RESULTS_NOW, "", DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.ASK)); RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_FETCH_DATA_BASE_TABLES_NAMES, "", true)); - RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_DISCONNECT_ON_DISABLE, "", true)); + + RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR, "", PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_VALUES, PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE)); + RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR, "", PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_VALUES, PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE)); + RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_SHOW_NO_RESULT_WARNING, "", true)); RapidMiner.registerParameter(new ParameterTypeCategory(RapidMinerGUI.PROPERTY_FONT_CONFIG, "", FontTools.getAvailableFonts(), FontTools.OPTION_INDEX_STANDARD_FONTS)); @@ -353,7 +364,6 @@ public synchronized void run(final String openLocation) throws Exception { // with the default product and constraints RapidMiner.init(); - // store (possibly new) active license (necessary, since no // ACTIVE_LICENSE_CHANGED event is fired on startup) LicenseManagerRegistry.INSTANCE.get().getAllActiveLicenses().forEach((l) -> { diff --git a/src/main/java/com/rapidminer/gui/actions/Actions.java b/src/main/java/com/rapidminer/gui/actions/Actions.java index deb715c83..273194e8b 100644 --- a/src/main/java/com/rapidminer/gui/actions/Actions.java +++ b/src/main/java/com/rapidminer/gui/actions/Actions.java @@ -318,6 +318,7 @@ private void enableActionsNow() { currentStates[ConditionalAction.PROCESS_RUNNING] = processState == Process.PROCESS_STATE_RUNNING; currentStates[ConditionalAction.EDIT_IN_PROGRESS] = EditBlockingProgressThread.isEditing(); currentStates[ConditionalAction.PROCESS_SAVED] = process.hasSaveDestination(); + currentStates[ConditionalAction.PROCESS_HAS_REPOSITORY_LOCATION] = process.getRepositoryLocation() != null; currentStates[ConditionalAction.PROCESS_RENDERER_IS_VISIBLE] = mainFrame.getProcessPanel().getProcessRenderer() .isShowing(); currentStates[ConditionalAction.PROCESS_RENDERER_HAS_UNDO_STEPS] = mainFrame.hasUndoSteps(); @@ -339,7 +340,7 @@ public void delete() { if (selectedOperator instanceof ProcessRootOperator) { return; } - if (!"false".equals(ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_DISCONNECT_ON_DISABLE))) { + if ("bridged".equals(ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR))) { ActionUtil.doPassthroughPorts(selectedOperator); } selectedOperator.remove(); diff --git a/src/main/java/com/rapidminer/gui/actions/UpgradeLicenseAction.java b/src/main/java/com/rapidminer/gui/actions/UpgradeLicenseAction.java index 4eea28766..d87c3f9c3 100644 --- a/src/main/java/com/rapidminer/gui/actions/UpgradeLicenseAction.java +++ b/src/main/java/com/rapidminer/gui/actions/UpgradeLicenseAction.java @@ -18,20 +18,20 @@ */ package com.rapidminer.gui.actions; -import com.rapidminer.gui.tools.NotificationPopup; -import com.rapidminer.gui.tools.ResourceAction; -import com.rapidminer.tools.I18N; -import com.rapidminer.tools.LogService; -import com.rapidminer.tools.RMUrlHandler; - import java.awt.Component; import java.awt.event.ActionEvent; import java.util.concurrent.ExecutionException; import java.util.logging.Level; - import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import com.rapidminer.core.license.ProductLinkRegistry; +import com.rapidminer.gui.tools.NotificationPopup; +import com.rapidminer.gui.tools.ResourceAction; +import com.rapidminer.tools.I18N; +import com.rapidminer.tools.LogService; +import com.rapidminer.tools.RMUrlHandler; + /** * This action starts the license upgrade process. @@ -45,12 +45,24 @@ public class UpgradeLicenseAction extends ResourceAction { /** the uri for the license upgrade */ private static final String URI_LICENSE_UPGRADE = I18N.getGUILabel("license.url"); + private String productId; /** * Creates a new {@link UpgradeLicenseAction} instance. */ public UpgradeLicenseAction() { + this(null); + } + + /** + * Creates a new {@link UpgradeLicenseAction} instance. + * + * @param productId + * the product id that caused the action + */ + public UpgradeLicenseAction(String productId) { super(false, "upgrade_license"); + this.productId = productId; } @Override @@ -70,12 +82,12 @@ public void loggedActionPerformed(final ActionEvent e) { * * @return */ - private static SwingWorker createUpgradeWorker() { + private SwingWorker createUpgradeWorker() { return new SwingWorker() { @Override protected Void doInBackground() throws Exception { - RMUrlHandler.handleUrl(URI_LICENSE_UPGRADE); + RMUrlHandler.handleUrl(ProductLinkRegistry.PURCHASE.get(productId, URI_LICENSE_UPGRADE)); return null; } diff --git a/src/main/java/com/rapidminer/gui/actions/search/ActionsGlobalSearchManager.java b/src/main/java/com/rapidminer/gui/actions/search/ActionsGlobalSearchManager.java index 599b688e9..d44950ccb 100644 --- a/src/main/java/com/rapidminer/gui/actions/search/ActionsGlobalSearchManager.java +++ b/src/main/java/com/rapidminer/gui/actions/search/ActionsGlobalSearchManager.java @@ -25,6 +25,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.Action; @@ -95,6 +97,12 @@ public class ActionsGlobalSearchManager extends AbstractGlobalSearchManager { /** when the perspective changes, we need to re-index the dockables to have them up-to-date */ private final PerspectiveChangeListener perspectiveChangeListener; + /** + * actions that are registered are stored here. This is used for a quick lookup if an action is part of the index. + * Searching the actual index takes way more time. + */ + private final Set registeredActions; + protected ActionsGlobalSearchManager() { super(ActionsGlobalSearch.CATEGORY_ID, ADDITIONAL_FIELDS, new GlobalSearchDefaultField(FIELD_DESCRIPTION, FIELD_BOOST_DESCRIPTION)); @@ -113,6 +121,8 @@ protected ActionsGlobalSearchManager() { deleteAllDockableActions(); indexDockables(); }; + + registeredActions = ConcurrentHashMap.newKeySet(); } @Override @@ -206,6 +216,7 @@ public void removeAction(final ResourceAction action) { Document doc = createDocument(action); if (doc != null) { removeDocumentFromIndex(doc); + registeredActions.remove(action.getKey()); } } @@ -221,15 +232,8 @@ public boolean isActionRegistered(final ResourceAction action) { throw new IllegalArgumentException("action must not be null!"); } - // search for element that has id = key - try { - GlobalSearchResultBuilder builder = new GlobalSearchResultBuilder(GlobalSearchUtilities.FIELD_UNIQUE_ID + GlobalSearchUtilities.QUERY_FIELD_SPECIFIER + action.getKey()); - builder.setMaxNumberOfResults(1).setSearchCategories(GlobalSearchRegistry.INSTANCE.getSearchCategoryById(getSearchCategoryId())); - return builder.runSearch().getNumberOfResults() == 1; - } catch (ParseException e) { - LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.actions.search.ActionsGlobalSearchManager.error.delete_views_error", e); - return false; - } + // search for action with given key + return registeredActions.contains(action.getKey()); } /** @@ -317,8 +321,11 @@ private Document createDocument(final ResourceAction action) { fields.add(GlobalSearchUtilities.INSTANCE.createFieldForIdentifiers(FIELD_DOCKABLE_TYPE, String.valueOf(Boolean.TRUE))); } + // add to registered actions map + registeredActions.add(action.getKey()); + // i18n key is the unique ID for the action category - return GlobalSearchUtilities.INSTANCE.createDocument(action.getKey(), String.valueOf(name), fields.toArray(new Field[fields.size()])); + return GlobalSearchUtilities.INSTANCE.createDocument(action.getKey(), String.valueOf(name), fields.toArray(new Field[0])); } /** diff --git a/src/main/java/com/rapidminer/gui/animation/IndeterminateAnimation.java b/src/main/java/com/rapidminer/gui/animation/IndeterminateAnimation.java index 6a35cf1f6..3e91a0f19 100644 --- a/src/main/java/com/rapidminer/gui/animation/IndeterminateAnimation.java +++ b/src/main/java/com/rapidminer/gui/animation/IndeterminateAnimation.java @@ -21,7 +21,6 @@ import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; -import java.awt.geom.AffineTransform; /** @@ -71,25 +70,21 @@ public boolean isRedrawRequired() { @Override public void draw(Graphics2D graphics) { - // store color and transformation - final AffineTransform transform = graphics.getTransform(); - final Color color = graphics.getColor(); + Graphics2D g2 = (Graphics2D) graphics.create(); // go to start position long now = System.currentTimeMillis(); int position = (int) ((now - start) % MS_PER_TURN) / DIVISOR; - graphics.rotate(Math.PI * 2 / NUMBER_OF_CIRCLES * position - Math.PI / 2); + g2.rotate(Math.PI * 2 / NUMBER_OF_CIRCLES * position - Math.PI / 2); // draw the circles for (Color spinnerColor : SPINNER_COLORS) { - graphics.setColor(spinnerColor); - graphics.fillOval(RADIUS_FROM_ORIGIN, 0, RADIUS_SMALL_CIRCLES, RADIUS_SMALL_CIRCLES); - graphics.rotate(-Math.PI * 2 / NUMBER_OF_CIRCLES); + g2.setColor(spinnerColor); + g2.fillOval(RADIUS_FROM_ORIGIN, 0, RADIUS_SMALL_CIRCLES, RADIUS_SMALL_CIRCLES); + g2.rotate(-Math.PI * 2 / NUMBER_OF_CIRCLES); } - // reset color and transformation - graphics.setTransform(transform); - graphics.setColor(color); + g2.dispose(); } @Override diff --git a/src/main/java/com/rapidminer/gui/animation/ProcessAnimationManager.java b/src/main/java/com/rapidminer/gui/animation/ProcessAnimationManager.java index 661b1c4ac..4ef12af90 100644 --- a/src/main/java/com/rapidminer/gui/animation/ProcessAnimationManager.java +++ b/src/main/java/com/rapidminer/gui/animation/ProcessAnimationManager.java @@ -96,17 +96,12 @@ boolean isRepaintRequired() { * Creates an {@link Animation} that shows the {@link OperatorProgress} of the operator. */ private Animation createAnimationForOperator(final Operator operator) { - return new ProgressAnimation(new ProgressProvider() { - - @Override - public int getProgress() { - OperatorProgress progress = operator.getProgress(); - if (progress.isIndeterminate()) { - return 0; - } - return progress.getProgress(); + return new ProgressAnimation(() -> { + OperatorProgress progress = operator.getProgress(); + if (progress.isIndeterminate()) { + return 0; } - + return progress.getProgress(); }); } diff --git a/src/main/java/com/rapidminer/gui/animation/ProgressAnimation.java b/src/main/java/com/rapidminer/gui/animation/ProgressAnimation.java index 52fd8625e..a439b9a51 100644 --- a/src/main/java/com/rapidminer/gui/animation/ProgressAnimation.java +++ b/src/main/java/com/rapidminer/gui/animation/ProgressAnimation.java @@ -24,7 +24,6 @@ import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; -import java.awt.Stroke; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -40,11 +39,11 @@ */ public class ProgressAnimation implements Animation { - /** the maximal angle */ - private static final int FULL_ANGLE = 360; + /** the maximal angle. Not 360 because the stroke is too big. Using 360 the last 10% all look like 100% */ + private static final int FULL_ANGLE = 350; - /** the angle where the arc starts */ - private static final int START_ANGLE = 90; + /** the angle where the arc starts. Slightly offset to the right due to big stroke size */ + private static final int START_ANGLE = 88; /** * the maximal text width, width of the maximal square inside a circle with radius @@ -60,7 +59,7 @@ public class ProgressAnimation implements Animation { private static final BasicStroke STROKE = new BasicStroke(LINE_WIDTH); /** the width of the arc when it is full */ - private static final int CIRCLE_WIDTH = 2 * IndeterminateAnimation.OUTER_RADIUS - LINE_WIDTH; + private static final int CIRCLE_DIAMETER = 2 * IndeterminateAnimation.OUTER_RADIUS - LINE_WIDTH; private static final Color ANIMATION_COLOR = IndeterminateAnimation.SPINNER_COLORS[0]; @@ -96,49 +95,40 @@ public boolean isRedrawRequired() { if (currentProgress == 0) { return indeterminateAnimation.isRedrawRequired(); } - if (currentProgress != lastDrawnProgress) { - return true; - } - return false; + return currentProgress != lastDrawnProgress; } @Override public void draw(Graphics2D graphics) { + Graphics2D g2 = (Graphics2D) graphics.create(); int currentProgress = progressProvider.getProgress(); if (currentProgress == 0) { - indeterminateAnimation.draw(graphics); + indeterminateAnimation.draw(g2); } else { lastDrawnProgress = currentProgress; - // store properties - final Color color = graphics.getColor(); - final Stroke stroke = graphics.getStroke(); - final Font font = graphics.getFont(); - final Object renderingHint = graphics.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL); // draw arc - graphics.setColor(ANIMATION_COLOR); - graphics.setStroke(STROKE); + g2.setColor(ANIMATION_COLOR); + g2.setStroke(STROKE); // rendering hint that prevents arc from wobbling - graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - graphics.drawArc(-CIRCLE_WIDTH / 2, -CIRCLE_WIDTH / 2, CIRCLE_WIDTH, CIRCLE_WIDTH, START_ANGLE, + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2.drawArc(-CIRCLE_DIAMETER / 2, -CIRCLE_DIAMETER / 2, CIRCLE_DIAMETER, CIRCLE_DIAMETER, START_ANGLE, -FULL_ANGLE * currentProgress / 100); // print progress if not 100 if (currentProgress < 100) { - graphics.setFont(platformSpecificFont); + g2.setFont(platformSpecificFont); final String text = "" + currentProgress; double textX = -textWidth / 2; if (currentProgress < 10) { textX = textX / 2; } - graphics.drawString(text, (int) textX, (int) textHeight / 2); + g2.drawString(text, (int) textX, (int) textHeight / 2); } - // restore properties - graphics.setColor(color); - graphics.setStroke(stroke); - graphics.setFont(font); - graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, renderingHint); + g2.dispose(); } } diff --git a/src/main/java/com/rapidminer/gui/flow/ProcessPanel.java b/src/main/java/com/rapidminer/gui/flow/ProcessPanel.java index 47ab5db82..8677e63e8 100644 --- a/src/main/java/com/rapidminer/gui/flow/ProcessPanel.java +++ b/src/main/java/com/rapidminer/gui/flow/ProcessPanel.java @@ -651,6 +651,13 @@ private Rectangle getScrollRectangle(Point center) { Point newViewPoint = new Point(center); Rectangle currentViewRect = getViewPort().getViewRect(); newViewPoint.translate((int) -currentViewRect.getCenterX(), (int) -currentViewRect.getCenterY()); + // Don't scroll outside the viewport + if (newViewPoint.x < 0) { + newViewPoint.x = 0; + } + if (newViewPoint.y < 0) { + newViewPoint.y = 0; + } return new Rectangle(newViewPoint, currentViewRect.getSize()); } diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/annotations/AnnotationsDecorator.java b/src/main/java/com/rapidminer/gui/flow/processrendering/annotations/AnnotationsDecorator.java index b57c844ef..3018b556b 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/annotations/AnnotationsDecorator.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/annotations/AnnotationsDecorator.java @@ -25,6 +25,7 @@ import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; +import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -113,6 +114,7 @@ public final class AnnotationsDecorator { /** icon depicting annotations on an operator */ private static final ImageIcon IMAGE_ANNOTATION = SwingTools.createIcon("16/note_pinned.png"); + private static final ImageIcon IMAGE_ANNOTATION_ZOOMED = SwingTools.createIcon("32/note_pinned.png"); /** the width of the edit panel above/below the annotation editor */ private static final int EDIT_PANEL_WIDTH = 190; @@ -334,10 +336,15 @@ private void draw(final Operator operator, final Graphics2D g2, final ProcessRen return; } Rectangle2D frame = rendererModel.getOperatorRect(operator); - int xOffset = (IMAGE_ANNOTATION.getIconWidth() + 2) * 2; - ProcessDrawUtils.getIcon(operator, IMAGE_ANNOTATION).paintIcon(null, g2, - (int) (frame.getX() + frame.getWidth() - xOffset), - (int) (frame.getY() + frame.getHeight() - IMAGE_ANNOTATION.getIconHeight() - 1)); + int iconSize = 16; + int xOffset = (iconSize + 2) * 2; + int iconX = (int) (frame.getX() + frame.getWidth() - xOffset); + int iconY = (int) (frame.getY() + frame.getHeight() - iconSize - 1); + ImageIcon icon = ProcessDrawUtils.getIcon(operator, rendererModel.getZoomFactor() <= 1d ? IMAGE_ANNOTATION : IMAGE_ANNOTATION_ZOOMED); + RenderingHints originalRenderingHints = g2.getRenderingHints(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.drawImage(icon.getImage(), iconX, iconY, iconSize, iconSize, null); + g2.setRenderingHints(originalRenderingHints); } }; diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/background/ProcessBackgroundImageDecorator.java b/src/main/java/com/rapidminer/gui/flow/processrendering/background/ProcessBackgroundImageDecorator.java index f650a14f0..60006d7d1 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/background/ProcessBackgroundImageDecorator.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/background/ProcessBackgroundImageDecorator.java @@ -80,11 +80,13 @@ private void draw(final ExecutionUnit process, final Graphics2D g2, final Proces // center image now if desired if (x == -1) { - double processWidth = rendererModel.getProcessWidth(process); + double zoomFactor = rendererModel.getZoomFactor(); + double processWidth = zoomFactor > 1.0 ? rendererModel.getProcessWidth(process) / zoomFactor : rendererModel.getProcessWidth(process); x = (int) ((processWidth - w) / 2); } if (y == -1) { - double processHeight = rendererModel.getProcessHeight(process); + double zoomFactor = rendererModel.getZoomFactor(); + double processHeight = zoomFactor > 1.0 ? rendererModel.getProcessHeight(process) / zoomFactor : rendererModel.getProcessHeight(process); y = (int) ((processHeight - h) / 2); } diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawUtils.java b/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawUtils.java index 45d9dc8d1..d5ca2bfa1 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawUtils.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawUtils.java @@ -108,7 +108,7 @@ private ProcessDrawUtils() { * the extension for the registered group color */ public static void registerAdditionalGroupColors(final String groupProperties, final String pluginName, - final ClassLoader classLoader, final Plugin provider) { + final ClassLoader classLoader, final Plugin provider) { SwingTools.registerAdditionalGroupColors(groupProperties, pluginName, classLoader, provider); } @@ -125,7 +125,7 @@ public static void registerAdditionalGroupColors(final String groupProperties, f * the extension to registered IOObjects for */ public static void registerAdditionalObjectColors(final String groupProperties, final String pluginName, - final ClassLoader classLoader, final Plugin provider) { + final ClassLoader classLoader, final Plugin provider) { try { IO_CLASS_TO_COLOR_MAP.parseProperties(groupProperties, "io.", ".color", classLoader, provider); } catch (IOException e) { diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawer.java b/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawer.java index 5a2011d65..80fd42bd3 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawer.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/draw/ProcessDrawer.java @@ -864,7 +864,7 @@ private void renderOperator(final Operator operator, final Graphics2D g2) { } else { errorIcon = isBlacklisted ? IMAGE_BLACKLISTED_ZOOMED : IMAGE_WARNING_ZOOMED; } - if (!operator.getErrorList().isEmpty() || isBlacklisted) { + if ((!operator.getErrorList().isEmpty() && !operator.isRunning()) || isBlacklisted) { int iconY = (int) (frame.getY() + frame.getHeight() - iconSize - 2); ImageIcon icon = ProcessDrawUtils.getIcon(operator, errorIcon); RenderingHints originalRenderingHints = g2.getRenderingHints(); diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererController.java b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererController.java index 606c14f25..573cef952 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererController.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererController.java @@ -856,6 +856,7 @@ void insertIntoHoveringConnection(final Operator operator) { if (bestOutput != null) { connect(bestOutput, oldDest); } + model.fireOperatorsMoved(Collections.singleton(operator)); } } finally { oldDest.unlock(); diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererTransferHandler.java b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererTransferHandler.java index 2a75a792b..a75d511c8 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererTransferHandler.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererTransferHandler.java @@ -251,6 +251,8 @@ public boolean dropNow(final List newOperators, Point loc) { first = false; } dropInsertionPredecessor = null; + + model.fireOperatorsMoved(newOperators); return true; } else { dropInsertionPredecessor = null; diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererView.java b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererView.java index 6d54fe7dc..5958f8371 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererView.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/view/ProcessRendererView.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.flow.processrendering.view; import java.awt.Component; @@ -39,12 +39,18 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Collection; +import java.util.Collections; import java.util.EnumMap; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JMenu; @@ -92,6 +98,7 @@ import com.rapidminer.gui.flow.processrendering.view.actions.RenameAction; import com.rapidminer.gui.flow.processrendering.view.actions.SelectAllAction; import com.rapidminer.gui.flow.processrendering.view.components.ProcessRendererTooltipProvider; +import com.rapidminer.gui.processeditor.OperatorPortActionRegistry; import com.rapidminer.gui.properties.celleditors.value.PropertyValueCellEditor; import com.rapidminer.gui.tools.PrintingTools; import com.rapidminer.gui.tools.ResourceAction; @@ -108,6 +115,7 @@ import com.rapidminer.operator.OperatorChain; import com.rapidminer.operator.ProcessRootOperator; import com.rapidminer.operator.ResultObject; +import com.rapidminer.operator.ports.DeliveringPortManager; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.OutputPort; import com.rapidminer.operator.ports.Port; @@ -520,8 +528,8 @@ public void keyPressed(final KeyEvent e) { // process render phases that come before the OPERATORS phase, abort in case the // event was consumed - for (RenderPhase phase : new RenderPhase[] { RenderPhase.FOREGROUND, RenderPhase.OVERLAY, - RenderPhase.OPERATOR_ADDITIONS }) { + for (RenderPhase phase : new RenderPhase[]{RenderPhase.FOREGROUND, RenderPhase.OVERLAY, + RenderPhase.OPERATOR_ADDITIONS}) { wasConsumed |= processPhaseListenerKeyEvent(KeyEventType.KEY_PRESSED, e, phase); if (wasConsumed) { return; @@ -540,8 +548,8 @@ public void keyPressed(final KeyEvent e) { } // remaining render phases, abort in case the event was consumed - for (RenderPhase phase : new RenderPhase[] { RenderPhase.CONNECTIONS, RenderPhase.OPERATOR_BACKGROUND, - RenderPhase.OPERATOR_ANNOTATIONS, RenderPhase.ANNOTATIONS, RenderPhase.BACKGROUND }) { + for (RenderPhase phase : new RenderPhase[]{RenderPhase.CONNECTIONS, RenderPhase.OPERATOR_BACKGROUND, + RenderPhase.OPERATOR_ANNOTATIONS, RenderPhase.ANNOTATIONS, RenderPhase.BACKGROUND}) { wasConsumed |= processPhaseListenerKeyEvent(KeyEventType.KEY_PRESSED, e, phase); if (wasConsumed) { return; @@ -711,7 +719,7 @@ public void dragEnded() { private final RepaintFilter repaintFilter; public ProcessRendererView(final ProcessRendererModel model, final ProcessPanel processPanel, - final MainFrame mainFrame) { + final MainFrame mainFrame) { this.mainFrame = mainFrame; this.model = model; this.controller = new ProcessRendererController(this, model); @@ -779,8 +787,7 @@ public void operatorsChanged(ProcessRendererOperatorEvent e, Collection opsToMove = new LinkedHashSet<>(operators); + boolean wasResized = false; + while (!opsToMove.isEmpty()) { + Iterator iterator = opsToMove.iterator(); + Operator op = iterator.next(); + iterator.remove(); + ExecutionUnit executionUnit = op.getExecutionUnit(); + List leftConnectedOperators = getDirectlyConnectedPorts(op.getInputPorts(), InputPort::getSource, executionUnit, Collections.emptyList()); + List rightConnectedOperators = getDirectlyConnectedPorts(op.getOutputPorts(), OutputPort::getDestination, executionUnit, opsToMove); + + final Rectangle2D operatorRect = model.getOperatorRect(op); + // check it does not collide with other operators and move it to the right if necessary + leftConnectedOperators.stream().map(model::getOperatorRect).filter(r -> r != null && Math.abs(r.getY() - operatorRect.getY()) < 10) + .mapToDouble(r -> r.getX() + ProcessDrawer.GRID_AUTOARRANGE_WIDTH - 1).filter(x -> operatorRect.getX() < x).forEach(x -> { + operatorRect.setRect(x, operatorRect.getY(), operatorRect.getWidth(), operatorRect.getHeight()); + model.setOperatorRect(op, operatorRect); + }); + // check all connected operators to the right also + opsToMove.addAll(rightConnectedOperators); + + wasResized |= controller.ensureProcessSizeFits(executionUnit, model.getOperatorRect(op)); // notify registered listeners fireOperatorMoved(op); } + // need to repaint if process was not resized + if (!wasResized) { + repaint(); + } break; case PORTS_CHANGED: for (Operator op : operators) { @@ -815,6 +840,13 @@ public void operatorsChanged(ProcessRendererOperatorEvent e, Collection List getDirectlyConnectedPorts(Ports

ports, Function opposite, ExecutionUnit executionUnit, Collection exclude) { + // get all connected ports, find their operator, make sure it is an operator on the same process level and is not already moved + return ports.getAllPorts().stream().filter(Port::isConnected).map(port -> opposite.apply(port).getPorts().getOwner().getOperator()) + .filter(co -> executionUnit == co.getExecutionUnit() && !exclude.contains(co)).distinct().collect(Collectors.toList()); + } + @Override public void annotationsChanged(ProcessRendererAnnotationEvent e, Collection annotations) { switch (e.getEventType()) { @@ -1449,7 +1481,9 @@ boolean showPopupMenu(final MouseEvent e) { @Override public void loggedActionPerformed(final ActionEvent e) { - data.setSource(hoveringPort.getPorts().getOwner().getOperator().getName()); + final Operator operator = hoveringPort.getPorts().getOwner().getOperator(); + data.setSource(operator.getName()); + DeliveringPortManager.setLastDeliveringPort(data, hoveringPort); mainFrame.getResultDisplay().showResult((ResultObject) data); } @@ -1464,6 +1498,15 @@ public void loggedActionPerformed(final ActionEvent e) { } menu.addSeparator(); } + + final List portActions = OperatorPortActionRegistry.INSTANCE.getPortActions(hoveringPort); + for (ResourceAction action : portActions) { + menu.add(action); + } + if (!portActions.isEmpty()) { + menu.addSeparator(); + } + List fixes = hoveringPort.collectQuickFixes(); if (!fixes.isEmpty()) { JMenu fixMenu = new ResourceMenu("quick_fixes"); @@ -1608,9 +1651,9 @@ public void loggedActionPerformed(final ActionEvent ae) { @Override public void loggedActionPerformed(final ActionEvent e) { data.setSource(hoveredOp.getName()); + DeliveringPortManager.setLastDeliveringPort(data, port); mainFrame.getResultDisplay().showResult((ResultObject) data); } - }); menu.add(showResult); } diff --git a/src/main/java/com/rapidminer/gui/flow/processrendering/view/components/OperatorWarningHandler.java b/src/main/java/com/rapidminer/gui/flow/processrendering/view/components/OperatorWarningHandler.java index 32acef1f6..75fbaaa3a 100644 --- a/src/main/java/com/rapidminer/gui/flow/processrendering/view/components/OperatorWarningHandler.java +++ b/src/main/java/com/rapidminer/gui/flow/processrendering/view/components/OperatorWarningHandler.java @@ -87,7 +87,7 @@ public void processMouseEvent(ExecutionUnit process, MouseEventType type, MouseE Operator operator = model.getHoveringOperator(); // check if there is a warning icon for this operator - if (operator != null && !operator.getErrorList().isEmpty()) { + if (operator != null && !operator.getErrorList().isEmpty() && !operator.isRunning()) { // calculate the bounding box of the warning icon as it is drawn by {@link Rectangle2D frame = model.getOperatorRect(operator); diff --git a/src/main/java/com/rapidminer/gui/look/fc/FileList.java b/src/main/java/com/rapidminer/gui/look/fc/FileList.java index 56d84ab39..7db7f891a 100644 --- a/src/main/java/com/rapidminer/gui/look/fc/FileList.java +++ b/src/main/java/com/rapidminer/gui/look/fc/FileList.java @@ -1042,7 +1042,10 @@ protected void updateTableData() { updateTablePanelSize(); for (Item item : selectedFilesVector) { - this.tablePanel.updateSelectionInterval(this.visibleItemsList.indexOf(item), true); + int index = this.visibleItemsList.indexOf(item); + if (index >= 0) { + this.tablePanel.updateSelectionInterval(index, true); + } } } diff --git a/src/main/java/com/rapidminer/gui/operatortree/actions/ToggleActivationItem.java b/src/main/java/com/rapidminer/gui/operatortree/actions/ToggleActivationItem.java index 917733064..fcb1534fe 100644 --- a/src/main/java/com/rapidminer/gui/operatortree/actions/ToggleActivationItem.java +++ b/src/main/java/com/rapidminer/gui/operatortree/actions/ToggleActivationItem.java @@ -63,12 +63,13 @@ public void actionToggled(ActionEvent e) { op.setEnabled(targetState); } if (!targetState) { - if(!"false".equals(ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_DISCONNECT_ON_DISABLE))) { + final String disableBehavior = ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR); + if ("bridged".equals(disableBehavior)) { for (Operator op : actions.getSelectedOperators()) { ActionUtil.doPassthroughPorts(op); } - } else { - for(Operator op : actions.getSelectedOperators()) { + } else if ("removed".equals(disableBehavior)) { + for (Operator op : actions.getSelectedOperators()) { op.getInputPorts().disconnectAll(); op.getOutputPorts().disconnectAll(); } diff --git a/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionProducer.java b/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionProducer.java new file mode 100644 index 000000000..a37ba31b1 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionProducer.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2001-2018 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.processeditor; + +import com.rapidminer.gui.tools.ResourceAction; +import com.rapidminer.operator.IOObject; +import com.rapidminer.operator.ports.Port; + + +/** + * Adding a new entry to Operator Port context menus is as simple as implementing an anonymous instance of this interface + * and adding it to the {@link OperatorPortActionRegistry}. + * + * @author Andreas Timm + * @since 9.1 + */ +public interface OperatorPortActionProducer { + + /** + * This is a first check to see if the implementation does accept these kind of {@link IOObject} as its input. + * + * @param ioobject + * from the {@link Port} that was accessed + * @return {@code true} if this producer wants to add actions for the {@link IOObject} type. + */ + public boolean accepts(Class ioobject); + + /** + * Will only be called if the accepts method returned true. Here is the place to insert the creation of a {@link ResourceAction} + * that will be added to a context menu of the right-clicked {@link Port} + * + * @param port + * the port that was right-clicked + * @return a {@link ResourceAction} or null + */ + public ResourceAction createAction(Port port); +} diff --git a/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionRegistry.java b/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionRegistry.java new file mode 100644 index 000000000..7e8081c97 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/processeditor/OperatorPortActionRegistry.java @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2001-2018 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.processeditor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.rapidminer.gui.tools.ResourceAction; +import com.rapidminer.operator.IOObject; +import com.rapidminer.operator.ports.Port; + + +/** + * The {@link OperatorPortActionRegistry} provides a hook to add {@link ResourceAction}s to {@link Port}s from {@link com.rapidminer.operator.Operator}s. + * Based on the type and the available {@link IOObject} of the {@link Port} the {@link OperatorPortActionProducer} can + * decide to provide a new {@link ResourceAction} to be added to the context menu of the hovered and right-clicked port. + * + * @author Andreas Timm + * @since 9.1 + */ +public enum OperatorPortActionRegistry { + /** + * The instance + */ + INSTANCE; + + /** + * Map containing registered {@link OperatorPortActionProducer}s for a {@link Port} class + */ + private Map, List> porttypeActions = new HashMap<>(); + + /** + * Add an {@link OperatorPortActionProducer} to these {@link Port} class instances and its specializations. + * + * @param clazz + * the {@link Port} class the producer is registered for + * @param producer + * the {@link ResourceAction} producing instance + */ + public void addPortAction(Class clazz, OperatorPortActionProducer producer) { + if (clazz == null) { + throw new IllegalArgumentException("'clazz' must not be null"); + } + if (producer == null) { + throw new IllegalArgumentException("'producer' must not be null"); + } + porttypeActions.computeIfAbsent(clazz, f -> new ArrayList<>()).add(producer); + } + + /** + * Remove an {@link OperatorPortActionProducer} from the registry. + * + * @param clazz + * {@link Port} class the producer was registered for + * @param producer + * the {@link ResourceAction} producing instance + * @return true if the removal did remove an entry from the registry + */ + public boolean removePortAction(Class clazz, OperatorPortActionProducer producer) { + if (porttypeActions.containsKey(clazz)) { + final List resourceActions = porttypeActions.get(clazz); + return resourceActions.remove(producer); + } + return false; + } + + /** + * Get the {@link ResourceAction}s for the given {@link Port}. Check if the registered {@link OperatorPortActionProducer} + * accept the data type provided from getAnyDataOrNull and add it to the result. + * + * @param port + * the port that is being checked for further entries. + * @return the additional ResourceActions in alphabetic order + */ + public List getPortActions(Port port) { + if (port == null || port.getAnyDataOrNull() == null) { + return Collections.emptyList(); + } + + final Class ioobjectClass = port.getAnyDataOrNull().getClass(); + List result = new ArrayList<>(); + for (Map.Entry, List> entry : porttypeActions.entrySet()) { + if (!entry.getKey().isAssignableFrom(port.getClass())) { + continue; + } + final List operatorPortActionProducers = entry.getValue(); + if (operatorPortActionProducers == null) { + continue; + } + operatorPortActionProducers.stream().filter(portAction -> portAction.accepts(ioobjectClass)) + .map(portAction -> portAction.createAction(port)).filter(Objects::nonNull).forEach(result::add); + } + return result; + } + +} diff --git a/src/main/java/com/rapidminer/gui/processeditor/XMLEditor.java b/src/main/java/com/rapidminer/gui/processeditor/XMLEditor.java index 6598c7a98..b34e7fd44 100644 --- a/src/main/java/com/rapidminer/gui/processeditor/XMLEditor.java +++ b/src/main/java/com/rapidminer/gui/processeditor/XMLEditor.java @@ -121,7 +121,7 @@ public void setText(String text) { @Override public void processUpdated(Process process) { - setText(process.getRootOperator().getXML(true)); + setText(process.getRootOperator().getXML(false)); } @Override @@ -155,14 +155,14 @@ public void setSelection(List selection) { public synchronized void validateProcess() throws IOException, XMLException { String editorContent = getXMLFromEditor(); Process oldProcess = RapidMinerGUI.getMainFrame().getProcess(); - String oldXML = oldProcess.getRootOperator().getXML(true); + String oldXML = oldProcess.getRootOperator().getXML(false); if (oldXML.trim().equals(editorContent)) { return; } Process newProcess = new Process(editorContent); ProcessRendererView processRenderer = mainFrame.getProcessPanel().getProcessRenderer(); ProcessDrawUtils.ensureOperatorsHaveLocation(newProcess, processRenderer.getModel()); - String newXML = newProcess.getRootOperator().getXML(true); + String newXML = newProcess.getRootOperator().getXML(false); if (!newXML.equals(oldXML)) { newProcess.setProcessLocation(oldProcess.getProcessLocation()); mainFrame.setProcess(newProcess, false); diff --git a/src/main/java/com/rapidminer/gui/processeditor/results/ResultActionGuiProvider.java b/src/main/java/com/rapidminer/gui/processeditor/results/ResultActionGuiProvider.java new file mode 100644 index 000000000..af460d8b5 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/processeditor/results/ResultActionGuiProvider.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2001-2018 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.processeditor.results; + +import java.util.function.Supplier; +import javax.swing.JComponent; + +import com.rapidminer.example.ExampleSet; + + +/** + * To be implemented to provide GUI components for the ResultTab action + * + * @author Andreas Timm + * @since 9.1 + */ +public interface ResultActionGuiProvider { + + /** + * Create a swing {@link JComponent} like a {@link javax.swing.AbstractButton} that executes further actions based on the given exampleSet. + * + * @param exampleSetSupplier + * the exampleSetSupplier to get() the potentially filtered {@link ExampleSet} from when executing this action + * @return an individual JComponent for user interaction + */ + JComponent createComponent(Supplier exampleSetSupplier); +} diff --git a/src/main/java/com/rapidminer/gui/processeditor/results/ResultDisplayTools.java b/src/main/java/com/rapidminer/gui/processeditor/results/ResultDisplayTools.java index c89911f92..134b54f5e 100644 --- a/src/main/java/com/rapidminer/gui/processeditor/results/ResultDisplayTools.java +++ b/src/main/java/com/rapidminer/gui/processeditor/results/ResultDisplayTools.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.processeditor.results; import java.awt.BorderLayout; @@ -27,7 +27,6 @@ import java.util.List; import java.util.Set; import java.util.logging.Level; - import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; @@ -84,15 +83,15 @@ public class ResultDisplayTools { /** * In these cases the unnecessary additional panel is suppressed */ - private static final Set NO_CARD_KEYS = new HashSet<>(Arrays.asList(new String[] { "collection", "metamodel", - "delegation_model" })); + private static final Set NO_CARD_KEYS = new HashSet<>(Arrays.asList(new String[]{"collection", "metamodel", + "delegation_model"})); static { defaultResultIcon = SwingTools.createIcon("16/" + DEFAULT_RESULT_ICON_NAME); } public static JPanel createVisualizationComponent(IOObject resultObject, IOContainer resultContainer, - String usedResultName) { + String usedResultName) { return createVisualizationComponent(resultObject, resultContainer, usedResultName, true); } @@ -116,7 +115,7 @@ public static JPanel createErrorComponent(String error) { * will not be shown */ public static JPanel createVisualizationComponent(IOObject result, final IOContainer resultContainer, - String usedResultName, final boolean showCards) { + String usedResultName, final boolean showCards) { result = TableViewingTools.replaceTable(result); final String resultName = RendererService.getName(result.getClass()); ButtonBarCardPanel visualisationComponent; @@ -180,28 +179,23 @@ public void run() { } getProgressListener().setCompleted(80); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - // update container - // renderer is finished, remove placeholder - inConstructionPanel.removeAll(); - - // add license information if necessary - if (!violationList.isEmpty()) { - JPanel warnPanel = new ResultLimitPanel(rendererComponent.getBackground(), - violationList.get(0)); - inConstructionPanel.add(warnPanel, BorderLayout.NORTH); - } + SwingUtilities.invokeLater(() -> { + // update container + // renderer is finished, remove placeholder + inConstructionPanel.removeAll(); - // add real renderer - inConstructionPanel.add(rendererComponent, BorderLayout.CENTER); - - inConstructionPanel.revalidate(); - inConstructionPanel.repaint(); + // add license information if necessary + if (!violationList.isEmpty()) { + JPanel warnPanel = new ResultLimitPanel(rendererComponent.getBackground(), + violationList.get(0)); + inConstructionPanel.add(warnPanel, BorderLayout.NORTH); } + // add real renderer + inConstructionPanel.add(rendererComponent, BorderLayout.CENTER); + + inConstructionPanel.revalidate(); + inConstructionPanel.repaint(); }); getProgressListener().complete(); } diff --git a/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionRegistry.java b/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionRegistry.java new file mode 100644 index 000000000..c97a19d6e --- /dev/null +++ b/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionRegistry.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2001-2018 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.processeditor.results; + +import java.security.AccessControlException; +import java.security.AccessController; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; + +import com.rapidminer.gui.tools.ResourceAction; +import com.rapidminer.security.PluginSandboxPolicy; +import com.rapidminer.tools.LogService; + + +/** + * The {@link ResultTabActionRegistry} provides a hook to add {@link ResourceAction}s to {@link ResultTab}s + * + * @author Andreas Timm + * @since 9.1 + */ +public enum ResultTabActionRegistry { + /** + * The instance + */ + INSTANCE; + + private static final int MAX_ENTRY_COUNT = 3; + /** + * All available actions + */ + private List resultActions = new ArrayList<>(); + + /** + * Add a {@link ResultActionGuiProvider} action to the ResultTab data view. + * + *

+ * Internal usage only! + *

+ * + * @param actionGuiProvider + * that creates a GUI JComponent for a later available ExampleSet + */ + public void addAction(ResultActionGuiProvider actionGuiProvider) { + if (actionGuiProvider == null) { + throw new IllegalArgumentException("actionGuiProvider must not be null"); + } + if (resultActions.size() >= MAX_ENTRY_COUNT) { + LogService.getRoot().log(Level.WARNING, "Adding more than {0} ResultTabActions is not supported.", MAX_ENTRY_COUNT); + return; + } + try { + // only signed extensions are allowed to register actions + if (System.getSecurityManager() != null) { + AccessController.checkPermission(new RuntimePermission(PluginSandboxPolicy.RAPIDMINER_INTERNAL_PERMISSION)); + } + } catch (AccessControlException e) { + return; + } + resultActions.add(actionGuiProvider); + } + + /** + * Remove a registered action from the ResultTab. + * + *

+ * Internal usage only! + *

+ * + * @param actionGuiProvider + * the previously registered {@link ResultActionGuiProvider} + * @return {@code true} if the provider was removed + */ + public boolean removeAction(ResultActionGuiProvider actionGuiProvider) { + try { + // only signed extensions are allowed to register actions + if (System.getSecurityManager() != null) { + AccessController.checkPermission(new RuntimePermission(PluginSandboxPolicy.RAPIDMINER_INTERNAL_PERMISSION)); + } + } catch (AccessControlException e) { + return false; + } + return resultActions.remove(actionGuiProvider); + } + + /** + * Get all available actions for the ResultTab + * + * @return List of {@link ResultActionGuiProvider}s + */ + public List getActions() { + return Collections.unmodifiableList(resultActions); + } +} diff --git a/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionVisualizer.java b/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionVisualizer.java new file mode 100644 index 000000000..f8fc2ed16 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/processeditor/results/ResultTabActionVisualizer.java @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2001-2018 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.processeditor.results; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.List; +import java.util.function.Supplier; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; + +import com.rapidminer.example.ExampleSet; + + +/** + * Helper class to to create swing components visualizing the {@link ResultActionGuiProvider}s. + * + * @author Andreas Timm + * @since 9.1 + */ +public final class ResultTabActionVisualizer { + + /** + * Maximum size for every component. + */ + private static final int MAX_COMPONENT_WIDTH = 250; + private static final int MAX_COMPONENT_HEIGHT = 50; + + /** + * Util class, construction not supported + */ + private ResultTabActionVisualizer() { + throw new UnsupportedOperationException("Do not instantiate thee"); + } + + /** + * Creates a swing component that either consists of the only available option or shows a popup list of possible actions. + * + * @param exampleSetSupplier + * the current exampleSetSupplier that should be used fur further actions + * @return a Button or a PopupMenu + */ + public static JComponent createResultActionsComponent(Supplier exampleSetSupplier) { + final List actions = ResultTabActionRegistry.INSTANCE.getActions(); + if (actions.isEmpty()) { + return null; + } + + final JPanel actionsPanel = new JPanel(); + actionsPanel.setLayout(new GridBagLayout()); + actionsPanel.setOpaque(false); + + actionsPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 0)); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + + for (ResultActionGuiProvider action : actions) { + final JComponent component = action.createComponent(exampleSetSupplier); + final Dimension preferredSize = component.getPreferredSize(); + if (preferredSize.getWidth() > MAX_COMPONENT_WIDTH || preferredSize.getHeight() > MAX_COMPONENT_HEIGHT) { + preferredSize.setSize(Math.min(preferredSize.width, MAX_COMPONENT_WIDTH), Math.min(preferredSize.height, MAX_COMPONENT_HEIGHT)); + } + actionsPanel.add(component, gbc); + gbc.gridx++; + } + return actionsPanel; + } +} diff --git a/src/main/java/com/rapidminer/gui/processeditor/search/OperatorGlobalSearchManager.java b/src/main/java/com/rapidminer/gui/processeditor/search/OperatorGlobalSearchManager.java index c79f24299..79cc85774 100644 --- a/src/main/java/com/rapidminer/gui/processeditor/search/OperatorGlobalSearchManager.java +++ b/src/main/java/com/rapidminer/gui/processeditor/search/OperatorGlobalSearchManager.java @@ -24,6 +24,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.logging.Level; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -46,6 +47,7 @@ import com.rapidminer.search.AbstractGlobalSearchManager; import com.rapidminer.search.GlobalSearchDefaultField; import com.rapidminer.search.GlobalSearchUtilities; +import com.rapidminer.tools.LogService; import com.rapidminer.tools.OperatorService; import com.rapidminer.tools.documentation.OperatorDocBundle; @@ -161,7 +163,7 @@ private Document createDocument(final OperatorDescription opDesc) { } catch (OperatorCreationException e) { // should not happen, if it does, ignore } - return GlobalSearchUtilities.INSTANCE.createDocument(opDesc.getKey(), opDesc.getName(), fields.toArray(new Field[fields.size()])); + return GlobalSearchUtilities.INSTANCE.createDocument(opDesc.getKey(), opDesc.getName(), fields.toArray(new Field[0])); } /** @@ -237,7 +239,13 @@ private void createOutputPortField(final List fields, final Operator op) sb.append(' '); // to prepare output MD, we need to trigger generation here - op.transformMetaData(); + try { + op.transformMetaData(); + } catch (Exception e) { + // some extensions may throw here, just ignore it and move on + LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.processeditor.global_search.OperatorSearchManager.error.output_metadata_transform_failed", + op.getOperatorDescription().getKey()); + } for (OutputPort outPort : outputPorts.getAllPorts()) { // we need to use the deprecated method because we don't want specific MD, but whatever MD is there MetaData resultMD = outPort.getMetaData(); diff --git a/src/main/java/com/rapidminer/gui/properties/AbstractSettingsItemProvider.java b/src/main/java/com/rapidminer/gui/properties/AbstractSettingsItemProvider.java new file mode 100644 index 000000000..762dd9012 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/properties/AbstractSettingsItemProvider.java @@ -0,0 +1,188 @@ +/** + * Copyright (C) 2001-2018 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.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.stream.Collectors; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; + +import com.rapidminer.gui.properties.SettingsItem.Type; +import com.rapidminer.tools.LogService; + + +/** + * Base implementation of a {@link SettingsItemProvider}. Extracted from {@link SettingsItems}. + * + * @author Adrian Wilke, Peter Hellinger, Jan Czogalla + * @since 9.1 + */ +public abstract class AbstractSettingsItemProvider implements SettingsItemProvider { + + /** Maps keys to SettingsItem objects */ + private Map itemMap = new LinkedHashMap<>(); + /** Was settings groups loaded successfully */ + private boolean isGroupingLoaded = false; + + @Override + public void clean() { + cleanEmptyCategory(Type.SUB_GROUP); + cleanEmptyCategory(Type.GROUP); + } + + @Override + public boolean containsKey(String key) { + return itemMap.containsKey(key); + } + + @Override + public SettingsItem get(String key) { + return itemMap.get(key); + } + + @Override + public List getItems(Type type) { + return itemMap.values().stream().filter(settingsItem -> settingsItem.getType() == type).collect(Collectors.toList()); + } + + @Override + public Collection getKeys() { + return new HashSet<>(itemMap.keySet()); + } + + @Override + public boolean loadGrouping() { + try { + itemMap = new SettingsXmlHandler().parse(getGroupDefinitions()); + isGroupingLoaded = true; + } catch (ParserConfigurationException | SAXException | IOException | URISyntaxException e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.AbstractSettingsItemProvider.parse_xml_error", + new String[]{ SettingsXmlHandler.SETTINGS_XML_FILE, e.getMessage()}); + isGroupingLoaded = false; + // Must not throw an exception, as the settings work without the structure inside XML. + } + return isGroupingLoaded; + } + + @Override + public void put(String key, SettingsItem item) { + if (key == null || key.isEmpty()) { + throw new IllegalArgumentException("Key not set"); + } + if (item == null) { + throw new IllegalArgumentException("No item for key " + key); + } + itemMap.put(key, item); + } + + @Override + public void remove(String key) { + remove(key, true, true); + } + + @Override + public void remove(String key, boolean removeFromSettingsItems, boolean removeFromHierarchy) { + if (!itemMap.containsKey(key)) { + throw new IllegalStateException("Could not remove settings item " + key + " as it is not known"); + } + + if (removeFromHierarchy) { + SettingsItem item = itemMap.get(key); + if (item.getChildren().isEmpty()) { + if (item.getParent() != null) { + item.getParent().getChildren().remove(item); + } + } else { + throw new IllegalStateException("Could not remove settings item " + key + " as it has children"); + } + } + + if (removeFromSettingsItems) { + itemMap.remove(key); + } + } + + @Override + public void removeParameterInverse(Collection keepKeys) { + Iterator> itemMapIterator = itemMap.entrySet().iterator(); + while (itemMapIterator.hasNext()) { + Entry itemMapEntry = itemMapIterator.next(); + String key = itemMapEntry.getKey(); + if (!keepKeys.contains(key)) { + SettingsItem item = itemMapEntry.getValue(); + if (item.getType().equals(Type.PARAMETER)) { + try { + remove(key, false, true); + itemMapIterator.remove(); + } catch (IllegalStateException e) { + LogService.getRoot().log(Level.WARNING, + "com.rapidminer.gui.properties.AbstractSettingsItemProvider.remove_item_error", e); + } + } + } + } + } + + @Override + public boolean isGroupingLoaded() { + return isGroupingLoaded; + } + + /** + * Specifies a {@link URI} to an XML file holding the settings. + * + * @since 9.1 + */ + protected abstract URI getGroupDefinitions() throws URISyntaxException; + + /** + * Cleans the given category. + * + * @param category the category to clean; one of {@link Type#SUB_GROUP} or Type#GROUP + * @since 9.1 + */ + private void cleanEmptyCategory(Type category) { + if (category == Type.PARAMETER) { + return; + } + for (SettingsItem item : getItems(category)) { + if (item.getChildren().isEmpty()) { + try { + remove(item.getKey()); + } catch (RuntimeException runtimeException) { + // This would be a failure in the settings structure and should not happen. + // The log is to notice an improbable occurrence. + LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.AbstractSettingsItemProvider.remove_item_error", + runtimeException); + } + } + } + } +} diff --git a/src/main/java/com/rapidminer/gui/properties/CompatibilityLevelSpinnerModel.java b/src/main/java/com/rapidminer/gui/properties/CompatibilityLevelSpinnerModel.java index e1bbadc73..180e7c623 100644 --- a/src/main/java/com/rapidminer/gui/properties/CompatibilityLevelSpinnerModel.java +++ b/src/main/java/com/rapidminer/gui/properties/CompatibilityLevelSpinnerModel.java @@ -32,14 +32,14 @@ /** * Displays the {@link OperatorVersion}s as returned by * {@link Operator#getIncompatibleVersionChanges()}. and {@link Operator#getCompatibilityLevel()} . - * + * * @author Simon Fischer - * + * */ public class CompatibilityLevelSpinnerModel extends AbstractSpinnerModel { /** - * + * */ private static final long serialVersionUID = 1L; private int index = 0; diff --git a/src/main/java/com/rapidminer/gui/properties/FilterPropertyDialog.java b/src/main/java/com/rapidminer/gui/properties/FilterPropertyDialog.java index 6a3bc2b4d..f411a7326 100644 --- a/src/main/java/com/rapidminer/gui/properties/FilterPropertyDialog.java +++ b/src/main/java/com/rapidminer/gui/properties/FilterPropertyDialog.java @@ -37,6 +37,7 @@ import javax.swing.JRadioButton; import javax.swing.border.EtchedBorder; +import com.rapidminer.gui.ApplicationFrame; import com.rapidminer.gui.properties.tablepanel.TablePanel; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceActionAdapter; @@ -200,7 +201,7 @@ public void loggedActionPerformed(final ActionEvent e) { buttonPanel.add(cancelButton, gbc); panel.add(innerPanel, BorderLayout.CENTER); - setLocationRelativeTo(null); + setLocationRelativeTo(ApplicationFrame.getApplicationFrame()); setDefaultSize(ButtonDialog.LARGE); layoutDefault(panel, buttonPanel); } diff --git a/src/main/java/com/rapidminer/gui/properties/GenericParameterPanel.java b/src/main/java/com/rapidminer/gui/properties/GenericParameterPanel.java index fc4755b87..9a3e0d0b8 100644 --- a/src/main/java/com/rapidminer/gui/properties/GenericParameterPanel.java +++ b/src/main/java/com/rapidminer/gui/properties/GenericParameterPanel.java @@ -24,8 +24,10 @@ import com.rapidminer.parameter.UndefinedParameterError; import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; /** @@ -57,15 +59,10 @@ protected Operator getOperator() { @Override protected Collection getProperties() { - List visible = new LinkedList(); - if (parameters != null) { - for (ParameterType type : parameters.getParameterTypes()) { - if (!type.isHidden()) { - visible.add(type); - } - } + if (parameters == null) { + return Collections.emptyList(); } - return visible; + return parameters.getParameterTypes().stream().filter(pt -> !pt.isHidden()).collect(Collectors.toList()); } @Override diff --git a/src/main/java/com/rapidminer/gui/properties/OperatorPropertyPanel.java b/src/main/java/com/rapidminer/gui/properties/OperatorPropertyPanel.java index 91738c7ec..7576c9fa8 100644 --- a/src/main/java/com/rapidminer/gui/properties/OperatorPropertyPanel.java +++ b/src/main/java/com/rapidminer/gui/properties/OperatorPropertyPanel.java @@ -28,6 +28,7 @@ import java.io.InputStream; import java.io.StringReader; import java.net.URL; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; @@ -36,7 +37,7 @@ import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - +import java.util.stream.Collectors; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.Icon; @@ -47,8 +48,6 @@ import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.border.Border; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; @@ -80,7 +79,6 @@ import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.Parameters; import com.rapidminer.tools.I18N; -import com.rapidminer.tools.Observable; import com.rapidminer.tools.Observer; import com.rapidminer.tools.PlatformUtilities; import com.vlsolutions.swing.docking.DockKey; @@ -153,29 +151,26 @@ public class OperatorPropertyPanel extends PropertyPanel implements Dockable, Pr private Operator operator; - private final Observer parameterObserver = new Observer() { - - @Override - public void update(Observable observable, String key) { - PropertyValueCellEditor editor = getEditorForKey(key); - if (editor != null) { - Object editorValueObject = editor.getCellEditorValue(); - ParameterType type = operator.getParameters().getParameterType(key); - String editorValue = type.toString(editorValueObject); - String opValue = operator.getParameters().getParameterOrNull(key); - // Second check prevents an endless validation loop in case opValue and editorValueObject are both null - if (!Objects.equals(opValue, editorValue) && opValue != editorValueObject) { - editor.getTableCellEditorComponent(null, opValue, false, 0, 1); - } - } else { - setupComponents(); - } + private final transient Observer parameterObserver = (observable, key) -> { + PropertyValueCellEditor editor = getEditorForKey(key); + if (editor == null) { + setupComponents(); + return; + } + Object editorValueObject = editor.getCellEditorValue(); + ParameterType type = operator.getParameters().getParameterType(key); + String editorValue = type.toString(editorValueObject); + String opValue = operator.getParameters().getParameterOrNull(key); + // Second check prevents an endless validation loop in case opValue and editorValueObject are both null + if (!Objects.equals(opValue, editorValue) && opValue != editorValueObject) { + editor.getTableCellEditorComponent(null, opValue, false, 0, 1); } }; final transient ToggleAction TOGGLE_EXPERT_MODE_ACTION = new ToggleExpertModeAction(); - private final JSpinner compatibilityLevelSpinner = new JSpinner(new CompatibilityLevelSpinnerModel()); + private final CompatibilityLevelSpinnerModel compatibilityLevelSpinnerModel = new CompatibilityLevelSpinnerModel(); + private final JSpinner compatibilityLevelSpinner = new JSpinner(compatibilityLevelSpinnerModel); private final ResourceLabel compatibilityLabel = new ResourceLabel("compatibility_level"); private final JPanel compatibilityPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); @@ -205,22 +200,18 @@ public void loggedActionPerformed(ActionEvent e) { setupComponents(); - compatibilityLevelSpinner.addChangeListener(new ChangeListener() { + compatibilityLevelSpinner.addChangeListener(e -> { + // compatibility level + OperatorVersion[] versionChanges = operator.getIncompatibleVersionChanges(); - @Override - public void stateChanged(ChangeEvent e) { - // compatibility level - OperatorVersion[] versionChanges = operator.getIncompatibleVersionChanges(); - - // sort to have an ascending order - Arrays.sort(versionChanges); - if (versionChanges.length > 0) { - OperatorVersion latestChange = versionChanges[versionChanges.length - 1]; - if (latestChange.isAtLeast(operator.getCompatibilityLevel())) { - compatibilityLabel.setIcon(WARNING_ICON); - } else { - compatibilityLabel.setIcon(OK_ICON); - } + // sort to have an ascending order + Arrays.sort(versionChanges); + if (versionChanges.length > 0) { + OperatorVersion latestChange = versionChanges[versionChanges.length - 1]; + if (latestChange.isAtLeast(operator.getCompatibilityLevel())) { + compatibilityLabel.setIcon(WARNING_ICON); + } else { + compatibilityLabel.setIcon(OK_ICON); } } }); @@ -275,14 +266,7 @@ public void setSelection(List selection) { if (operator != null) { this.operator.getParameters().addObserver(parameterObserver, true); if (isShowParameterHelp()) { - PARAMETER_UPDATE_SERVICE.execute(new Runnable() { - - @Override - public void run() { - parseParameterDescriptions(operator); - } - - }); + PARAMETER_UPDATE_SERVICE.execute(() -> parseParameterDescriptions(operator)); } // compatibility level @@ -291,7 +275,7 @@ public void run() { // no incompatible versions exist changeCompatibility.setVisible(false); } else { - ((CompatibilityLevelSpinnerModel) compatibilityLevelSpinner.getModel()).setOperator(operator); + compatibilityLevelSpinnerModel.setOperator(operator); changeCompatibility.setAction(createCompatibilityAction(operator.getCompatibilityLevel().getLongVersion())); changeCompatibility.setVisible(true); } @@ -310,15 +294,11 @@ public Component getComponent() { final JScrollPane scrollPane = new ExtendedJScrollPane(this); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.getViewport().addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent e) { - if (scrollPane.getVerticalScrollBar().isVisible()) { - scrollPane.setBorder(BOTH_BORDERS); - } else { - scrollPane.setBorder(TOP_BORDER); - } + scrollPane.getViewport().addChangeListener(e -> { + if (scrollPane.getVerticalScrollBar().isVisible()) { + scrollPane.setBorder(BOTH_BORDERS); + } else { + scrollPane.setBorder(TOP_BORDER); } }); @@ -404,39 +384,24 @@ protected void setValue(Operator operator, ParameterType type, String value) { @Override protected List getProperties() { - List visible = new LinkedList(); - int hidden = 0; + List visible = new ArrayList<>(); + boolean isExpertMode = isExpertMode(); int advancedCount = 0; if (operator != null) { - for (ParameterType type : operator.getParameters().getParameterTypes()) { - if (type.isHidden()) { - continue; - } - if (type.isExpert()) { - advancedCount++; - if (!isExpertMode()) { - hidden++; - continue; - } - } - visible.add(type); - } - } - - if (hidden > 0) { - hideAdvancedParameters.setVisible(false); - showAdvancedParameters.setVisible(true); - showAdvancedParameters.setToolTipText(I18N.getGUIMessage("gui.action.parameters.show_advanced.tip", hidden)); - } else { - showAdvancedParameters.setVisible(false); - if (advancedCount > 0) { - hideAdvancedParameters.setVisible(true); - hideAdvancedParameters.setToolTipText(I18N.getGUIMessage("gui.action.parameters.hide_advanced.tip", - advancedCount)); + List nonHidden = operator.getParameters().getParameterTypes().stream().filter(parameterType -> !parameterType.isHidden()).collect(Collectors.toList()); + List nonExpert = nonHidden.stream().filter(pt -> !pt.isExpert()).collect(Collectors.toList()); + advancedCount = nonHidden.size() - nonExpert.size(); + if (isExpertMode) { + visible = nonHidden; } else { - hideAdvancedParameters.setVisible(false); + visible = nonExpert; } } + + hideAdvancedParameters.setVisible(isExpertMode && advancedCount > 0); + hideAdvancedParameters.setToolTipText(I18N.getGUIMessage("gui.action.parameters.hide_advanced.tip", advancedCount)); + showAdvancedParameters.setVisible(!isExpertMode); + showAdvancedParameters.setToolTipText(I18N.getGUIMessage("gui.action.parameters.show_advanced.tip", advancedCount)); return visible; } diff --git a/src/main/java/com/rapidminer/gui/properties/PropertyPanel.java b/src/main/java/com/rapidminer/gui/properties/PropertyPanel.java index bdf4b2a65..2df5af2c2 100644 --- a/src/main/java/com/rapidminer/gui/properties/PropertyPanel.java +++ b/src/main/java/com/rapidminer/gui/properties/PropertyPanel.java @@ -44,6 +44,7 @@ import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.border.Border; import javax.swing.event.CellEditorListener; @@ -80,6 +81,7 @@ import com.rapidminer.gui.properties.celleditors.value.SimpleFileValueCellEditor; import com.rapidminer.gui.properties.celleditors.value.SimpleSuggestionBoxValueCellEditor; import com.rapidminer.gui.properties.celleditors.value.TextValueCellEditor; +import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.components.ToolTipWindow; import com.rapidminer.gui.tools.components.ToolTipWindow.TipProvider; @@ -342,6 +344,20 @@ public void editingStopped(ChangeEvent e) { row++; } + // label for no parameters case + if (row == 0) { + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.CENTER; + c.weightx = 1; + c.fill = GridBagConstraints.HORIZONTAL; + JLabel noParametersLabel = new ResourceLabel("propertyPanel.no_parameters"); + noParametersLabel.setHorizontalAlignment(SwingConstants.CENTER); + add(noParametersLabel, c); + row++; + } + c.gridx = 0; c.gridy = row; c.weightx = 1; diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsDialog.java b/src/main/java/com/rapidminer/gui/properties/SettingsDialog.java index 54b48bfa1..c8f271f72 100644 --- a/src/main/java/com/rapidminer/gui/properties/SettingsDialog.java +++ b/src/main/java/com/rapidminer/gui/properties/SettingsDialog.java @@ -27,11 +27,14 @@ import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.io.IOException; import java.util.Collection; import java.util.LinkedList; -import java.util.Properties; - +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Box; @@ -54,6 +57,9 @@ import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.TextFieldWithAction; import com.rapidminer.gui.tools.dialogs.ButtonDialog; +import com.rapidminer.parameter.ParameterHandler; +import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; import com.rapidminer.tools.I18N; import com.rapidminer.tools.ParameterService; @@ -70,7 +76,7 @@ *

* *

- * To add a new preference, you have to use the method {@link ParameterService#registerParameter()}. + * To add a new preference, you have to use the method {@link ParameterService#registerParameter(ParameterType)}. * Your new parameter can be added to the i18n by adding the related key and a value to the resource * file Settings.properties. Configure the structure of your properties by editing the * resource file settings.xml. This affects the order and sub-groups. Extensions can use the @@ -79,7 +85,7 @@ * http://rapidminer.com/documentation/ *

* - * @author Ingo Mierswa, Adrian Wilke + * @author Ingo Mierswa, Adrian Wilke, Jan Czogalla */ public class SettingsDialog extends ButtonDialog { @@ -105,14 +111,16 @@ public class SettingsDialog extends ButtonDialog { private JPanel container; /** - * the displayed tabs which includes the settings + * cache for the displayed properties */ - private SettingsTabs tabs; + private transient ParameterHandler parameterHandler; + + private transient SettingsItemProvider settingsItemProvider; /** - * cache for the displayed properties + * the displayed tabs which includes the settings */ - private Properties propertyCache = new Properties(); + private SettingsTabs tabs; /** * this label will be shown if no matching settings could be found @@ -128,7 +136,8 @@ public SettingsDialog() { } /** - * Sets up the related {@link SettingsTabs} and buttons. + * Sets up the related {@link SettingsTabs} and buttons for the Studio settings. This uses {@link #getDefaultStudioHandler()} + * and {@link SettingsItems#INSTANCE} for initialization. * * Selects the specified selected tab. * @@ -136,7 +145,37 @@ public SettingsDialog() { * A key of a preferences group to identify the initial selected tab. */ public SettingsDialog(String initialSelectedTab) { - super(ApplicationFrame.getApplicationFrame(), "settings", ModalityType.APPLICATION_MODAL, new Object[] {}); + this(getDefaultStudioHandler(), SettingsItems.INSTANCE, initialSelectedTab); + // add listener to remove parameter handler when dialog is closed + addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + parameterHandler.getParameters().getParameterTypes().stream() + .flatMap(pt -> pt.getConditions().stream()).forEach(pc -> pc.setParameterHandler(null)); + } + }); + } + + /** + * Sets up the related {@link SettingsTabs} and buttons for generic setting. + *

+ * Selects the specified selected tab. + * + * @param parameterHandler + * the parameter handler responsible for these settings and for resolving dependencies; must not be {@code null} + * @param settingsItemProvider + * the settings item provider; must not be {@code null} + * @param initialSelectedTab + * A key of a preferences group to identify the initial selected tab. + */ + public SettingsDialog(ParameterHandler parameterHandler, SettingsItemProvider settingsItemProvider, String initialSelectedTab) { + super(ApplicationFrame.getApplicationFrame(), "settings", ModalityType.APPLICATION_MODAL, new Object[0]); + + if (parameterHandler == null || settingsItemProvider == null) { + throw new IllegalArgumentException("parameter handler and settings item provider must not be null!"); + } + this.parameterHandler = parameterHandler; + this.settingsItemProvider = settingsItemProvider; // main component container container = new JPanel(new BorderLayout()); @@ -172,8 +211,15 @@ public void loggedActionPerformed(ActionEvent e) { * Creates the settings tabs in regard to the filter. */ private JComponent createTabs(String initialSelectedTab, String filter) { + if (tabs != null) { + // remove old tabs as observer + parameterHandler.getParameters().removeObserver(tabs); + } + // Create tabs - tabs = new SettingsTabs(this, filter, propertyCache); + tabs = new SettingsTabs(this, filter); + // add new tabs as observer + parameterHandler.getParameters().addObserver(tabs, false); // Select tab, if known if (initialSelectedTab != null) { @@ -221,10 +267,8 @@ public void loggedActionPerformed(final ActionEvent e) { }; final DocumentListener filterListener = new DocumentListener() { - private Timer updateTimer; - + private Timer updateTimer = new Timer(FILTER_TIMER_DELAY, filterAction); { - updateTimer = new Timer(FILTER_TIMER_DELAY, filterAction); updateTimer.setRepeats(false); } @@ -286,7 +330,8 @@ public void loggedActionPerformed(final ActionEvent e) { return searchPanel; } - private void updateFilter(String filter) { + protected void updateFilter(String filter) { + settingsItemProvider.getKeys().forEach(k -> settingsItemProvider.get(k).setUsedInDialog(false)); container.remove(tabs); container.remove(noMatchingSettingsLabel); container.add(createTabs(null, filter), BorderLayout.CENTER); @@ -306,4 +351,32 @@ public void setVisible(boolean b) { } super.setVisible(b); } + + public ParameterHandler getParameterHandler() { + return parameterHandler; + } + + public SettingsItemProvider getSettingsItemProvider() { + return settingsItemProvider; + } + + /** + * Creates a simple {@link ParameterHandler} that relies on + * {@link ParameterService#getDefinedParameterKeys()} as its source of parameters + * @since 9.1 + */ + private static ParameterHandler getDefaultStudioHandler() { + return new SimpleListBasedParameterHandler() { + + // add all keys' parameter types if available; also set the parameter handler + private List parameterTypes = ParameterService.getParameterKeys().stream() + .map(ParameterService::getParameterType).filter(Objects::nonNull) + .peek(pt -> pt.getConditions().forEach(pc -> pc.setParameterHandler(this))).collect(Collectors.toList()); + + @Override + public List getParameterTypes() { + return parameterTypes; + } + }; + } } diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsItem.java b/src/main/java/com/rapidminer/gui/properties/SettingsItem.java index 216ab721c..7b98c6203 100644 --- a/src/main/java/com/rapidminer/gui/properties/SettingsItem.java +++ b/src/main/java/com/rapidminer/gui/properties/SettingsItem.java @@ -18,11 +18,15 @@ */ package com.rapidminer.gui.properties; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.function.Supplier; import java.util.logging.Level; +import org.apache.commons.lang.StringUtils; + import com.rapidminer.RapidMiner; import com.rapidminer.parameter.ParameterType; import com.rapidminer.tools.I18N; @@ -36,10 +40,12 @@ * * Parent/child relations are completely handled in the constructors. * - * @author Adrian Wilke + * @author Adrian Wilke, Jan Czogalla */ public class SettingsItem { + private String groupKey; + /** * Regarding the {@link SettingsDialog}, this represents either a tab (GROUP), a heading in a * tab (SUB_GROUP), or a setting by a parameter (PARAMETER) @@ -48,7 +54,7 @@ public enum Type { GROUP, SUB_GROUP, PARAMETER } - public final static String DEFAULT_PARAMETER_PREFIX = "rapidminer."; + public static final String DEFAULT_PARAMETER_PREFIX = "rapidminer."; /** Key of properties file */ private String key; @@ -65,17 +71,30 @@ public enum Type { /** 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 element's key + * @param parent + * Parent SettingsItem or null, if there is none + * @param type + */ + public SettingsItem(String key, SettingsItem parent, Type type) { + this(null, key, parent, type); + } + /** * Sets object variables and updates parent/child relations. * + * @param groupKey The element's group's key * @param key - * The elements key + * The element's key * @param parent * Parent SettingsItem or null, if there is none * @param type * The type of the item */ - public SettingsItem(String key, SettingsItem parent, Type type) { + public SettingsItem(String groupKey, String key, SettingsItem parent, Type type) { if (key == null || key.isEmpty()) { throw new IllegalArgumentException( "Settings item has no Key." + (parent == null ? "" : " Parent: " + parent.toString())); @@ -85,6 +104,7 @@ public SettingsItem(String key, SettingsItem parent, Type type) { "Settings item has no type." + (parent == null ? "" : " Parent: " + parent.toString())); } + this.groupKey = groupKey; this.key = key; this.parent = parent; this.type = type; @@ -135,26 +155,17 @@ 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 { + filter = StringUtils.stripToNull(filter); + if (filter == null) { return true; } + String[] filterTokens = filter.split(" "); + for (int i = 0; i < filterTokens.length; i++) { + filterTokens[i] = filterTokens[i].toLowerCase(Locale.ENGLISH); + } + List> stringProviders = Arrays.asList(child::getKey, child::getTitle, child::getDescription); + return stringProviders.stream().map(Supplier::get).filter(s -> s != null && !s.isEmpty()) + .map(s -> s.toLowerCase(Locale.ENGLISH)).anyMatch(s -> Arrays.stream(filterTokens).anyMatch(s::contains)); } /** @@ -184,7 +195,7 @@ public String getDescription() { * Returns the group key. Or null, if the group key is not known. */ public String getGroupKey() { - return ParameterService.getGroupKey(getKey()); + return groupKey; } /** @@ -231,7 +242,9 @@ public String getKey() { /** * Returns the type of the defined parameter identified by its ID. Returns null if * its key is unknown. + * @deprecated since 9.1; use {@link SettingsPropertyPanel#getParameterType(SettingsItem)} instead */ + @Deprecated public ParameterType getParameterType() { return ParameterService.getParameterType(key); } @@ -253,61 +266,46 @@ public SettingsItem getParent() { */ public String getTitle() { String title = I18N.getSettingsMessage(key, I18N.SettingsType.TITLE); - if (title.equals(key + I18N.SettingsType.TITLE)) { + if (!title.equals(key + I18N.SettingsType.TITLE)) { + return 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); - } + // 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; - // 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()); - } + if (getType() == 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('.', ' '); + } else if (getType() != Type.GROUP){ + // Remove 'rapidminer.' + if (title.startsWith(DEFAULT_PARAMETER_PREFIX)) { + title = title.substring(DEFAULT_PARAMETER_PREFIX.length()); + } + // Remove group prefix + if (groupKey != null && title.startsWith(groupKey + '.')) { + title = title.substring(groupKey.length() + 1); + } + title = title.replace('.', ' '); } - return title; + title = title.replace('_', ' '); + title = title.trim(); + return title.isEmpty() ? title : Character.toUpperCase(title.charAt(0)) + title.substring(1, title.length()); } /** @@ -337,16 +335,16 @@ public void setUsedInDialog(boolean usedInDialog) { */ @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); if (parent != null) { sb.append(parent.toString()); sb.append(" | "); } - if (type.equals(Type.PARAMETER)) { + if (type == Type.PARAMETER) { sb.append("["); } sb.append(key); - if (type.equals(Type.PARAMETER)) { + if (type == Type.PARAMETER) { sb.append("]"); } return sb.toString(); diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsItemProvider.java b/src/main/java/com/rapidminer/gui/properties/SettingsItemProvider.java new file mode 100644 index 000000000..b2ea679e0 --- /dev/null +++ b/src/main/java/com/rapidminer/gui/properties/SettingsItemProvider.java @@ -0,0 +1,155 @@ +/** + * Copyright (C) 2001-2018 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.Collection; +import java.util.List; + +import com.rapidminer.gui.properties.SettingsItem.Type; +import com.rapidminer.parameter.ParameterHandler; + + +/** + * An interface that specifies how a collection of {@link SettingsItem SettingsItems} can behave. + * Extracted from {@link SettingsItems}/{@link AbstractSettingsItemProvider}. + * + * @author Peter Hellinger, Jan Czogalla + * @since 9.1 + * + */ +public interface SettingsItemProvider { + + /** Removes empty subgroups and groups */ + void clean(); + + /** Checks if a key is known. */ + boolean containsKey(String key); + + /** Returns item or null, if key is unknown. */ + SettingsItem get(String key); + + /** + * Returns the value of the given key. Returns {@code null} for unknown or non-parameter keys. + * + * @since 9.1 + */ + String getValue(String key); + + /** + * Check if enforced settings exist + * + * @since 9.1 + */ + default boolean hasEnforcedSettings() { + return false; + } + + /** + * Check if the given settings key is enforced + * + * @since 9.1 + */ + + default boolean isSettingEnforced(String key) { + return false; + } + + /** Returns all items of the specified type. */ + List getItems(Type type); + + /** Returns all known keys. */ + Collection getKeys(); + + /** + * Adds an item to the map of used SettingsItem objects. Checks for null and empty + * values of the parameters. + */ + void put(String key, SettingsItem item); + + /** + * Removes item from {@link SettingsItems} and the {@link SettingsItem} internal hierarchy. + * + * @param key + * Key of item + * @throws IllegalStateException + * If key is not known or related item has children + */ + void remove(String key); + + /** + * Removes item from {@link SettingsItems} and/or the {@link SettingsItem} internal hierarchy. + * The execution of the remove operation can be set for each of the both data structures. + * + * @param key + * Key of item + * @param removeFromSettingsItems + * Remove from {@link SettingsItems} data structure + * @param removeFromHierarchy + * Removes from {@link SettingsItem} internal hierarchy + * + * @throws IllegalStateException + * If key is not known or related item has children + */ + void remove(String key, boolean removeFromSettingsItems, boolean removeFromHierarchy); + + /** Removes all elements of type parameter, whose keys are not contained in keepKeys */ + void removeParameterInverse(Collection keepKeys); + + /** + * Creates a SettingsItem and adds it to the item map. Parent items of the type GROUP are also + * generated. + * + * @param key + * The key of the item + * @param type + * The type of the item + * + * @return The created SettingsItem + */ + SettingsItem createAndAddItem(String key, Type type); + + /** + * Loads the grouping and returns whether it was successful. Subsequent calls to {@link #isGroupingLoaded()} + * will then return the same value. + * + * @since 9.1 + */ + boolean loadGrouping(); + + /** + * Returns true if the XML file was parsed successfully. Returns false if not. + * + * @since 9.1 + */ + boolean isGroupingLoaded(); + + /** + * Applies the values of the given parameter handler to the items + * + * @since 9.1 + */ + void applyValues(ParameterHandler parameterHandler); + + /** + * Saves the settings + * + * @since 9.1 + */ + void saveSettings(); +} \ No newline at end of file diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsItems.java b/src/main/java/com/rapidminer/gui/properties/SettingsItems.java index 8d3c58613..fbee51f12 100644 --- a/src/main/java/com/rapidminer/gui/properties/SettingsItems.java +++ b/src/main/java/com/rapidminer/gui/properties/SettingsItems.java @@ -18,217 +18,33 @@ */ package com.rapidminer.gui.properties; -import java.io.IOException; +import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.logging.Level; - -import javax.xml.parsers.ParserConfigurationException; - -import org.xml.sax.SAXException; import com.rapidminer.gui.properties.SettingsItem.Type; -import com.rapidminer.tools.LogService; +import com.rapidminer.parameter.ParameterHandler; +import com.rapidminer.parameter.Parameters; import com.rapidminer.tools.ParameterService; import com.rapidminer.tools.Tools; /** - * This singleton instance handles {SettingItem}s. It contains a map, which maps settings keys to - * {@link SettingsItem}s. Additionally to some default map methods and helper methods are provided. + * This singleton implementation of {@link AbstractSettingsItemProvider} handles {@link SettingsItem}s for general Studio settings. + * It contains a map, which maps settings keys to {@link SettingsItem}s. Additionally to some default map methods and helper methods are provided. * - * @author Adrian Wilke + * @author Adrian Wilke, Peter Hellinger, Jan Czogalla */ -public enum SettingsItems { - - INSTANCE; +public final class SettingsItems extends AbstractSettingsItemProvider { - /** Maps keys to SettingsItem objects */ - private Map itemMap = new LinkedHashMap<>(); - - /** Was XML of RapidMiner Studio parsed successfully? */ - private boolean studioXmlParsed = false; + public static final SettingsItems INSTANCE = new SettingsItems(); /** Singleton: Empty private constructor */ private SettingsItems() {} - /** Removes empty subgroups and groups */ - public void clean() { - List mapItems = getItems(Type.SUB_GROUP); - Iterator mapIterator = mapItems.iterator(); - while (mapIterator.hasNext()) { - SettingsItem item = mapIterator.next(); - if (item.getChildren().isEmpty()) { - try { - remove(item.getKey()); - } catch (RuntimeException runtimeException) { - // This would be a failure in the settings structure and should not happen. - // The log is to notice an improbable occurrence. - LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsItems.remove_item_error", - runtimeException); - } - } - } - mapItems = getItems(Type.GROUP); - mapIterator = mapItems.iterator(); - while (mapIterator.hasNext()) { - SettingsItem item = mapIterator.next(); - if (item.getChildren().isEmpty()) { - try { - remove(item.getKey()); - } catch (RuntimeException runtimeException) { - // This would be a failure in the settings structure and should not happen. - // The log is to notice an improbable occurrence. - LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsItems.remove_item_error", - runtimeException); - } - } - } - }; - - /** Checks if a key is known. */ - public boolean containsKey(String key) { - return itemMap.containsKey(key); - } - - /** Returns item or null, if key is unknown. */ - public SettingsItem get(String key) { - return itemMap.get(key); - } - - /** Returns all items of the specified type. */ - public List getItems(Type type) { - List settingsItems = new LinkedList<>(); - for (SettingsItem settingsItem : itemMap.values()) { - if (settingsItem.getType().equals(type)) { - settingsItems.add(settingsItem); - } - } - return settingsItems; - } - - /** Returns all known keys. */ - public Collection getKeys() { - return new HashSet(itemMap.keySet()); - } - - /** - * Parses XML file of RapidMiner Studio with settings structure. - * - * Sets {@link SettingsItems#studioXmlParsed} to the return value. - * - * @return true, if the XML was parsed successfully. false, if not. - */ - public boolean parseStudioXml() { - try { - itemMap = new SettingsXmlHandler().parse(Tools.getResource(SettingsXmlHandler.SETTINGS_XML_FILE).toURI()); - studioXmlParsed = true; - return true; - } catch (ParserConfigurationException | SAXException | IOException | URISyntaxException e) { - String[] params = new String[2]; - params[0] = SettingsXmlHandler.SETTINGS_XML_FILE; - params[1] = e.getMessage(); - LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsItems.parse_xml_error", params); - studioXmlParsed = false; - return false; - // Must not throw an exception, as the settings work without the structure inside XML. - } - } - - /** - * Adds an item to the map of used SettingsItem objects. Checks for null and empty - * values of the parameters. - */ - public void put(String key, SettingsItem item) { - if (key == null || key.isEmpty()) { - throw new IllegalArgumentException("Key not set"); - } - if (item == null) { - throw new IllegalArgumentException("No item for key " + key); - } - itemMap.put(key, item); - } - - /** - * Removes item from {@link SettingsItems} and the {@link SettingsItem} internal hierarchy. - * - * @param key - * Key of item - * @throws IllegalStateException - * If key is not known or related item has children - */ - public void remove(String key) throws IllegalStateException { - remove(key, true, true); - } - - /** - * Removes item from {@link SettingsItems} and/or the {@link SettingsItem} internal hierarchy. - * The execution of the remove operation can be set for each of the both data structures. - * - * @param key - * Key of item - * @param removeFromSettingsItems - * Remove from {@link SettingsItems} data structure - * @param removeFromHierarchy - * Removes from {@link SettingsItem} internal hierarchy - * - * @throws IllegalStateException - * If key is not known or related item has children - */ - public void remove(String key, boolean removeFromSettingsItems, boolean removeFromHierarchy) - throws IllegalStateException { - - if (!itemMap.containsKey(key)) { - throw new IllegalStateException("Could not remove settings item " + key + " as it is not known"); - } - - if (removeFromHierarchy) { - SettingsItem item = itemMap.get(key); - if (item.getChildren().isEmpty()) { - if (item.getParent() != null) { - item.getParent().getChildren().remove(item); - } - } else { - throw new IllegalStateException("Could not remove settings item " + key + " as it has children"); - } - } - - if (removeFromSettingsItems) { - itemMap.remove(key); - } - } - - /** Removes all elements of type parameter, whose keys are not contained in keepKeys */ - public void removeParameterInverse(Collection keepKeys) { - Iterator> itemMapIterator = itemMap.entrySet().iterator(); - while (itemMapIterator.hasNext()) { - Entry itemMapEntry = itemMapIterator.next(); - String key = itemMapEntry.getKey(); - if (!keepKeys.contains(key)) { - SettingsItem item = itemMapEntry.getValue(); - if (item.getType().equals(Type.PARAMETER)) { - try { - remove(key, false, true); - itemMapIterator.remove(); - } catch (IllegalStateException e) { - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.gui.properties.SettingsItems.remove_item_error", e); - } - } - } - } - } - - /** Returns true if the XML file was parsed successfully. Returns false if not. */ - public boolean isStudioXmlParsedSuccessfully() { - return studioXmlParsed; + @Override + public String getValue(String key) { + return ParameterService.getParameterValue(key); } /** @@ -242,7 +58,8 @@ public boolean isStudioXmlParsedSuccessfully() { * * @return The created SettingsItem */ - public static SettingsItem createAndAddItem(String key, Type type) { + @Override + public SettingsItem createAndAddItem(String key, Type type) { if (key == null || key.isEmpty()) { throw new IllegalArgumentException("Settings item has no key."); } @@ -250,21 +67,75 @@ public static SettingsItem createAndAddItem(String key, Type type) { SettingsItem parent = null; // If type is parameter, choose or create the related group + String groupKey = ParameterService.getGroupKey(key); if (type == Type.PARAMETER) { - String groupKey = ParameterService.getGroupKey(key); - if (!INSTANCE.containsKey(groupKey)) { + if (!containsKey(groupKey)) { parent = createAndAddItem(groupKey, Type.GROUP); } else { - parent = INSTANCE.get(groupKey); + parent = get(groupKey); } } // Create new SettingsItem - SettingsItem settingsItem = new SettingsItem(key, parent, type); + SettingsItem settingsItem = new SettingsItem(groupKey, key, parent, type); // Add to SettingsItems - INSTANCE.put(key, settingsItem); + put(key, settingsItem); return settingsItem; } + + /** @see ParameterService#setParameterValue(String, String) */ + @Override + public void applyValues(ParameterHandler parameterHandler) { + Parameters parameters = parameterHandler.getParameters(); + Collection parameterKeys = ParameterService.getParameterKeys(); + parameters.getDefinedKeys().stream().filter(parameterKeys::contains) + .forEach(k -> ParameterService.setParameterValue(k, parameters.getParameterOrNull(k))); + } + + /** @see ParameterService#saveParameters() */ + @Override + public void saveSettings() { + ParameterService.saveParameters(); + } + + /** @see ParameterService#hasEnforcedValues() */ + @Override + public boolean hasEnforcedSettings() { + return ParameterService.hasEnforcedValues(); + } + + /** @see ParameterService#isValueEnforced(String) */ + @Override + public boolean isSettingEnforced(String key) { + return ParameterService.isValueEnforced(key); + } + + @Override + protected URI getGroupDefinitions() throws URISyntaxException { + return Tools.getResource(SettingsXmlHandler.SETTINGS_XML_FILE).toURI(); + } + + /** + * Parses XML file of RapidMiner Studio with settings structure. + * + * Sets result of {@link #isStudioXmlParsedSuccessfully()} to the return value. + * + * @return {@code true}, iff the XML was parsed successfully. + * @deprecated since 9.1; use {@link #loadGrouping()} instead + */ + @Deprecated + public boolean parseStudioXml() { + return loadGrouping(); + } + + /** + * Returns true if the XML file was parsed successfully. Returns false if not. + * @deprecated since 9.1; use {@link #isGroupingLoaded()} instead + */ + @Deprecated + public boolean isStudioXmlParsedSuccessfully() { + return isGroupingLoaded(); + } } diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsPropertyPanel.java b/src/main/java/com/rapidminer/gui/properties/SettingsPropertyPanel.java index 8920eb983..97a2e0e92 100644 --- a/src/main/java/com/rapidminer/gui/properties/SettingsPropertyPanel.java +++ b/src/main/java/com/rapidminer/gui/properties/SettingsPropertyPanel.java @@ -26,8 +26,10 @@ import java.util.Collection; import java.util.LinkedList; import java.util.List; -import java.util.Properties; - +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; @@ -42,17 +44,17 @@ import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.operator.Operator; +import com.rapidminer.parameter.ParameterHandler; import com.rapidminer.parameter.ParameterType; import com.rapidminer.tools.I18N; -import com.rapidminer.tools.ParameterService; /** * The SettingsPropertyPanel is used to display settings of the same group. The used settings items - * are read from the {@link ParameterService}. This class also holds a method for applying changes - * in the value back to the {@link ParameterService}. + * are read from the {@link com.rapidminer.tools.ParameterService ParameterService}. This class also holds a method for applying changes + * in the value back to the {@link com.rapidminer.tools.ParameterService ParameterService}. * - * @author Sebastian Land, Simon Fischer, Adrian Wilke + * @author Sebastian Land, Simon Fischer, Adrian Wilke, Jan Czogalla */ public class SettingsPropertyPanel extends PropertyPanel { @@ -60,9 +62,10 @@ public class SettingsPropertyPanel extends PropertyPanel { private static final int FIRST_SUBGROUP_TOP_MARGIN = 6; private static final int SUBGROUP_TOP_MARGIN = 20; - private final Collection shownParameterTypes; - private final Collection allParameterTypes; - private final Properties allParameterValues; + final transient Collection shownParameterTypes; + + private final transient ParameterHandler parameterHandler; + private final transient SettingsItemProvider settingsItemProvider; private final String groupTitle; @@ -78,38 +81,40 @@ public class SettingsPropertyPanel extends PropertyPanel { /** Sub-group with the title of the tab should one be used one time */ private boolean subGroupTabNameUsed = false; - public SettingsPropertyPanel(String groupTitle, List itemSubGroups, List itemParameters, - String filter, Properties propertyCache) { + public SettingsPropertyPanel(SettingsDialog settingsDialog, String groupTitle, List itemSubGroups, List itemParameters, String filter) { + parameterHandler = settingsDialog.getParameterHandler(); + settingsItemProvider = settingsDialog.getSettingsItemProvider(); + this.groupTitle = groupTitle; // These data structures are used to provide overwritten PropertyPanel methods shownParameterTypes = new LinkedList<>(); - allParameterTypes = new LinkedList<>(); - if (propertyCache != null) { - allParameterValues = propertyCache; - } else { - allParameterValues = new Properties(); - } + + Set definedKeys = parameterHandler.getParameters().getDefinedKeys(); // Add parameters of sub-groups first for (SettingsItem subGroup : itemSubGroups) { - for (SettingsItem item : subGroup.getChildren(Type.PARAMETER, filter)) { - shownParameterTypes.add(item.getParameterType()); - } for (SettingsItem item : subGroup.getChildren(Type.PARAMETER)) { - allParameterTypes.add(item.getParameterType()); - if (propertyCache == null || !propertyCache.containsKey(item.getKey())) { - allParameterValues.put(item.getKey(), ParameterService.getParameterValue(item.getKey())); + if (subGroup.isInFilter(item, filter)) { + ParameterType parameterType = getParameterType(item); + if (parameterType != null) { + shownParameterTypes.add(parameterType); + } + } + if (!definedKeys.contains(item.getKey())) { + parameterHandler.setParameter(item.getKey(), getParameterValue(item)); } } } // Add parameters without sub-group for (SettingsItem item : itemParameters) { - allParameterTypes.add(item.getParameterType()); - shownParameterTypes.add(item.getParameterType()); - if (propertyCache == null || !propertyCache.containsKey(item.getKey())) { - allParameterValues.put(item.getKey(), ParameterService.getParameterValue(item.getKey())); + ParameterType parameterType = getParameterType(item); + if (parameterType != null) { + shownParameterTypes.add(parameterType); + } + if (!definedKeys.contains(item.getKey())) { + parameterHandler.setParameter(item.getKey(), getParameterValue(item)); } } @@ -120,14 +125,24 @@ public SettingsPropertyPanel(String groupTitle, List itemSubGroups setupComponents(); } + /** @since 9.1 */ + private ParameterType getParameterType(SettingsItem item) { + return parameterHandler.getParameters().getParameterType(item.getKey()); + } + + /** @since 9.1 */ + private String getParameterValue(SettingsItem item) { + return settingsItemProvider.getValue(item.getKey()); + } + @Override protected Collection getProperties() { - return shownParameterTypes; + return shownParameterTypes.stream().filter(pt -> !pt.isHidden()).collect(Collectors.toList()); } @Override protected String getValue(ParameterType type) { - String value = allParameterValues.getProperty(type.getKey()); + String value = parameterHandler.getParameters().getParameterOrNull(type.getKey()); if (value == null) { return null; } else { @@ -137,20 +152,21 @@ protected String getValue(ParameterType type) { @Override protected void setValue(Operator operator, ParameterType type, String value) { - allParameterValues.put(type.getKey(), value); - - if (!SettingsItems.INSTANCE.containsKey(type.getKey())) { + if (!settingsItemProvider.containsKey(type.getKey())) { // Object is automatically added to an internal list - SettingsItems.createAndAddItem(type.getKey(), Type.PARAMETER); + settingsItemProvider.createAndAddItem(type.getKey(), Type.PARAMETER); } + parameterHandler.setParameter(type.getKey(), value); } - /** Applies the properties without saving them. */ + /** + * Applies the properties without saving them. + * @deprecated since 9.1; this does nothing anymore + * @see SettingsTabs#applyProperties() + */ + @Deprecated public void applyProperties() { - for (ParameterType type : allParameterTypes) { - String value = allParameterValues.getProperty(type.getKey()); - ParameterService.setParameterValue(type, value); - } + // noop; handled in SettingsTabs now } @Override @@ -195,15 +211,9 @@ private JPanel createSubGroupPanel(String labelText) { * @return if the parent item should be added */ private boolean useParentAsHeading(SettingsItem parent) { - if (!parent.getType().equals(Type.SUB_GROUP)) { - // Only sub-groups are added as headings - return false; - } else if (parent.isUsedInDialog()) { - // No sub-group should be added twice - return false; - } else { - return true; - } + // Only sub-groups are added as headings + // No sub-group should be added twice + return parent.getType() == Type.SUB_GROUP && !parent.isUsedInDialog(); } /** @@ -214,18 +224,10 @@ private boolean useParentAsHeading(SettingsItem parent) { * @return if the heading 'misc' should be added */ private boolean useMiscHeading(SettingsItem parent) { - if (parent.getType().equals(Type.SUB_GROUP)) { - // Do not add Miscellaneous, if the is a sub-group with a better title - return false; - } else if (subGroupMiscUsed) { - // The sub group 'Misc' should not be added twice - return false; - } else if (!useSubGroups) { - // Only use 'Misc', if there are other known sub-groups - return false; - } else { - return true; - } + // Do not add Miscellaneous, if there is a sub-group with a better title + // The sub group 'Misc' should not be added twice + // Only use 'Misc', if there are other known sub-groups + return parent.getType() != Type.SUB_GROUP && !subGroupMiscUsed && useSubGroups; } /** @@ -236,18 +238,10 @@ private boolean useMiscHeading(SettingsItem parent) { * @return if the tab name should be added as heading */ private boolean useTabHeading(SettingsItem parent) { - if (parent.getType().equals(Type.SUB_GROUP)) { - // Do not add tab name, if the is a sub-group with a better title - return false; - } else if (subGroupTabNameUsed) { - // The heading should only be added one time - return false; - } else if (useSubGroups) { - // Only use tab name, if no other sub-groups are used - return false; - } else { - return true; - } + // Do not add tab name, if the is a sub-group with a better title + // The heading should only be added one time + // Only use tab name, if no other sub-groups are used + return parent.getType() != Type.SUB_GROUP && !subGroupTabNameUsed && !useSubGroups; } @Override @@ -262,7 +256,7 @@ protected JPanel createParameterPanel(ParameterType type, PropertyValueCellEdito JPanel containerPanel = new JPanel(); containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.PAGE_AXIS)); - SettingsItem settingsItem = SettingsItems.INSTANCE.get(type.getKey()); + SettingsItem settingsItem = settingsItemProvider.get(type.getKey()); // Add sub-group title before adding properties @@ -343,13 +337,13 @@ protected JPanel createParameterPanel(ParameterType type, PropertyValueCellEdito surroundingPanel.add(parameterPanel, BorderLayout.CENTER); JPanel helpWrapperPanel = surroundingPanel; - if (ParameterService.hasEnforcedValues()) { + if (settingsItemProvider.hasEnforcedSettings()) { JPanel infoPanel = new JPanel(new BorderLayout()); helpWrapperPanel = new JPanel(new BorderLayout()); infoPanel.add(helpWrapperPanel, BorderLayout.CENTER); surroundingPanel.add(infoPanel, BorderLayout.EAST); final JLabel lockedByAdminLabel; - if (ParameterService.isValueEnforced(type.getKey())) { + if (settingsItemProvider.isSettingEnforced(type.getKey())) { SwingTools.setEnabledRecursive(contentsPanel, false); lockedByAdminLabel = new ResourceLabel("preferences.setting_enforced"); } else { @@ -365,4 +359,17 @@ protected JPanel createParameterPanel(ParameterType type, PropertyValueCellEdito return containerPanel; } + @Override + public void setupComponents() { + // reset items used state + shownParameterTypes.stream().flatMap(pt -> { + SettingsItem item = settingsItemProvider.get(pt.getKey()); + return Stream.of(item, item.getParent()); + }).filter(Objects::nonNull)//.filter(item -> item.getType() != Type.GROUP) + .forEach(si -> si.setUsedInDialog(false)); + // reset other states + useSubGroups = subGroupMiscUsed = subGroupTabNameUsed = false; + isFirstSubGroup = true; + super.setupComponents(); + } } diff --git a/src/main/java/com/rapidminer/gui/properties/SettingsTabs.java b/src/main/java/com/rapidminer/gui/properties/SettingsTabs.java index c6ea16e4c..a6c6a85c9 100644 --- a/src/main/java/com/rapidminer/gui/properties/SettingsTabs.java +++ b/src/main/java/com/rapidminer/gui/properties/SettingsTabs.java @@ -24,16 +24,14 @@ import java.awt.Point; import java.io.IOException; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.logging.Level; - import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; @@ -44,6 +42,7 @@ import javax.swing.ScrollPaneConstants; import com.rapidminer.RapidMiner; +import com.rapidminer.external.alphanum.AlphanumComparator; import com.rapidminer.gui.properties.SettingsItem.Type; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ExtendedJTabbedPane; @@ -52,6 +51,8 @@ import com.rapidminer.gui.tools.components.ToolTipWindow.TipProvider; import com.rapidminer.gui.tools.components.ToolTipWindow.TooltipLocation; import com.rapidminer.tools.LogService; +import com.rapidminer.tools.Observable; +import com.rapidminer.tools.Observer; import com.rapidminer.tools.ParameterService; @@ -61,7 +62,7 @@ * * @author Sebastian Land, Ingo Mierswa, Adrian Wilke */ -public class SettingsTabs extends ExtendedJTabbedPane { +public class SettingsTabs extends ExtendedJTabbedPane implements Observer { private static final long serialVersionUID = -229446448782516589L; @@ -87,20 +88,12 @@ public class SettingsTabs extends ExtendedJTabbedPane { public static final Color COLOR_GROUP_DESCRIPTION = SwingTools.RAPIDMINER_GRAY; /** Compares titles of SettingItem objects */ - private static final Comparator SETTINGS_ITEM_COMPARATOR = new Comparator() { - - @Override - public int compare(SettingsItem itemA, SettingsItem itemB) { - if (itemA == null && itemB == null) { - return 0; - } else if (itemA == null) { - return 1; - } else if (itemB == null) { - return -1; - } else { - return itemA.getTitle().compareTo(itemB.getTitle()); - } + private static final Comparator SETTINGS_TITLE_COMPARATOR = new AlphanumComparator(); + private static final Comparator SETTINGS_ITEM_COMPARATOR = (itemA, itemB) -> { + if (itemA == null) { + return itemB == null ? 0 : 1; } + return itemB == null ? -1 : SETTINGS_TITLE_COMPARATOR.compare(itemA.getTitle(), itemB.getTitle()); }; /** @@ -110,7 +103,7 @@ public int compare(SettingsItem itemA, SettingsItem itemB) { * The containing dialog. Is used to create {@link ToolTipWindow}s for tabs. */ public SettingsTabs(SettingsDialog settingsDialog) { - this(settingsDialog, null, null); + this(settingsDialog, null); } /** @@ -120,19 +113,17 @@ public SettingsTabs(SettingsDialog settingsDialog) { * The containing dialog. Is used to create {@link ToolTipWindow}s for tabs. * @param filter * Used to filter the setting parameters - * @param propertyCache - * which should be used to retrieve the values */ - public SettingsTabs(SettingsDialog settingsDialog, String filter, Properties propertyCache) { + public SettingsTabs(SettingsDialog settingsDialog, String filter) { this.settingsDialog = settingsDialog; setTabPlacement(JTabbedPane.LEFT); // Get defined-parameters // These are all parameters, which will appear in dialog - Collection definedParameterKeys = ParameterService.getDefinedParameterKeys(); + Collection definedParameterKeys = new HashSet<>(settingsDialog.getParameterHandler().getParameters().getKeys()); // Get parsed settings items - SettingsItems items = SettingsItems.INSTANCE; + SettingsItemProvider items = settingsDialog.getSettingsItemProvider(); // Remove structured settings items, which are not in defined-parameter // (The structure is known, but they would not be used) @@ -156,7 +147,7 @@ public SettingsTabs(SettingsDialog settingsDialog, String filter, Properties pro while (iterator.hasNext()) { String key = iterator.next(); - SettingsItems.createAndAddItem(key, Type.PARAMETER); + items.createAndAddItem(key, Type.PARAMETER); if (isDebugMode) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.properties.SettingsTabs.no_parameter_in_xml", @@ -169,29 +160,22 @@ public SettingsTabs(SettingsDialog settingsDialog, String filter, Properties pro // Create tabs List groups = items.getItems(Type.GROUP); - if (!items.isStudioXmlParsedSuccessfully()) { + if (!items.isGroupingLoaded()) { // Sort groups lexicographically, if XML could not be parsed - Collections.sort(groups, SETTINGS_ITEM_COMPARATOR); + groups.sort(SETTINGS_ITEM_COMPARATOR); } for (SettingsItem group : groups) { List subGroups = group.getChildren(Type.SUB_GROUP, filter); List parameters = group.getChildren(Type.PARAMETER, filter); - boolean isSubGroupsEmpty = true; - for (SettingsItem subGroup : subGroups) { - if (!subGroup.getChildren(Type.PARAMETER, filter).isEmpty()) { - isSubGroupsEmpty = false; - break; - } - } - if (parameters.size() > 0 || !isSubGroupsEmpty) { - createTab(group.getKey(), group.getTitle(), group.getDescription(), subGroups, parameters, filter, - propertyCache); + boolean isSubGroupsEmpty = subGroups.stream().allMatch(subGroup -> subGroup.getChildren(Type.PARAMETER, filter).isEmpty()); + if (!parameters.isEmpty() || !isSubGroupsEmpty) { + createTab(group.getKey(), group.getTitle(), group.getDescription(), subGroups, parameters, filter); } } // Remove the used flag to prevent broken settings dialog after second opening. - for (String key : SettingsItems.INSTANCE.getKeys()) { - SettingsItems.INSTANCE.get(key).setUsedInDialog(false); + for (String key : items.getKeys()) { + items.get(key).setUsedInDialog(false); } } @@ -211,7 +195,7 @@ public void selectTab(String groupKey) { * Creates a tab */ private void createTab(String groupKey, String groupTitle, String groupDescription, List subGroups, - List parameters, String filter, Properties propertyCache) { + List parameters, String filter) { JPanel containerPanel = new JPanel(); containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.PAGE_AXIS)); @@ -235,18 +219,13 @@ private void createTab(String groupKey, String groupTitle, String groupDescripti } containerPanel.add(descriptionPanel); - final SettingsPropertyPanel table = new SettingsPropertyPanel(groupTitle, subGroups, parameters, filter, - propertyCache); + final SettingsPropertyPanel table = new SettingsPropertyPanel(settingsDialog, groupTitle, subGroups, parameters, filter); new ToolTipWindow(settingsDialog, new TipProvider() { @Override public String getTip(Object id) { - if (id == null) { - return null; - } else { - return SettingsTabs.tooltipDescriptions.get(id); - } + return id == null ? null : SettingsTabs.tooltipDescriptions.get(id); } @Override @@ -254,19 +233,13 @@ public Object getIdUnder(Point point) { Point tableScreenLocation = table.getLocationOnScreen(); int mouseX = point.x + tableScreenLocation.x; int mouseY = point.y + tableScreenLocation.y; - for (JComponent component : SettingsTabs.tooltipDescriptions.keySet()) { - if (!component.isShowing()) { - continue; - } else { - int compX = component.getLocationOnScreen().x; - int compY = component.getLocationOnScreen().y; - if (mouseX > compX && mouseY > compY && mouseX < compX + component.getWidth() - && mouseY < compY + component.getHeight()) { - return component; - } - } - } - return null; + return SettingsTabs.tooltipDescriptions.keySet().stream().filter(JComponent::isShowing) + .filter(component -> { + int compX = component.getLocationOnScreen().x; + int compY = component.getLocationOnScreen().y; + return (mouseX > compX && mouseY > compY && mouseX < compX + component.getWidth() + && mouseY < compY + component.getHeight()); + }).findFirst().orElse(null); } @Override @@ -288,10 +261,16 @@ public Component getCustomComponent(Object id) { groupKeysToTabIndexMap.put(groupKey, getTabCount() - 1); } + @Override + public void update(Observable observable, String key) { + // find affected property panels in regards to conditions, then update their components + parameterPanels.stream().filter(spp -> spp.shownParameterTypes.stream() + .flatMap(pt -> pt.getConditions().stream()).anyMatch(pc -> key.equals(pc.getConditionParameter()))) + .forEach(SettingsPropertyPanel::setupComponents); + } + public void applyProperties() { - for (SettingsPropertyPanel panel : parameterPanels) { - panel.applyProperties(); - } + settingsDialog.getSettingsItemProvider().applyValues(settingsDialog.getParameterHandler()); } /** @@ -299,7 +278,7 @@ public void applyProperties() { */ public void save() throws IOException { applyProperties(); - ParameterService.saveParameters(); + settingsDialog.getSettingsItemProvider().saveSettings(); } /** diff --git a/src/main/java/com/rapidminer/gui/properties/TextPropertyDialog.java b/src/main/java/com/rapidminer/gui/properties/TextPropertyDialog.java index c370fce99..4bd0694cf 100644 --- a/src/main/java/com/rapidminer/gui/properties/TextPropertyDialog.java +++ b/src/main/java/com/rapidminer/gui/properties/TextPropertyDialog.java @@ -31,6 +31,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rtextarea.RTextScrollPane; +import com.rapidminer.gui.ApplicationFrame; import com.rapidminer.gui.properties.celleditors.value.TextValueCellEditor; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.SQLEditor; @@ -74,7 +75,7 @@ public void loggedActionPerformed(ActionEvent e) { Dimension currentSize = getSize(); if (currentSize.getHeight() != dim.getHeight() && currentSize.getWidth() != dim.getWidth()) { setSize(dim); - setLocationRelativeTo(null); + setLocationRelativeTo(ApplicationFrame.getApplicationFrame()); resizeButton.setText(I18N.getMessage(I18N.getGUIBundle(), "gui.action.text_dialog.shrink.label")); resizeButton.setToolTipText(I18N.getMessage(I18N.getGUIBundle(), "gui.action.text_dialog.shrink.tip")); resizeButton.setMnemonic(I18N.getMessage(I18N.getGUIBundle(), "gui.action.text_dialog.shrink.mne") diff --git a/src/main/java/com/rapidminer/gui/renderer/MatchingEntry.java b/src/main/java/com/rapidminer/gui/renderer/MatchingEntry.java new file mode 100644 index 000000000..051aa25ab --- /dev/null +++ b/src/main/java/com/rapidminer/gui/renderer/MatchingEntry.java @@ -0,0 +1,153 @@ +/** + * Copyright (C) 2001-2018 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.renderer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Vector; + + +/** + * An entry which stores a match score how well this entry matches. + * + * @author Andreas Timm, Marco Böck, Jan Czogalla + * @since 9.1.0 + */ +public class MatchingEntry implements Comparable { + + private String entryName; + private double match; + + + /** + * Creates a new data match element. + * + * @param entryName + * the name of the data + * @param match + * the match score + */ + private MatchingEntry(String entryName, double match) { + this.entryName = entryName; + this.match = match; + } + + /** + * Returns the name. + * + * @return the name + */ + public String getEntryName() { + return entryName; + } + + /** + * Returns the match score. + * + * @return the match score + */ + public double getMatch() { + return this.match; + } + + /** + * Compares this element to a different one. Returns the result of Double.compare(o.match, this.match). + * Unknown matches will be sorted to the end. + * + * @param o + * the other + * @return the result of Double.compare(o.match, this.match) + */ + @Override + public int compareTo(MatchingEntry o) { + return Double.compare(-match, -o.match); + } + + /** + * Change the match value. + * + * @param match + * a double value between 0.0 and 1.0 + */ + public void setMatch(double match) { + this.match = match; + } + + @Override + public String toString() { + return entryName; + } + + /** + * Factory method to create a single {@link MatchingEntry}. Will return {@code null} if the {@code entryName} is {@code null}. + */ + public static MatchingEntry create(String entryName, double match) { + if (entryName == null) { + return null; + } + return new MatchingEntry(entryName, match); + } + + /** + * Factory method to create a bunch of {@link MatchingEntry} elements. + * + * @param entryValueMap + * a String mapping to prediction values + * @return the sorted {@link MatchingEntry} array + */ + public static MatchingEntry[] create(Map entryValueMap) { + if (entryValueMap == null || entryValueMap.isEmpty()) { + return new MatchingEntry[0]; + } + List result = new ArrayList<>(); + entryValueMap.forEach((key, value) -> result.add(new MatchingEntry(key, value))); + Collections.sort(result); + return result.toArray(new MatchingEntry[0]); + } + + /** + * A factory method to create elements without a prediction match value of this kind. + * + * @param values + * the Strings that are available but have no prediction + * @return an array of {@link MatchingEntry} + */ + public static MatchingEntry[] createArray(String[] values) { + if (values == null) { + return new MatchingEntry[0]; + } + MatchingEntry[] result = new MatchingEntry[values.length]; + Arrays.setAll(result, i -> new MatchingEntry(values[i], 0)); + return result; + } + + /** + * A factory method to create elements without a prediction match value of this kind. + * + * @param values + * the Strings that are available but have no prediction + * @return a vector of {@link MatchingEntry} + */ + public static Vector createVector(String[] values) { + return new Vector<>(Arrays.asList(createArray(values))); + } +} diff --git a/src/main/java/com/rapidminer/gui/renderer/MatchingEntryRenderer.java b/src/main/java/com/rapidminer/gui/renderer/MatchingEntryRenderer.java new file mode 100644 index 000000000..fefa83a2c --- /dev/null +++ b/src/main/java/com/rapidminer/gui/renderer/MatchingEntryRenderer.java @@ -0,0 +1,159 @@ +/** + * Copyright (C) 2001-2018 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.renderer; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.text.NumberFormat; +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; + + +/** + * A renderer for {@link MatchingEntry}. Each entry stores a match score showing how well this entry matches other data. + * + * @author Andreas Timm, Marco Böck + * @since 9.1.0 + */ +public class MatchingEntryRenderer extends JPanel implements ListCellRenderer { + + /** The label to show the matching value */ + private JLabel matchLabel; + + /** The label that contains the text MatchingEntry name */ + private JLabel textLabel; + + + /** + * Creates a new renderer. + */ + public MatchingEntryRenderer() { + textLabel = new JLabel(); + matchLabel = new JLabel() { + + @Override + public Dimension getPreferredSize() { + return new Dimension(36, super.getPreferredSize().height); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + }; + + setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 3)); + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.weighty = 0; + c.anchor = GridBagConstraints.NORTHWEST; + c.insets = new Insets(0, 0, 0, 0); + + c.weightx = 0; + c.gridwidth = GridBagConstraints.RELATIVE; + add(matchLabel, c); + + c.weightx = 1; + c.gridwidth = GridBagConstraints.REMAINDER; + add(textLabel, c); + } + + /** + * Returns the preferred size. + * + * @return the preferred size + */ + @Override + public Dimension getPreferredSize() { + return new Dimension(150, super.getPreferredSize().height + 12); + } + + /** + * Returns the actual renderer component. + * + * @param list + * the list + * @param value + * the value + * @param index + * the index + * @param isSelected + * if selected + * @param cellHasFocus + * if has focus + * @return the renderer + */ + @Override + public Component getListCellRendererComponent(JList list, MatchingEntry value, int index, boolean isSelected, boolean cellHasFocus) { + setComponentOrientation(list.getComponentOrientation()); + + setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); + + matchLabel.setText(null); + if (value != null ) { + double match = value.getMatch(); + String matchText = getMatchtext(match); + String entryName = value.getEntryName(); + matchLabel.setVisible(!matchText.isEmpty() && !entryName.isEmpty()); + matchLabel.setText(matchText); + textLabel.setText(entryName.isEmpty() ? " " : entryName); + setToolTipText(entryName.isEmpty() ? null : entryName); + + Color foreGroundColor = match < 0.1 ? Color.GRAY : Color.BLACK; + matchLabel.setForeground(foreGroundColor); + textLabel.setForeground(foreGroundColor); + } + + matchLabel.setFont(list.getFont()); + textLabel.setFont(list.getFont()); + + return this; + } + + /** + * Get the formatted matching text. Can be green. + * + * @param match + * the match value to show + * @return an HTML String or an empty String + */ + public static String getMatchtext(double match) { + if (Double.isNaN(match)) { + return ""; + } + return "= 0.8 ? "green" : match < 0.1 ? "light-gray" : "black") + + "\">" + + NumberFormat.getPercentInstance().format(match) + + ""; + } +} \ No newline at end of file diff --git a/src/main/java/com/rapidminer/gui/renderer/RendererService.java b/src/main/java/com/rapidminer/gui/renderer/RendererService.java index 97af63955..7e6d625f8 100644 --- a/src/main/java/com/rapidminer/gui/renderer/RendererService.java +++ b/src/main/java/com/rapidminer/gui/renderer/RendererService.java @@ -200,19 +200,20 @@ public static void init(String rendererFileName, InputStream in, ClassLoader cla LogService.getRoot().log( Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), - "com.rapidminer.gui.renderer.RendererService.initializing_io_object_description_error", e), e); + "com.rapidminer.gui.renderer.RendererService.initializing_io_object_description_error", + rendererFileName), e); } catch (IOException e) { LogService.getRoot().log( Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), "com.rapidminer.gui.renderer.RendererService.initializing_io_object_description_parsing_error", - e), e); + rendererFileName), e); } catch (SAXException e) { LogService.getRoot().log( Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), "com.rapidminer.gui.renderer.RendererService.initializing_io_object_description_parsing_error", - e), e); + rendererFileName), e); } finally { if (in != null) { try { diff --git a/src/main/java/com/rapidminer/gui/renderer/data/ExampleSetDataRenderer.java b/src/main/java/com/rapidminer/gui/renderer/data/ExampleSetDataRenderer.java index 205ec8b0e..994d78dd2 100644 --- a/src/main/java/com/rapidminer/gui/renderer/data/ExampleSetDataRenderer.java +++ b/src/main/java/com/rapidminer/gui/renderer/data/ExampleSetDataRenderer.java @@ -60,7 +60,7 @@ public String getName() { @Override public Component getVisualizationComponent(Object renderable, IOContainer ioContainer) { ExampleSet exampleSet = (ExampleSet) renderable; - return new DataViewer(exampleSet, true); + return new DataViewer(exampleSet); } /** diff --git a/src/main/java/com/rapidminer/gui/search/GlobalSearchController.java b/src/main/java/com/rapidminer/gui/search/GlobalSearchController.java index 98158e63a..32abab72b 100644 --- a/src/main/java/com/rapidminer/gui/search/GlobalSearchController.java +++ b/src/main/java/com/rapidminer/gui/search/GlobalSearchController.java @@ -93,7 +93,11 @@ protected void loadMoreRows(final GlobalSearchResult previousResult, final Strin return; } - searchOrAppendForCategory(previousResult.getLastResult(), lastQuery, categoryId, lastCategoryFilter != null ? NUMBER_OF_RESULTS_SINGLE_CAT : NUMBER_OF_RESULTS_ALL_CATS); + int resultNumberLimit = lastCategoryFilter != null ? NUMBER_OF_RESULTS_SINGLE_CAT : NUMBER_OF_RESULTS_ALL_CATS; + if (resultNumberLimit == previousResult.getPotentialNumberOfResults() - previousResult.getNumberOfResults() - 1) { + resultNumberLimit++; + } + searchOrAppendForCategory(previousResult.getLastResult(), lastQuery, categoryId, resultNumberLimit); } @@ -177,7 +181,7 @@ private void searchOrAppendForCategory(final ScoreDoc offset, final String query @Override protected GlobalSearchResult doInBackground() throws Exception { model.setPending(categoryId, true); - GlobalSearchResultBuilder builder = new GlobalSearchResultBuilder(query.trim()).setMaxNumberOfResults(resultNumberLimit).setHighlightResult(true); + GlobalSearchResultBuilder builder = new GlobalSearchResultBuilder(query.trim()).setMaxNumberOfResults(resultNumberLimit).setMoreResults(1).setHighlightResult(true); builder.setSearchCategories(GlobalSearchRegistry.INSTANCE.getSearchCategoryById(categoryId)).setSearchOffset(offset).setSimpleMode(true); return builder.runSearch(); } diff --git a/src/main/java/com/rapidminer/gui/tools/ExtendedJTable.java b/src/main/java/com/rapidminer/gui/tools/ExtendedJTable.java index 24cf41d7e..1f10d93c3 100644 --- a/src/main/java/com/rapidminer/gui/tools/ExtendedJTable.java +++ b/src/main/java/com/rapidminer/gui/tools/ExtendedJTable.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.tools; import java.awt.Color; @@ -153,12 +153,12 @@ public ExtendedJTable(final boolean sortable, final boolean columnMovable, final } public ExtendedJTable(final TableModel model, final boolean sortable, final boolean columnMovable, - final boolean autoResize) { + final boolean autoResize) { this(model, sortable, columnMovable, autoResize, true, false); } public ExtendedJTable(final TableModel model, final boolean sortable, final boolean columnMovable, - final boolean autoResize, final boolean useColoredCellRenderer, final boolean fixFirstColumn) { + final boolean autoResize, final boolean useColoredCellRenderer, final boolean fixFirstColumn) { super(); this.sortable = sortable; this.useColoredCellRenderer = useColoredCellRenderer; @@ -314,7 +314,7 @@ public void setRowHighlighting(boolean enabled) { * given row is the currently highlighted row. * * @param row - * the row to check + * the row to check * @return {@code true} if it is currently highlighted; {@code false} otherwise */ public boolean isRowHighlighted(int row) { @@ -329,7 +329,7 @@ public boolean isRowHighlighted(int row) { * Sets the last highlighted row. * * @param row - * the last highlighted row + * the last highlighted row */ public void setLastHighlightedRow(int row) { if (!rowHighlightingEnabled) { @@ -758,7 +758,7 @@ public boolean getScrollableTracksViewportWidth() { * They might difer if the table is sorted. * * @param rowIndex - * The index of the row in the view. + * The index of the row in the view. * @return The index of the row in the original model. */ public int getModelIndex(final int rowIndex) { @@ -900,4 +900,26 @@ public String getTip(final Object id) { return getToolTipText(cellId.getFirst(), cellId.getSecond()); } } + + @Override + public Rectangle getCellRect(int row, int column, boolean includeSpacing) { + Rectangle rect = super.getCellRect(row, column, includeSpacing); + if (rect.y < 0) { + // If y < 0 the amount of rows times rowheight exceeds Integer.MAX_VALUE and becomes negative. + // This workaround will show a huge table, secured by factor 10 because else initially the table might be blank + rect.y = Integer.MAX_VALUE - (rect.height * 10); + } + return rect; + } + + /** + * Check if there are more rows than those that can be displayed due to swing's height limitation that can not be + * larger than Integer.MAX_VALUE. + * + * @return {@code true} if the table is completely displayable and no rows are missing, else it would be useful to display the information about invisible rows. + * @since 9.1 + */ + public boolean canShowAllRows() { + return (long) getRowHeight() * getRowCount() < Integer.MAX_VALUE; + } } diff --git a/src/main/java/com/rapidminer/gui/tools/PasswordDialog.java b/src/main/java/com/rapidminer/gui/tools/PasswordDialog.java index 0e407202c..d6bb71acd 100644 --- a/src/main/java/com/rapidminer/gui/tools/PasswordDialog.java +++ b/src/main/java/com/rapidminer/gui/tools/PasswordDialog.java @@ -25,7 +25,6 @@ import java.net.PasswordAuthentication; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; - import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; @@ -37,8 +36,8 @@ import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.security.UserCredential; import com.rapidminer.gui.security.Wallet; -import com.rapidminer.gui.tools.SwingTools.ResultRunnable; import com.rapidminer.gui.tools.dialogs.ButtonDialog; +import com.rapidminer.tools.I18N; import com.rapidminer.tools.LogService; import com.rapidminer.tools.ParameterService; import com.rapidminer.tools.PasswordInputCanceledException; @@ -200,7 +199,8 @@ public static PasswordAuthentication getPasswordAuthentication(String id, String if (authentication == null) { authentication = new UserCredential(forUrl, null, null); } - if (i18nKey == null || i18nKey.contains("authentication")) { + // only set to default authentication key if provided key not available + if (i18nKey == null || i18nKeyNotAvailable(i18nKey)) { i18nKey = "authentication"; args = new Object[] { authentication.getURL() }; } @@ -210,41 +210,15 @@ public static PasswordAuthentication getPasswordAuthentication(String id, String final String passwordI18N = i18nKey; // create PasswordDialog on EDT - final PasswordDialog pd = SwingTools.invokeAndWaitWithResult(new ResultRunnable() { - - @Override - public PasswordDialog run() { - PasswordDialog pd = new PasswordDialog(ApplicationFrame.getApplicationFrame(), passwordI18N, - passwordDialogCredentials, pdArgs); - // Onboarding is already a APPLICATION_MODAL - pd.setModalityType(ModalityType.TOOLKIT_MODAL); - pd.setVisible(true); - return pd; - } + final PasswordDialog pd = SwingTools.invokeAndWaitWithResult(() -> { + PasswordDialog pd1 = new PasswordDialog(ApplicationFrame.getApplicationFrame(), passwordI18N, + passwordDialogCredentials, pdArgs); + // Onboarding is already a APPLICATION_MODAL + pd1.setModalityType(ModalityType.TOOLKIT_MODAL); + pd1.setVisible(true); + return pd1; }); - if (pd.wasConfirmed()) { - PasswordAuthentication result = pd.makeAuthentication(); - if (pd.rememberBox.isSelected()) { - UserCredential userCredential = new UserCredential(forUrl, result.getUserName(), result.getPassword()); - if (id != null) { - Wallet.getInstance().registerCredentials(id, userCredential); - } else { - // compatibility with old API - Wallet.getInstance().registerCredentials(userCredential); - } - Wallet.getInstance().saveCache(); - } else { - if (id != null) { - Wallet.getInstance().removeEntry(id, forUrl); - } else { - // compatibility with old API - Wallet.getInstance().removeEntry(forUrl); - } - Wallet.getInstance().saveCache(); - } - - return result; - } else { + if (!pd.wasConfirmed()) { // If the user canceled the Password Dialog on forceRefresh the password is at this // point null. Restore old value to prevent NPEs. if (forceRefresh) { @@ -252,6 +226,37 @@ public PasswordDialog run() { } throw new PasswordInputCanceledException(); } + PasswordAuthentication result = pd.makeAuthentication(); + if (pd.rememberBox.isSelected()) { + UserCredential userCredential = new UserCredential(forUrl, result.getUserName(), result.getPassword()); + if (id != null) { + Wallet.getInstance().registerCredentials(id, userCredential); + } else { + // compatibility with old API + Wallet.getInstance().registerCredentials(userCredential); + } + } else if (id != null) { + Wallet.getInstance().removeEntry(id, forUrl); + } else { + // compatibility with old API + Wallet.getInstance().removeEntry(forUrl); + } + Wallet.getInstance().saveCache(); + + return result; + } + + /** + * Tests the availability of a given i18n key. More specifically tests if the key + *

{@code gui.dialog..title} can be found. + * + * @param i18nKey the i18n key to test for dialog purposes + * @return whether the key is available + * @since 9.0.2 + */ + private static boolean i18nKeyNotAvailable(String i18nKey) { + String fullKey = "gui.dialog." + i18nKey + ".title"; + return fullKey.equals(I18N.getMessage(I18N.getGUIBundle(), fullKey)); } public static PasswordAuthentication getPasswordAuthentication(String forUrl, boolean forceRefresh, diff --git a/src/main/java/com/rapidminer/gui/tools/ProgressThread.java b/src/main/java/com/rapidminer/gui/tools/ProgressThread.java index 8a6ed2b17..eb246a2ca 100644 --- a/src/main/java/com/rapidminer/gui/tools/ProgressThread.java +++ b/src/main/java/com/rapidminer/gui/tools/ProgressThread.java @@ -298,7 +298,7 @@ public void setDisplayLabel(String i18nKey) { } /** - * Note that this method has nothing to do with Thread.strart. It merely enqueues this Runnable + * Note that this method has nothing to do with Thread.start. It merely enqueues this Runnable * in the Executor's queue. */ public void start() { diff --git a/src/main/java/com/rapidminer/gui/tools/ResourceDockKey.java b/src/main/java/com/rapidminer/gui/tools/ResourceDockKey.java index 82b88027d..72b23d566 100644 --- a/src/main/java/com/rapidminer/gui/tools/ResourceDockKey.java +++ b/src/main/java/com/rapidminer/gui/tools/ResourceDockKey.java @@ -66,7 +66,7 @@ public ResourceDockKey(String resourceKey, boolean displayIcon) { } setFloatEnabled(true); setCloseEnabled(true); - setAutoHideEnabled(true); + setAutoHideEnabled(false); // setting default dock group to root: Must be overriden if should be result setDockGroup(MainFrame.DOCK_GROUP_ROOT); diff --git a/src/main/java/com/rapidminer/gui/tools/ResourceLabel.java b/src/main/java/com/rapidminer/gui/tools/ResourceLabel.java index 15d1ce71c..d38144c5d 100644 --- a/src/main/java/com/rapidminer/gui/tools/ResourceLabel.java +++ b/src/main/java/com/rapidminer/gui/tools/ResourceLabel.java @@ -41,7 +41,7 @@ public class ResourceLabel extends JLabel { *

  • gui.label.-key-.label as label
  • *
  • gui.label.-key-.tip as tooltip
  • *
  • gui.label.-key-.mne as mnemonic
  • - *
  • gui.label.-key-.icon as icon. Here the size must be assigned by leeding 24/ or something + *
  • gui.label.-key-.icon as icon. Here the size must be assigned by leading 24/ or something * like this
  • * */ @@ -52,6 +52,9 @@ public ResourceLabel(String i18nKey, Object... i18nArgs) { String mne = getMessageOrNull(i18nKey + ".mne"); String icon = getMessageOrNull(i18nKey + ".icon"); if (icon != null) { + if (!icon.contains("/")) { + icon = "16/" + icon; + } ImageIcon iicon = SwingTools.createIcon(icon); setIcon(iicon); } diff --git a/src/main/java/com/rapidminer/gui/tools/SwingTools.java b/src/main/java/com/rapidminer/gui/tools/SwingTools.java index 2c1e493f0..059812190 100644 --- a/src/main/java/com/rapidminer/gui/tools/SwingTools.java +++ b/src/main/java/com/rapidminer/gui/tools/SwingTools.java @@ -68,7 +68,6 @@ import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; -import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.KeyStroke; @@ -1255,9 +1254,6 @@ public void run() { * the I18n-key which will be used to display the internationalized message * @param errorMessage * the error message associated to this message - * @param displayExceptionMessage - * indicates if the exception message will be displayed in the dialog or just in the - * detailed panel * @param arguments * additional arguments for the internationalized message, which replace * {0}, {1}, etcpp. @@ -1278,9 +1274,6 @@ public static void showSimpleErrorMessage(final String key, final String errorMe * the I18n-key which will be used to display the internationalized message * @param errorMessage * the error message associated to this message - * @param displayExceptionMessage - * indicates if the exception message will be displayed in the dialog or just in the - * detailed panel * @param arguments * additional arguments for the internationalized message, which replace * {0}, {1}, etcpp. @@ -1313,7 +1306,7 @@ public void run() { * @param displayExceptionMessage * indicates if the exception message will be displayed in the dialog or just in the * detailed panel - * @param arguments + * @param objects * additional arguments for the internationalized message, which replace * {0}, {1}, etcpp. */ @@ -1335,16 +1328,17 @@ public static void showFinalErrorMessage(final String key, final Throwable e, fi * @param displayExceptionMessage * indicates if the exception message will be displayed in the dialog or just in the * detailed panel - * @param arguments + * @param objects * additional arguments for the internationalized message, which replace * {0}, {1}, etcpp. * @since 7.5.0 */ public static void showFinalErrorMessage(final Window owner, final String key, final Throwable e, final boolean displayExceptionMessage, final Object... objects) { - // if debug modus is enabled, print throwable into logger + // if debug mode is enabled, print throwable into logger if (ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_DEBUGMODE).equals("true")) { - LogService.getRoot().log(Level.SEVERE, e.getMessage(), e); + // Some exceptions don't have messages, logging null throws a NPE + LogService.getRoot().log(Level.SEVERE, String.valueOf(e.getMessage()), e); } invokeLater(new Runnable() { @@ -1364,7 +1358,7 @@ public void run() { * the I18n-key which will be used to display the internationalized message * @param e * the exception associated to this message - * @param arguments + * @param objects * additional arguments for the internationalized message, which replace * {0}, {1}, etcpp. */ diff --git a/src/main/java/com/rapidminer/gui/tools/VersionNumber.java b/src/main/java/com/rapidminer/gui/tools/VersionNumber.java index 965415f47..42f4bbc01 100644 --- a/src/main/java/com/rapidminer/gui/tools/VersionNumber.java +++ b/src/main/java/com/rapidminer/gui/tools/VersionNumber.java @@ -117,7 +117,7 @@ public VersionNumber(String versionString) { patchLevel = 0; } if (classifierIndex >= 0) { - classifier = CLASSIFIER_TAG + version.substring(classifierIndex + 1, version.length()); + classifier = CLASSIFIER_TAG + version.substring(classifierIndex + 1); } else { classifier = null; } diff --git a/src/main/java/com/rapidminer/gui/tools/dialogs/ButtonDialog.java b/src/main/java/com/rapidminer/gui/tools/dialogs/ButtonDialog.java index fdc2a60c4..ad57a9e4a 100644 --- a/src/main/java/com/rapidminer/gui/tools/dialogs/ButtonDialog.java +++ b/src/main/java/com/rapidminer/gui/tools/dialogs/ButtonDialog.java @@ -32,7 +32,6 @@ import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.KeyEvent; @@ -743,14 +742,8 @@ protected JPanel makeButtonPanel(AbstractButton... buttons) { for (final AbstractButton button : buttons) { if (button != null) { buttonPanel.add(button); - button.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - ActionStatisticsCollector.getInstance().log(ActionStatisticsCollector.TYPE_DIALOG, key, - button.getActionCommand()); - } - }); + button.addActionListener( + e -> ActionStatisticsCollector.getInstance().log(ActionStatisticsCollector.TYPE_DIALOG, key, button.getActionCommand())); } } return buttonPanel; diff --git a/src/main/java/com/rapidminer/gui/tools/dialogs/MultiPageDialog.java b/src/main/java/com/rapidminer/gui/tools/dialogs/MultiPageDialog.java index df77faf72..9463476d1 100644 --- a/src/main/java/com/rapidminer/gui/tools/dialogs/MultiPageDialog.java +++ b/src/main/java/com/rapidminer/gui/tools/dialogs/MultiPageDialog.java @@ -44,7 +44,7 @@ public abstract class MultiPageDialog extends ButtonDialog implements ChangeList private JPanel cardPanel; - private final JButton previous = new JButton(new ResourceAction("previous") { + protected final JButton previous = new JButton(new ResourceAction("previous") { private static final long serialVersionUID = 1L; @@ -53,7 +53,7 @@ public void loggedActionPerformed(java.awt.event.ActionEvent e) { previous(); } }); - private final JButton next = new JButton(new ResourceAction("next") { + protected final JButton next = new JButton(new ResourceAction("next") { private static final long serialVersionUID = 1L; @@ -62,7 +62,7 @@ public void loggedActionPerformed(java.awt.event.ActionEvent e) { next(); } }); - private final JButton finish = new JButton(new ResourceAction("finish") { + protected final JButton finish = new JButton(new ResourceAction("finish") { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/rapidminer/gui/viewer/DataViewer.java b/src/main/java/com/rapidminer/gui/viewer/DataViewer.java index c4ac6ce52..48e8c3fac 100644 --- a/src/main/java/com/rapidminer/gui/viewer/DataViewer.java +++ b/src/main/java/com/rapidminer/gui/viewer/DataViewer.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.viewer; import java.awt.BorderLayout; @@ -23,16 +23,15 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.util.LinkedList; import java.util.List; - import javax.swing.BorderFactory; import javax.swing.JComboBox; +import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.border.Border; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.set.Condition; @@ -41,11 +40,14 @@ import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.look.RapidLookTools; +import com.rapidminer.gui.processeditor.results.ResultTabActionVisualizer; import com.rapidminer.gui.tools.ExtendedJScrollPane; +import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.operator.tools.ExpressionEvaluationException; import com.rapidminer.report.Tableable; import com.rapidminer.tools.I18N; import com.rapidminer.tools.ParameterService; +import com.rapidminer.tools.usagestats.ActionStatisticsCollector; /** @@ -58,23 +60,20 @@ public class DataViewer extends JPanel implements Tableable { private static final long serialVersionUID = -8114228636932871865L; - private static final int DEFAULT_MAX_SIZE_FOR_FILTERING = 100000; + private static final int DEFAULT_MAX_SIZE_FOR_FILTERING = 100_000; - private JLabel generalInfo = new JLabel(); - { - generalInfo.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); - } private DataViewerTable dataTable = new DataViewerTable(); - /** Filter label display. */ + /** + * filter label display + */ private JLabel filterLabel; private transient ExampleSet originalExampleSet; - private JScrollPane tableScrollPane; - public DataViewer(ExampleSet exampleSet, boolean providedFilter) { + public DataViewer(ExampleSet exampleSet) { super(new BorderLayout()); setOpaque(true); setBackground(Colors.WHITE); @@ -88,19 +87,17 @@ public DataViewer(ExampleSet exampleSet, boolean providedFilter) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; - StringBuffer infoText = new StringBuffer("ExampleSet ("); - int noExamples = originalExampleSet.size(); - infoText.append(noExamples); - infoText.append(noExamples == 1 ? " example, " : " examples, "); - int noSpecial = originalExampleSet.getAttributes().specialSize(); - infoText.append(noSpecial); - infoText.append(noSpecial == 1 ? " special attribute, " : " special attributes, "); - int noRegular = originalExampleSet.getAttributes().size(); - infoText.append(noRegular); - infoText.append(noRegular == 1 ? " regular attribute)" : " regular attributes)"); - generalInfo.setText(infoText.toString()); - headerBar.add(generalInfo, gbc); + final JComponent resultActionsComponent = ResultTabActionVisualizer.createResultActionsComponent(() -> originalExampleSet); + if (resultActionsComponent != null) { + gbc.insets = new Insets(0, 10, 0, 0); + headerBar.add(new JLabel(I18N.getGUILabel("data_view.open_in.label")), gbc); + + gbc.gridx += 1; + gbc.insets = new Insets(0, 0, 0, 0); + headerBar.add(resultActionsComponent, gbc); + } // add filler component in middle gbc.gridx += 1; @@ -109,69 +106,91 @@ public DataViewer(ExampleSet exampleSet, boolean providedFilter) { headerBar.add(new JLabel(), gbc); // filter - if (providedFilter) { - filterLabel = new JLabel(I18N.getMessage(I18N.getGUIBundle(), "gui.label.data_view.filter.label")); + filterLabel = new JLabel(I18N.getGUILabel("data_view.filter.label")); - gbc.gridx += 1; - gbc.fill = GridBagConstraints.NONE; - gbc.weightx = 0.0; - headerBar.add(filterLabel, gbc); - - updateFilterCounter(originalExampleSet); - List applicableFilterNames = new LinkedList<>(); - for (String conditionName : ConditionedExampleSet.KNOWN_CONDITION_NAMES) { - try { - ConditionedExampleSet.createCondition(conditionName, exampleSet, null); - applicableFilterNames.add(conditionName); - } catch (ConditionCreationException ex) { - } // Do nothing - } - String[] applicableConditions = new String[applicableFilterNames.size()]; - applicableFilterNames.toArray(applicableConditions); - final JComboBox filterSelector = new JComboBox<>(applicableConditions); - filterSelector.putClientProperty(RapidLookTools.PROPERTY_INPUT_BACKGROUND_DARK, true); - filterSelector.setMinimumSize(new Dimension(140, 30)); - filterSelector.setPreferredSize(new Dimension(140, 30)); - filterSelector - .setToolTipText("These filters can be used to skip examples in the view fulfilling the filter condition."); - filterSelector.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent e) { - updateFilter((String) filterSelector.getSelectedItem()); - } - }); - - int maxNumberBeforeFiltering = DEFAULT_MAX_SIZE_FOR_FILTERING; - String maxString = ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_RAPIDMINER_GUI_MAX_STATISTICS_ROWS); - if (maxString != null) { - try { - maxNumberBeforeFiltering = Integer.parseInt(maxString); - } catch (NumberFormatException e) { - // do nothing - } - } - if (exampleSet.size() > maxNumberBeforeFiltering) { - filterSelector.setEnabled(false); + gbc.gridx += 1; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + headerBar.add(filterLabel, gbc); + + updateFilterCounter(originalExampleSet); + List applicableFilterNames = new LinkedList<>(); + for (String conditionName : ConditionedExampleSet.KNOWN_CONDITION_NAMES) { + try { + ConditionedExampleSet.createCondition(conditionName, exampleSet, null); + applicableFilterNames.add(conditionName); + } catch (ConditionCreationException ex) { + } // Do nothing + } + String[] applicableConditions = new String[applicableFilterNames.size()]; + applicableFilterNames.toArray(applicableConditions); + final JComboBox filterSelector = new JComboBox<>(applicableConditions); + filterSelector.putClientProperty(RapidLookTools.PROPERTY_INPUT_BACKGROUND_DARK, true); + filterSelector.setMinimumSize(new Dimension(140, 30)); + filterSelector.setPreferredSize(new Dimension(140, 30)); + filterSelector.setToolTipText(I18N.getGUILabel("data_view.filter.tip")); + filterSelector.addItemListener(e -> updateFilter((String) filterSelector.getSelectedItem())); + + int maxNumberBeforeFiltering = DEFAULT_MAX_SIZE_FOR_FILTERING; + String maxString = ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_RAPIDMINER_GUI_MAX_STATISTICS_ROWS); + if (maxString != null) { + try { + maxNumberBeforeFiltering = Integer.parseInt(maxString); + } catch (NumberFormatException e) { + // do nothing } - gbc.gridx += 1; - gbc.fill = GridBagConstraints.VERTICAL; - gbc.weighty = 1.0; - gbc.insets = new Insets(0, 10, 0, 0); - headerBar.add(filterSelector, gbc); } + if (exampleSet.size() > maxNumberBeforeFiltering) { + filterSelector.setEnabled(false); + } + gbc.gridx += 1; + gbc.insets = new Insets(0, 10, 0, 0); + headerBar.add(filterSelector, gbc); add(headerBar, BorderLayout.NORTH); - tableScrollPane = new ExtendedJScrollPane(dataTable); + JScrollPane tableScrollPane = new ExtendedJScrollPane(dataTable); tableScrollPane.setOpaque(true); tableScrollPane.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 10)); tableScrollPane.setBackground(Colors.WHITE); tableScrollPane.getViewport().setBackground(Colors.WHITE); add(tableScrollPane, BorderLayout.CENTER); + int noExamples = originalExampleSet.size(); + int noSpecial = originalExampleSet.getAttributes().specialSize(); + int noRegular = originalExampleSet.getAttributes().size(); + String infoTextBegin = I18N.getGUILabel("data_view.filter_result_begin.label"); + String infoTextExample = I18N.getGUILabel( + noExamples == 1 ? "data_view.filter_result_example.label" : "data_view.filter_result_examples.label", noExamples); + String infoTextSpecial = I18N.getGUILabel( + noSpecial == 1 ? "data_view.filter_result_special.label" : "data_view.filter_result_specials.label", noSpecial); + String infoTextRegular = I18N.getGUILabel( + noRegular == 1 ? "data_view.filter_result_regular.label" : "data_view.filter_result_regulars.label", noRegular); + JLabel generalInfo = new JLabel(infoTextBegin + infoTextExample + infoTextSpecial + infoTextRegular); + final Border emptyBorder = BorderFactory.createEmptyBorder(6, 10, 6, 0); + generalInfo.setBorder(emptyBorder); + setExampleSet(exampleSet); + if (!dataTable.canShowAllRows()) { + // if this happens there are too many rows to be displayed by swing because its an int overflow. Adding information for the user + final JLabel tooManyRowsLabel = new ResourceLabel("datatable.too_many_rows"); + tooManyRowsLabel.setBorder(emptyBorder); + JPanel panel = new JPanel(new GridBagLayout()); + panel.setOpaque(false); + GridBagConstraints panelGbc = new GridBagConstraints(); + panelGbc.gridx = 0; + panelGbc.gridy = 0; + panelGbc.weightx = 1; + panelGbc.anchor = GridBagConstraints.WEST; + panel.add(tooManyRowsLabel, panelGbc); + panelGbc.gridy++; + panel.add(generalInfo, panelGbc); + add(panel, BorderLayout.SOUTH); + } else { + add(generalInfo, BorderLayout.SOUTH); + } + dataTable.unpack(); } @@ -179,31 +198,6 @@ public void setExampleSet(ExampleSet exampleSet) { dataTable.setExampleSet(exampleSet); } - private void updateFilter(String conditionName) { - ExampleSet filteredExampleSet = originalExampleSet; - try { - Condition condition = ConditionedExampleSet.createCondition(conditionName, originalExampleSet, null); - filteredExampleSet = new ConditionedExampleSet(originalExampleSet, condition); - } catch (ConditionCreationException ex) { - originalExampleSet.getLog().logError( - "Cannot create condition '" + conditionName + "' for filtered data view: " + ex.getMessage() - + ". Using original data set view..."); - filteredExampleSet = originalExampleSet; - } catch (ExpressionEvaluationException ex) { - originalExampleSet.getLog().logError( - "Cannot create condition '" + conditionName + "' for filtered data view: " + ex.getMessage() - + ". Using original data set view..."); - filteredExampleSet = originalExampleSet; - } - updateFilterCounter(filteredExampleSet); - setExampleSet(filteredExampleSet); - } - - private void updateFilterCounter(ExampleSet filteredExampleSet) { - filterLabel.setText(I18N.getMessage(I18N.getGUIBundle(), "gui.label.data_view.filter.label", - filteredExampleSet.size(), originalExampleSet.size())); - } - @Override public void prepareReporting() { dataTable.prepareReporting(); @@ -244,4 +238,25 @@ public boolean isFirstColumnHeader() { return false; } + private void updateFilter(String conditionName) { + ActionStatisticsCollector.INSTANCE.log(ActionStatisticsCollector.TYPE_EXAMPLESET_VIEW_FILTER, ActionStatisticsCollector.VALUE_FILTER_SELECTED, conditionName); + + ExampleSet filteredExampleSet; + try { + Condition condition = ConditionedExampleSet.createCondition(conditionName, originalExampleSet, null); + filteredExampleSet = new ConditionedExampleSet(originalExampleSet, condition); + } catch (ConditionCreationException | ExpressionEvaluationException ex) { + originalExampleSet.getLog().logError( + "Cannot create condition '" + conditionName + "' for filtered data view: " + ex.getMessage() + + ". Using original data set view..."); + filteredExampleSet = originalExampleSet; + } + updateFilterCounter(filteredExampleSet); + setExampleSet(filteredExampleSet); + } + + private void updateFilterCounter(ExampleSet filteredExampleSet) { + filterLabel.setText(I18N.getGUILabel("data_view.filter.label", filteredExampleSet.size(), originalExampleSet.size())); + } + } diff --git a/src/main/java/com/rapidminer/gui/viewer/DataViewerTable.java b/src/main/java/com/rapidminer/gui/viewer/DataViewerTable.java index 972c1375b..a4eb25e33 100644 --- a/src/main/java/com/rapidminer/gui/viewer/DataViewerTable.java +++ b/src/main/java/com/rapidminer/gui/viewer/DataViewerTable.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.viewer; import java.awt.Color; @@ -27,7 +27,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; - import javax.swing.table.JTableHeader; import com.rapidminer.example.Attribute; @@ -58,6 +57,9 @@ public class DataViewerTable extends ExtendedJTable { private static final int MAXIMAL_CONTENT_LENGTH = 200; + + protected static final int MAX_ROW_HEIGHT = 30; + protected static final int MIN_ROW_HEIGHT = 25; private static final long serialVersionUID = 5535239693801265693L; @@ -80,7 +82,6 @@ public DataViewerTable() { setAutoResizeMode(AUTO_RESIZE_OFF); setFixFirstColumnForRearranging(true); installToolTip(); - setRowHeight(getRowHeight() + 5); // handles the highlighting of the currently hovered row setRowHighlighting(true); @@ -154,6 +155,9 @@ public Color getCellColor(int row, int column) { setCutOnLineBreak(true); setMaximalTextLength(MAXIMAL_CONTENT_LENGTH); + final int size = exampleSet.size(); + setRowHeight(calcRowHeight(MAX_ROW_HEIGHT, MIN_ROW_HEIGHT, size)); + ProgressThread createStatsThread = new ProgressThread("update_result_statistics") { @Override @@ -186,7 +190,18 @@ public void run() { } - /** This method ensures that the correct tool tip for the current column is delivered. */ + private static int calcRowHeight(int maxRowHeight, int minRowHeight, int count) { + if (count == 0) { + return maxRowHeight; + } + final int f = Integer.MAX_VALUE / count; + final int m = Math.max(minRowHeight, f); + return Math.min(maxRowHeight, m); + } + + /** + * This method ensures that the correct tool tip for the current column is delivered. + */ @Override protected JTableHeader createDefaultTableHeader() { JTableHeader header = new JTableHeader(columnModel) { diff --git a/src/main/java/com/rapidminer/gui/viewer/collection/CollectionTreeCellRenderer.java b/src/main/java/com/rapidminer/gui/viewer/collection/CollectionTreeCellRenderer.java index f9d069c96..24be4f5f8 100644 --- a/src/main/java/com/rapidminer/gui/viewer/collection/CollectionTreeCellRenderer.java +++ b/src/main/java/com/rapidminer/gui/viewer/collection/CollectionTreeCellRenderer.java @@ -21,7 +21,6 @@ import java.awt.Component; import java.util.HashMap; import java.util.Map; - import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JLabel; @@ -46,7 +45,7 @@ public class CollectionTreeCellRenderer extends DefaultTreeCellRenderer { private final Icon ICON_FOLDER_OPEN = SwingTools.createIcon("16/folder_open.png"); private final Icon ICON_FOLDER_CLOSED = SwingTools.createIcon("16/folder.png"); - private final Map childNames = new HashMap(); + private final Map childNames = new HashMap<>(); public CollectionTreeCellRenderer(IOObject collection) { if (collection instanceof MetaModel) { @@ -70,17 +69,15 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean if (name == null) { name = ro.getName(); } - String source = ro.getSource() != null ? " (" + ro.getSource() + ")" : ""; - label.setText("" + name + source + ""); + label.setText("" + name + ""); if (ro instanceof IOObjectCollection) { label.setIcon(expanded ? ICON_FOLDER_OPEN : ICON_FOLDER_CLOSED); } else { Icon resultIcon = ro.getResultIcon(); label.setIcon(resultIcon); } - } else if (ioobject instanceof IOObject) { - IOObject ioo = ioobject; - label.setText(ioo.getClass().getSimpleName()); + } else if (ioobject != null) { + label.setText(ioobject.getClass().getSimpleName()); } return label; } diff --git a/src/main/java/com/rapidminer/io/process/ProcessLayoutXMLFilter.java b/src/main/java/com/rapidminer/io/process/ProcessLayoutXMLFilter.java index 9da092626..263cf313c 100644 --- a/src/main/java/com/rapidminer/io/process/ProcessLayoutXMLFilter.java +++ b/src/main/java/com/rapidminer/io/process/ProcessLayoutXMLFilter.java @@ -285,12 +285,8 @@ public static int lookupPortSpacing(Port port) { PortSpacingWrapper wrapper = (PortSpacingWrapper) operator.getUserData(KEY_PORT_SPACING); if (wrapper != null) { Map spacings = wrapper.get(); - if (spacings.containsKey(port)) { - return spacings.get(port); - } else { - // no spacing stored for this particular port - return 0; - } + // get spacing or no spacing + return spacings.getOrDefault(port, 0); } else { // no spacing data available return 0; diff --git a/src/main/java/com/rapidminer/io/process/ProcessOriginProcessXMLFilter.java b/src/main/java/com/rapidminer/io/process/ProcessOriginProcessXMLFilter.java index d04be51ca..27892d977 100644 --- a/src/main/java/com/rapidminer/io/process/ProcessOriginProcessXMLFilter.java +++ b/src/main/java/com/rapidminer/io/process/ProcessOriginProcessXMLFilter.java @@ -56,7 +56,7 @@ public enum ProcessOriginState implements UserData { GENERATED_AUTOMODEL("am_gen_"), /** - * Exported by Auto Model (used opened it) + * Exported by Auto Model (user opened it) * * @since 9.0.0 */ @@ -109,7 +109,14 @@ public enum ProcessOriginState implements UserData { * * @since 9.0.0 */ - GENERATED_TUTORIAL("tutorial_"); + GENERATED_TUTORIAL("tutorial_"), + + /** + * Exported by Auto Model in the Cloud (user opened it) + * + * @since 9.0.2 + */ + EXPORTED_AUTOMODEL_CLOUD("amc_exp_"); private String prefix; diff --git a/src/main/java/com/rapidminer/operator/AbstractIOObject.java b/src/main/java/com/rapidminer/operator/AbstractIOObject.java index 1c5a04db8..64bf3e52b 100644 --- a/src/main/java/com/rapidminer/operator/AbstractIOObject.java +++ b/src/main/java/com/rapidminer/operator/AbstractIOObject.java @@ -1,249 +1,240 @@ -/** - * Copyright (C) 2001-2018 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.operator; - -import com.rapidminer.operator.ports.OutputPort; -import com.rapidminer.operator.ports.ProcessingStep; -import com.rapidminer.tools.LogService; -import com.rapidminer.tools.LoggingHandler; -import com.rapidminer.tools.XMLSerialization; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.OutputStream; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.zip.GZIPInputStream; - - -/** - * This is an abstract superclass for all IOObject. It provides basic implementations for all - * methods of the IOObject interface. In addition, it also provides static methods which can be used - * for reading IOObjects from XML strings and input streams / files containing the XML - * serialization. - * - * @author Ingo Mierswa - */ -public abstract class AbstractIOObject implements IOObject { - - private static final long serialVersionUID = 7131412868947165460L; - - /** The source of this IOObect. Might be null. */ - private String source = null; - - /** The current working operator. */ - private transient LoggingHandler loggingHandler; - - private transient LinkedList processingHistory = new LinkedList<>(); - - private transient HashMap userData = new HashMap<>(); - - /** Sets the source of this IOObject. */ - @Override - public void setSource(String sourceName) { - this.source = sourceName; - } - - /** Returns the source of this IOObject (might return null if the source is unknown). */ - @Override - public String getSource() { - return source; - } - - @Override - public void appendOperatorToHistory(Operator operator, OutputPort port) { - if (processingHistory == null) { - processingHistory = new LinkedList<>(); - if (operator.getProcess() != null) { - processingHistory.add(new ProcessingStep(operator, port)); - } - } - ProcessingStep newStep = new ProcessingStep(operator, port); - if (operator.getProcess() != null && (processingHistory.isEmpty() || !processingHistory.getLast().equals(newStep))) { - processingHistory.add(newStep); - } - } - - @Override - public List getProcessingHistory() { - if (processingHistory == null) { - processingHistory = new LinkedList<>(); - } - return processingHistory; - } - - /** - * Gets the logging associated with the operator currently working on this IOObject or the - * global log service if no operator was set. - */ - @SuppressWarnings("deprecation") - @Override - public LoggingHandler getLog() { - if (this.loggingHandler != null) { - return this.loggingHandler; - } else { - return LogService.getGlobal(); - } - } - - /** - * Sets the current working operator, i.e. the operator which is currently working on this - * IOObject. This might be used for example for logging. - */ - @Override - public void setLoggingHandler(LoggingHandler loggingHandler) { - this.loggingHandler = loggingHandler; - } - - /** - * Returns not a copy but the very same object. This is ok for IOObjects which cannot be altered - * after creation. However, IOObjects which might be changed (e.g. - * {@link com.rapidminer.example.ExampleSet}s) should overwrite this method and return a proper - * copy. - */ - @Override - public IOObject copy() { - return this; - } - - /** - * Initializes the writing of this object. This method is invoked before the actual writing is - * performed. The default implementation does nothing. - * - * This method should also be used for clean up processes which should be performed before the - * actual writing is done. For example, models might decide to keep the example set information - * directly after learning (e.g. for visualization reasons) but not to write them down. Please - * note that all fields will be written into files unless they are set to null in this method or - * they are marked as transient. - */ - protected void initWriting() {} - - /** - * Just serializes this object with help of a {@link XMLSerialization}. Initializes - * {@link #initWriting()} before the actual writing is performed. - */ - @Override - public final void write(OutputStream out) throws IOException { - initWriting(); - XMLSerialization.getXMLSerialization().writeXML(this, out); - } - - @Override - public Object getUserData(String key) { - if (userData == null) { - userData = new HashMap<>(); - } - return userData.get(key); - } - - @Override - public Object setUserData(String key, Object value) { - return userData.put(key, value); - } - - /** - * Deserializes an IOObect from the given XML stream. TODO: Make private and remove deprecated - * annotation - * - * @throws IOException - * if any IO error occurs. - * @throws IllegalStateException - * if {@link XMLSerialization#init(ClassLoader)} has never been called. - * @deprecated Use {@link #read(InputStreamProvider, String)} to be able to read all formats - * (xml zipped/not zipped and binary) - */ - @Deprecated - public static IOObject read(InputStream in) throws IOException { - final XMLSerialization serializer = XMLSerialization.getXMLSerialization(); - if (serializer == null) { - throw new IllegalStateException( - "XMLSerialization not initialized, please invoke XMLSerialization.init(ClassLoader) before using this method."); - } - return (IOObject) serializer.fromXML(in); - } - - /** This interface is needed since we must reset the stream in case of an exception. */ - public static interface InputStreamProvider { - - public InputStream getInputStream() throws IOException; - } - - public static IOObject read(final File file) throws IOException { - return read(new InputStreamProvider() { - - @Override - public InputStream getInputStream() throws IOException { - return new FileInputStream(file); - } - }); - } - - public static IOObject read(final byte[] buf) throws IOException { - return read(new InputStreamProvider() { - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(buf); - } - }); - } - - public static IOObject read(InputStreamProvider inProvider) throws IOException { - ObjectInputStream objectIn = null; - try { - // try if the object was written as a serializable object - objectIn = new ObjectInputStream(inProvider.getInputStream()); - IOObject object = (IOObject) objectIn.readObject(); - objectIn.close(); // done in finally - return object; - } catch (Exception e) { - // if not serialized, then try the usual serialization (xml) - InputStream in = null; - try { - in = new GZIPInputStream(inProvider.getInputStream()); - } catch (IOException e1) { - // do nothing and simply use the given input stream - in = inProvider.getInputStream(); - } - try { - return read(in); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e1) { - } - } - } - } finally { - if (objectIn != null) { - try { - objectIn.close(); - } catch (IOException e) { - } - } - } - } - -} +/** + * Copyright (C) 2001-2018 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.operator; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.zip.GZIPInputStream; + +import com.rapidminer.operator.ports.OutputPort; +import com.rapidminer.operator.ports.ProcessingStep; +import com.rapidminer.tools.LogService; +import com.rapidminer.tools.LoggingHandler; +import com.rapidminer.tools.XMLSerialization; + + +/** + * This is an abstract superclass for all IOObject. It provides basic implementations for all + * methods of the IOObject interface. In addition, it also provides static methods which can be used + * for reading IOObjects from XML strings and input streams / files containing the XML + * serialization. + * + * @author Ingo Mierswa + */ +public abstract class AbstractIOObject implements IOObject { + + private static final long serialVersionUID = 7131412868947165460L; + + /** The source of this IOObect. Might be null. */ + private String source = null; + + /** The current working operator. */ + private transient LoggingHandler loggingHandler; + + private transient LinkedList processingHistory = new LinkedList<>(); + + private transient HashMap userData = new HashMap<>(); + + /** Sets the source of this IOObject. */ + @Override + public void setSource(String sourceName) { + this.source = sourceName; + } + + /** Returns the source of this IOObject (might return null if the source is unknown). */ + @Override + public String getSource() { + return source; + } + + @Override + public void appendOperatorToHistory(Operator operator, OutputPort port) { + if (operator.getProcess() == null) { + return; + } + if (processingHistory == null) { + processingHistory = new LinkedList<>(); + } + ProcessingStep newStep = new ProcessingStep(operator, port); + if (processingHistory.isEmpty() || !processingHistory.getLast().equals(newStep)) { + processingHistory.add(newStep); + } + } + + @Override + public List getProcessingHistory() { + if (processingHistory == null) { + processingHistory = new LinkedList<>(); + } + return processingHistory; + } + + /** + * Gets the logging associated with the operator currently working on this IOObject or the + * global log service if no operator was set. + */ + @SuppressWarnings("deprecation") + @Override + public LoggingHandler getLog() { + if (this.loggingHandler != null) { + return this.loggingHandler; + } else { + return LogService.getGlobal(); + } + } + + /** + * Sets the current working operator, i.e. the operator which is currently working on this + * IOObject. This might be used for example for logging. + */ + @Override + public void setLoggingHandler(LoggingHandler loggingHandler) { + this.loggingHandler = loggingHandler; + } + + /** + * Returns not a copy but the very same object. This is ok for IOObjects which cannot be altered + * after creation. However, IOObjects which might be changed (e.g. + * {@link com.rapidminer.example.ExampleSet}s) should overwrite this method and return a proper + * copy. + */ + @Override + public IOObject copy() { + return this; + } + + /** + * Initializes the writing of this object. This method is invoked before the actual writing is + * performed. The default implementation does nothing. + * + * This method should also be used for clean up processes which should be performed before the + * actual writing is done. For example, models might decide to keep the example set information + * directly after learning (e.g. for visualization reasons) but not to write them down. Please + * note that all fields will be written into files unless they are set to null in this method or + * they are marked as transient. + */ + protected void initWriting() {} + + /** + * Just serializes this object with help of a {@link XMLSerialization}. Initializes + * {@link #initWriting()} before the actual writing is performed. + */ + @Override + public final void write(OutputStream out) throws IOException { + initWriting(); + XMLSerialization.getXMLSerialization().writeXML(this, out); + } + + @Override + public Object getUserData(String key) { + if (userData == null) { + userData = new HashMap<>(); + } + return userData.get(key); + } + + @Override + public Object setUserData(String key, Object value) { + if (userData == null) { + userData = new HashMap<>(); + } + return userData.put(key, value); + } + + /** + * Deserializes an IOObect from the given XML stream. TODO: Make private and remove deprecated + * annotation + * + * @throws IOException + * if any IO error occurs. + * @throws IllegalStateException + * if {@link XMLSerialization#init(ClassLoader)} has never been called. + * @deprecated Use {@link #read(InputStreamProvider)} to be able to read all formats + * (xml zipped/not zipped and binary) + */ + @Deprecated + public static IOObject read(InputStream in) throws IOException { + final XMLSerialization serializer = XMLSerialization.getXMLSerialization(); + if (serializer == null) { + throw new IllegalStateException( + "XMLSerialization not initialized, please invoke XMLSerialization.init(ClassLoader) before using this method."); + } + return (IOObject) serializer.fromXML(in); + } + + /** This interface is needed since we must reset the stream in case of an exception. */ + public static interface InputStreamProvider { + + public InputStream getInputStream() throws IOException; + } + + public static IOObject read(final File file) throws IOException { + return read(() -> new FileInputStream(file)); + } + + public static IOObject read(final byte[] buf) throws IOException { + return read(() -> new ByteArrayInputStream(buf)); + } + + public static IOObject read(InputStreamProvider inProvider) throws IOException { + ObjectInputStream objectIn = null; + try { + // try if the object was written as a serializable object + objectIn = new ObjectInputStream(inProvider.getInputStream()); + IOObject object = (IOObject) objectIn.readObject(); + objectIn.close(); // done in finally + return object; + } catch (Exception e) { + // if not serialized, then try the usual serialization (xml) + InputStream in = null; + try { + in = new GZIPInputStream(inProvider.getInputStream()); + } catch (IOException e1) { + // do nothing and simply use the given input stream + in = inProvider.getInputStream(); + } + try { + return read(in); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e1) { + } + } + } + } finally { + if (objectIn != null) { + try { + objectIn.close(); + } catch (IOException e) { + } + } + } + } + +} diff --git a/src/main/java/com/rapidminer/operator/Operator.java b/src/main/java/com/rapidminer/operator/Operator.java index 3a05dd5e8..f1492428b 100644 --- a/src/main/java/com/rapidminer/operator/Operator.java +++ b/src/main/java/com/rapidminer/operator/Operator.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.operator; import java.io.File; @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; - import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; @@ -58,6 +57,7 @@ import com.rapidminer.operator.annotation.ResourceConsumer; import com.rapidminer.operator.annotation.ResourceConsumptionEstimator; import com.rapidminer.operator.nio.model.AbstractDataResultSetReader; +import com.rapidminer.operator.ports.DeliveringPortManager; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.InputPorts; import com.rapidminer.operator.ports.OutputPort; @@ -506,7 +506,7 @@ public final String rename(String newName) { * Sets the user specified comment for this operator. * * @deprecated use - * {@link com.rapidminer.io.process.GUIProcessXMLFilter#addOperatorAnnotation(Operator, com.rapidminer.gui.flow.processrendering.annotations.WorkflowAnnotation)} + * {@link com.rapidminer.io.process.GUIProcessXMLFilter#addOperatorAnnotation(com.rapidminer.gui.flow.processrendering.annotations.model.OperatorAnnotation)} * instead! Calling this method will do nothing anymore. */ @Deprecated @@ -518,8 +518,8 @@ public void setUserDescription(String description) { /** * Looks up {@link UserData} entries. Returns null if key is unknown. * - * @param The - * key of the user data. + * @param key + * The key of the user data. * @return The user data. */ public UserData getUserData(String key) { @@ -553,7 +553,7 @@ public void setUserData(String key, UserData data) { * The user specified comment for this operator. * * @deprecated use - * {@link com.rapidminer.io.processGUIProcessXMLFilter#lookupOperatorAnnotations(Operator)} + * {@link com.rapidminer.io.process.GUIProcessXMLFilter#lookupOperatorAnnotations(Operator)} * instead! This method will always return {@code null}. */ @Deprecated @@ -679,7 +679,7 @@ public Operator cloneOperator(String name, boolean forParallelExecution) { throw new RuntimeException("Can not create clone of operator '" + getName(), e); } clone.setName(getName()); - clone.breakPoint = new boolean[] { breakPoint[0], breakPoint[1] }; + clone.breakPoint = new boolean[]{breakPoint[0], breakPoint[1]}; clone.enabled = enabled; clone.expanded = expanded; @@ -870,14 +870,14 @@ public int checkProperties() { if (type.getDefaultValue() == null && !parameterSet) { addError(new SimpleProcessSetupError(Severity.ERROR, portOwner, Collections.singletonList(new ParameterSettingQuickFix(this, type.getKey())), - "undefined_parameter", new Object[] { type.getKey().replace('_', ' ') })); + "undefined_parameter", new Object[]{type.getKey().replace('_', ' ')})); errorCount++; } else if (type instanceof ParameterTypeAttribute && parameterSet) { try { if ("".equals(getParameter(type.getKey()))) { addError(new SimpleProcessSetupError(Severity.ERROR, portOwner, Collections.singletonList(new ParameterSettingQuickFix(this, type.getKey())), - "undefined_parameter", new Object[] { type.getKey().replace('_', ' ') })); + "undefined_parameter", new Object[]{type.getKey().replace('_', ' ')})); errorCount++; } } catch (UndefinedParameterError e) { @@ -892,19 +892,19 @@ public int checkProperties() { if (!value.startsWith( RepositoryLocation.REPOSITORY_PREFIX + RepositoryManager.SAMPLE_REPOSITORY_NAME)) { addError(new SimpleProcessSetupError(Severity.WARNING, portOwner, - Collections. emptyList(), "accessing_repository_by_name", - new Object[] { type.getKey().replace('_', ' '), value })); + Collections.emptyList(), "accessing_repository_by_name", + new Object[]{type.getKey().replace('_', ' '), value})); } } else if (value.startsWith(String.valueOf(RepositoryLocation.SEPARATOR))) { addError(new SimpleProcessSetupError(Severity.ERROR, portOwner, Collections.singletonList( new RelativizeRepositoryLocationQuickfix(this, type.getKey(), value)), "absolute_repository_location", - new Object[] { type.getKey().replace('_', ' '), value })); + new Object[]{type.getKey().replace('_', ' '), value})); } } - } else if(type instanceof ParameterTypeDateFormat) { + } else if (type instanceof ParameterTypeDateFormat) { Locale locale = Locale.getDefault(); try { int localeIndex; @@ -925,7 +925,7 @@ Collections. emptyList(), "accessing_repository_by_name", String value = getParameters().getParameterOrNull(type.getKey()); if (value != null && !ParameterTypeDate.isValidDate(value)) { addError(new SimpleProcessSetupError(Severity.WARNING, portOwner, "invalid_date_format", - new Object[] { type.getKey().replace('_', ' '), value })); + new Object[]{type.getKey().replace('_', ' '), value})); } } } @@ -943,7 +943,7 @@ public int checkDeprecations() { int deprecationCount = 0; if (deprecationString != null) { addError(new SimpleProcessSetupError(Severity.WARNING, portOwner, "deprecation", - new Object[] { getOperatorDescription().getName(), deprecationString })); + new Object[]{getOperatorDescription().getName(), deprecationString})); deprecationCount = 1; } return deprecationCount; @@ -1034,8 +1034,8 @@ public final void execute() throws OperatorException { } OperatorException operatorException = ((OperatorRuntimeException) e).toOperatorException(); if (!(operatorException instanceof UserError)) { - throw operatorException; - } + throw operatorException; + } UserError userError = (UserError) operatorException; if (userError.getOperator() == null) { userError.setOperator(this); @@ -1059,6 +1059,7 @@ public final void execute() throws OperatorException { ioObject.setSource(getName()); if (ioObject instanceof IOObjectCollection) { for (IOObject ioo : ((IOObjectCollection) ioObject).getObjects()) { + DeliveringPortManager.setLastDeliveringPort(ioo, outputPort); if (ioo.getSource() == null) { ioo.setSource(getName()); } @@ -1331,7 +1332,7 @@ public Parameters getParameters() { // if not loaded already: do now parameters = new Parameters(getParameterTypes()); parameters.addObserver(delegatingParameterObserver, false); - + makeDirtyOnUpdate(parameters); } return parameters; @@ -1534,7 +1535,8 @@ public java.awt.Color getParameterAsColor(String key) throws UndefinedParameterE * this method returns null. Operators should always use this method instead of directly using * the method {@link Process#resolveFileName(String)}. * - * @throws DirectoryCreationError + * @throws IOException + * @throws UserError */ @Override public InputStream getParameterAsInputStream(String key) throws IOException, UserError { @@ -1579,7 +1581,7 @@ public java.io.File getParameterAsFile(String key) throws UserError { * method returns null. Operators should always use this method instead of directly using the * method {@link Process#resolveFileName(String)}. * - * @throws DirectoryCreationError + * @throws UserError */ @Override public java.io.File getParameterAsFile(String key, boolean createMissingDirectories) throws UserError { @@ -1792,7 +1794,7 @@ public String getXML(boolean hideDefault, boolean onlyCoreElements) { } public static Operator createFromXML(Element element, Process targetProcess, - List unknownParameterInformation) throws XMLException { + List unknownParameterInformation) throws XMLException { return createFromXML(element, targetProcess, unknownParameterInformation, null); } @@ -1802,7 +1804,7 @@ public static Operator createFromXML(Element element, Process targetProcess, * changes. */ public static Operator createFromXML(Element element, Process process, - List unknownParameterInformation, ProgressListener l) throws XMLException { + List unknownParameterInformation, ProgressListener l) throws XMLException { XMLImporter importer = new XMLImporter(l); return importer.parseOperator(element, XMLImporter.CURRENT_VERSION, process, unknownParameterInformation); } @@ -1813,8 +1815,8 @@ public static Operator createFromXML(Element element, Process process, * been created from this version. See {@link XMLImporter#VERSION_RM_5} for details. */ public static Operator createFromXML(Element element, Process process, - List unknownParameterInformation, ProgressListener progressListener, - VersionNumber originatingVersion) throws XMLException { + List unknownParameterInformation, ProgressListener progressListener, + VersionNumber originatingVersion) throws XMLException { XMLImporter importer = new XMLImporter(progressListener); return importer.parseOperator(element, originatingVersion, process, unknownParameterInformation); } @@ -1997,7 +1999,7 @@ public String createProcessTree(int indent) { /** * Returns this operator's name and class. * - * @deprecated Use {@link #createMarkedProcessTree(int,String,Operator)} instead + * @deprecated Use {@link #createMarkedProcessTree(int, String, Operator)} instead */ @Deprecated public String createMarkedExperimentTree(int indent, String mark, Operator markOperator) { @@ -2012,30 +2014,30 @@ public String createMarkedProcessTree(int indent, String mark, Operator markOper /** * Returns this operator's name and class. * - * @deprecated Use {@link #createProcessTree(int,String,String,Operator,String)} instead + * @deprecated Use {@link #createProcessTree(int, String, String, Operator, String)} instead */ @Deprecated protected String createExperimentTree(int indent, String selfPrefix, String childPrefix, Operator markOperator, - String mark) { + String mark) { return createProcessTree(indent, selfPrefix, childPrefix, markOperator, mark); } /** Returns this operator's name and class. */ protected String createProcessTree(int indent, String selfPrefix, String childPrefix, Operator markOperator, - String mark) { + String mark) { return createProcessTreeEntry(indent, selfPrefix, childPrefix, markOperator, mark); } /** Returns this operator's name and class in a list. */ protected List createProcessTreeList(int indent, String selfPrefix, String childPrefix, Operator markOperator, - String mark) { + String mark) { List processTreeList = new LinkedList<>(); processTreeList.add(createProcessTreeEntry(indent, selfPrefix, childPrefix, markOperator, mark)); return processTreeList; } private String createProcessTreeEntry(int indent, String selfPrefix, String childPrefix, Operator markOperator, - String mark) { + String mark) { if (markOperator != null && getName().equals(markOperator.getName())) { return Tools.indent(indent - mark.length()) + mark + selfPrefix + getName() + "[" + applyCount + "]" + " (" + getOperatorClassName() + ")"; diff --git a/src/main/java/com/rapidminer/operator/ScriptingOperator.java b/src/main/java/com/rapidminer/operator/ScriptingOperator.java index 87e5a1d60..283ad2f10 100644 --- a/src/main/java/com/rapidminer/operator/ScriptingOperator.java +++ b/src/main/java/com/rapidminer/operator/ScriptingOperator.java @@ -105,13 +105,7 @@ public class ScriptingOperator extends Operator { */ private static class ConcurrentBindingDelegator extends Binding { - private final ThreadLocal binding = new ThreadLocal() { - - @Override - protected Binding initialValue() { - return new Binding(); - } - }; + private final ThreadLocal binding = ThreadLocal.withInitial(Binding::new); @Override public Object getVariable(String name) { @@ -216,7 +210,7 @@ protected void performAdditionalChecks() { public void doWork() throws OperatorException { String script = getParameterAsString(PARAMETER_SCRIPT); if (getParameterAsBoolean(PARAMETER_STANDARD_IMPORTS)) { - StringBuffer imports = new StringBuffer(); + StringBuilder imports = new StringBuilder(); imports.append("import com.rapidminer.example.*;\n"); imports.append("import com.rapidminer.example.set.*;\n"); imports.append("import com.rapidminer.example.table.*;\n"); @@ -234,11 +228,7 @@ public void doWork() throws OperatorException { // inside a loop to start many parsings at the same time Object lock; synchronized (LOCK_MAP) { - lock = LOCK_MAP.get(script); - if (lock == null) { - lock = new Object(); - LOCK_MAP.put(script, lock); - } + lock = LOCK_MAP.computeIfAbsent(script, s -> new Object()); } Script cachedScript; @@ -277,7 +267,7 @@ public void doWork() throws OperatorException { if (result instanceof Object[]) { outExtender.deliver(Arrays.asList((IOObject[]) result)); } else if (result instanceof List) { - List results = new LinkedList(); + List results = new LinkedList<>(); for (Object single : (List) result) { if (single instanceof IOObject) { results.add((IOObject) single); diff --git a/src/main/java/com/rapidminer/operator/clustering/clusterer/FastKMeans.java b/src/main/java/com/rapidminer/operator/clustering/clusterer/FastKMeans.java index e117e6d0d..08878f1d9 100644 --- a/src/main/java/com/rapidminer/operator/clustering/clusterer/FastKMeans.java +++ b/src/main/java/com/rapidminer/operator/clustering/clusterer/FastKMeans.java @@ -19,6 +19,7 @@ package com.rapidminer.operator.clustering.clusterer; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -30,6 +31,7 @@ import com.rapidminer.example.Tools; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.UserError; import com.rapidminer.operator.clustering.CentroidClusterModel; import com.rapidminer.operator.clustering.ClusterModel; @@ -64,7 +66,6 @@ public class FastKMeans extends RMAbstractClusterer { * initialization that are performed" */ public static final String PARAMETER_MAX_RUNS = "max_runs"; - boolean kpp = getParameterAsBoolean(KMeanspp.PARAMETER_USE_KPP); /** * The parameter name for "the maximal number of iterations performed for one run of the k @@ -87,6 +88,7 @@ public FastKMeans(OperatorDescription description) { @Override protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throws OperatorException { + boolean kpp = getParameterAsBoolean(KMeanspp.PARAMETER_USE_KPP) && getCompatibilityLevel().isAbove(KMeanspp.VERSION_KPP_NOT_WORKING); int k = getParameterAsInt(PARAMETER_K); int maxOptimizationSteps = getParameterAsInt(PARAMETER_MAX_OPTIMIZATION_STEPS); int maxRuns = getParameterAsInt(PARAMETER_MAX_RUNS); @@ -108,7 +110,7 @@ protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throw // extracting attribute names Attributes attributes = exampleSet.getAttributes(); - ArrayList attributeNames = new ArrayList(attributes.size()); + ArrayList attributeNames = new ArrayList<>(attributes.size()); for (Attribute attribute : attributes) { attributeNames.add(attribute.getName()); } @@ -125,7 +127,8 @@ protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throw // init centroids by assigning one single, unique example! int i = 0; if (kpp) { - KMeanspp kmpp = new KMeanspp(getOperatorDescription(), k, exampleSet, measure, generator); + KMeanspp kmpp = new KMeanspp(this, k, exampleSet, measure, generator); + int[] hilf = kmpp.getStart(); int i1 = 0; @@ -343,8 +346,8 @@ protected boolean handlesInfiniteValues() { public List getParameterTypes() { List types = super.getParameterTypes(); types.add(new ParameterTypeInt(PARAMETER_K, "The number of clusters which should be detected.", 2, Integer.MAX_VALUE, - 2, false)); - types.add(new ParameterTypeBoolean(KMeanspp.PARAMETER_USE_KPP, KMeanspp.SHORT_DESCRIPTION, false)); + 5, false)); + types.add(new ParameterTypeBoolean(KMeanspp.PARAMETER_USE_KPP, KMeanspp.SHORT_DESCRIPTION, true)); types.addAll(getMeasureParameterTypes()); types.add(new ParameterTypeInt(PARAMETER_MAX_RUNS, "The maximal number of runs of k-Means with random initialization that are performed.", 1, Integer.MAX_VALUE, @@ -359,4 +362,13 @@ public List getParameterTypes() { protected Map getMeasureParametersDefaults() { return Collections.singletonMap(DistanceMeasures.PARAMETER_MEASURE_TYPES, DistanceMeasures.NUMERICAL_MEASURES_TYPE); } + + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + OperatorVersion[] incompatibleVersions = super.getIncompatibleVersionChanges(); + OperatorVersion[] extendedIncompatibleVersions = Arrays.copyOf(incompatibleVersions, + incompatibleVersions.length + 1); + extendedIncompatibleVersions[incompatibleVersions.length] = KMeanspp.VERSION_KPP_NOT_WORKING; + return extendedIncompatibleVersions; + } } diff --git a/src/main/java/com/rapidminer/operator/clustering/clusterer/KMeans.java b/src/main/java/com/rapidminer/operator/clustering/clusterer/KMeans.java index 8f9f180bb..195b65ea9 100644 --- a/src/main/java/com/rapidminer/operator/clustering/clusterer/KMeans.java +++ b/src/main/java/com/rapidminer/operator/clustering/clusterer/KMeans.java @@ -125,7 +125,7 @@ protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throw // init centroids by assigning one single, unique example! int i = 0; if (kpp) { - KMeanspp kmpp = new KMeanspp(getOperatorDescription(), k, exampleSet, measure, generator); + KMeanspp kmpp = new KMeanspp(this, k, exampleSet, measure, generator); int[] hilf = kmpp.getStart(); int i1 = 0; diff --git a/src/main/java/com/rapidminer/operator/clustering/clusterer/KernelKMeans.java b/src/main/java/com/rapidminer/operator/clustering/clusterer/KernelKMeans.java index 9e220e79b..8d1fb908c 100644 --- a/src/main/java/com/rapidminer/operator/clustering/clusterer/KernelKMeans.java +++ b/src/main/java/com/rapidminer/operator/clustering/clusterer/KernelKMeans.java @@ -251,7 +251,7 @@ public List getParameterTypes() { types.add(new ParameterTypeBoolean(PARAMETER_USE_WEIGHTS, "Indicates if the weight attribute should be used.", false, false)); types.add(new ParameterTypeInt(PARAMETER_K, "The number of clusters which should be detected.", 2, Integer.MAX_VALUE, - 2, false)); + 5, false)); types.add(new ParameterTypeInt(PARAMETER_MAX_OPTIMIZATION_STEPS, "The maximal number of iterations performed for one run of k-Means.", 1, Integer.MAX_VALUE, 100, false)); diff --git a/src/main/java/com/rapidminer/operator/clustering/clusterer/XMeans.java b/src/main/java/com/rapidminer/operator/clustering/clusterer/XMeans.java index 26d9406dc..0d8fec0f7 100644 --- a/src/main/java/com/rapidminer/operator/clustering/clusterer/XMeans.java +++ b/src/main/java/com/rapidminer/operator/clustering/clusterer/XMeans.java @@ -22,9 +22,12 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang.ArrayUtils; + import com.rapidminer.example.ExampleSet; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.clustering.CentroidClusterModel; import com.rapidminer.operator.clustering.ClusterModel; import com.rapidminer.parameter.ParameterType; @@ -68,6 +71,18 @@ public class XMeans extends RMAbstractClusterer { */ public static final String PARAMETER_MAX_OPTIMIZATION_STEPS = "max_optimization_steps"; + + /** + * After this version the Operator parameters are propagated to the internal operators. There is also a change in + * the behaviour of the internal operators, that affects the final result. + */ + public static final OperatorVersion VERSION_9_0_0_LABEL_ROLE_BUG = new OperatorVersion(9, 0, 0); + + /** + * After this version the points counted twice bug that was introduced with the {@link #VERSION_9_0_0_LABEL_ROLE_BUG} fix should no longer appear. + */ + public static final OperatorVersion VERSION_9_1_0_POINTS_COUNTED_TWICE_BUG = new OperatorVersion(9, 0, 3); + OperatorDescription Description = null; public XMeans(OperatorDescription description) { @@ -87,9 +102,18 @@ protected ClusterModel generateInternalClusterModel(ExampleSet eSet) throws Oper int maxOptimizationSteps = getParameterAsInt(PARAMETER_MAX_OPTIMIZATION_STEPS); int maxRuns = getParameterAsInt(PARAMETER_MAX_RUNS); + XMeansCore xm = new XMeansCore(eSet, k_min, k_max, kpp, maxOptimizationSteps, maxRuns, Description, measure, fast_k); + + xm.setCompatibilityLevel(this.getCompatibilityLevel()); + + if (this.getCompatibilityLevel().isAbove(VERSION_9_0_0_LABEL_ROLE_BUG)) { + xm.setParameter(RMAbstractClusterer.PARAMETER_ADD_AS_LABEL, getParameter(RMAbstractClusterer.PARAMETER_ADD_AS_LABEL)); + xm.setParameter(RMAbstractClusterer.PARAMETER_ADD_CLUSTER_ATTRIBUTE, getParameter(RMAbstractClusterer.PARAMETER_ADD_CLUSTER_ATTRIBUTE)); + } xm.setExecutingOperator(this); + return xm.doXMean(); } @@ -112,11 +136,11 @@ protected boolean handlesInfiniteValues() { public List getParameterTypes() { List types = super.getParameterTypes(); types.add(new ParameterTypeInt(PARAMETER_K_Min, "The minimal number of clusters which should be detected.", 2, - Integer.MAX_VALUE, 2, false)); + Integer.MAX_VALUE, 3, false)); types.add(new ParameterTypeInt(PARAMETER_K_Max, "The maximal number of clusters which should be detected.", 3, Integer.MAX_VALUE, 60, false)); - ParameterType type = new ParameterTypeBoolean(KMeanspp.PARAMETER_USE_KPP, KMeanspp.SHORT_DESCRIPTION, false); + ParameterType type = new ParameterTypeBoolean(KMeanspp.PARAMETER_USE_KPP, KMeanspp.SHORT_DESCRIPTION, true); type.setExpert(false); types.add(type); @@ -136,4 +160,10 @@ public List getParameterTypes() { protected Map getMeasureParametersDefaults() { return Collections.singletonMap(DistanceMeasures.PARAMETER_MEASURE_TYPES, DistanceMeasures.NUMERICAL_MEASURES_TYPE); } + + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + return (OperatorVersion[]) ArrayUtils.addAll(super.getIncompatibleVersionChanges(), + new OperatorVersion[]{VERSION_9_0_0_LABEL_ROLE_BUG, KMeanspp.VERSION_KPP_NOT_WORKING, VERSION_9_1_0_POINTS_COUNTED_TWICE_BUG}); + } } diff --git a/src/main/java/com/rapidminer/operator/concurrency/internal/ParallelOperatorChain.java b/src/main/java/com/rapidminer/operator/concurrency/internal/ParallelOperatorChain.java index bf75f3467..85de226b2 100644 --- a/src/main/java/com/rapidminer/operator/concurrency/internal/ParallelOperatorChain.java +++ b/src/main/java/com/rapidminer/operator/concurrency/internal/ParallelOperatorChain.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import com.rapidminer.RapidMiner; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.utils.ExampleSets; import com.rapidminer.operator.ExecutionUnit; @@ -34,7 +33,7 @@ import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeBoolean; import com.rapidminer.parameter.UndefinedParameterError; -import com.rapidminer.tools.ParameterService; +import com.rapidminer.studio.internal.Resources; /** @@ -64,7 +63,7 @@ public ParallelOperatorChain(OperatorDescription description, String... subproce * @return */ protected boolean checkParallelizability() { - if(Integer.parseInt(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS)) == 1) { + if(Resources.getConcurrencyContext(this).getParallelism() == 1) { return false; } diff --git a/src/main/java/com/rapidminer/operator/features/PopulationPlotter.java b/src/main/java/com/rapidminer/operator/features/PopulationPlotter.java index f49ddc207..786a9d8d7 100644 --- a/src/main/java/com/rapidminer/operator/features/PopulationPlotter.java +++ b/src/main/java/com/rapidminer/operator/features/PopulationPlotter.java @@ -23,6 +23,7 @@ import com.rapidminer.datatable.SimpleDataTableRow; import com.rapidminer.example.Attribute; import com.rapidminer.example.ExampleSet; +import com.rapidminer.gui.ApplicationFrame; import com.rapidminer.gui.plotter.ScatterPlotter; import com.rapidminer.gui.plotter.SimplePlotterDialog; import com.rapidminer.gui.tools.ExtendedJScrollPane; @@ -225,7 +226,7 @@ public void startVisualization(Object id) { frame.getContentPane().add(new ExtendedJScrollPane(visualizationComponent), BorderLayout.CENTER); frame.setSize(600, 400); - frame.setLocationRelativeTo(null); + frame.setLocationRelativeTo(ApplicationFrame.getApplicationFrame()); frame.setVisible(true); } } diff --git a/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSetUnificator.java b/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSetUnificator.java index 275675f95..b41d2e97f 100644 --- a/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSetUnificator.java +++ b/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSetUnificator.java @@ -18,69 +18,27 @@ */ package com.rapidminer.operator.learner.associations; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.ports.PortPairExtender; import com.rapidminer.operator.ports.metadata.MetaData; -import com.rapidminer.tools.container.Tupel; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; /** * This operator compares a number of FrequentItemSet sets and removes every not unique * FrequentItemSet. - * - * @author Sebastian Land + * + * @author Sebastian Land, Jonas Wilms-Pfau */ public class FrequentItemSetUnificator extends Operator { - private static class FrequencyIgnoringSetComparator implements Comparator { - - @Override - public int compare(FrequentItemSet o1, FrequentItemSet o2) { - // compare size - Collection items = o1.getItems(); - Collection hisItems = o2.getItems(); - if (items.size() < hisItems.size()) { - return -1; - } else if (items.size() > hisItems.size()) { - return 1; - } else { - // compare items - Iterator iterator = hisItems.iterator(); - for (Item myCurrentItem : items) { - int relation = myCurrentItem.toString().compareTo(iterator.next().toString()); - if (relation != 0) { - return relation; - } - } - // equal sets - return 0; - } - } - - } - - private static class TupelComparator implements Comparator>> { - - @Override - public int compare(Tupel> o1, - Tupel> o2) { - FrequencyIgnoringSetComparator comparator = new FrequencyIgnoringSetComparator(); - return comparator.compare(o1.getFirst(), o2.getFirst()); - } - - } - private PortPairExtender portExtender = new PortPairExtender("frequent item sets", getInputPorts(), getOutputPorts(), new MetaData(FrequentItemSets.class)); @@ -90,63 +48,72 @@ public FrequentItemSetUnificator(OperatorDescription description) { portExtender.ensureMinimumNumberOfPorts(2); getTransformer().addRule(portExtender.makePassThroughRule()); portExtender.start(); - } @Override public void doWork() throws OperatorException { - List sets = portExtender.getData(FrequentItemSets.class); - for (FrequentItemSets set : sets) { - set.sortSets(new FrequencyIgnoringSetComparator()); - sets.add(set); - } + List allSets = portExtender.getData(FrequentItemSets.class); - ArrayList>> iteratorTupels = new ArrayList>>( - 2); - for (FrequentItemSets classSets : sets) { - Iterator iterator = classSets.iterator(); - iteratorTupels.add(new Tupel>(iterator.next(), iterator)); - } - // running through iterators - while (haveNext(iteratorTupels)) { - // filling set to test if all frequent item sets are equal - Set currentSets = new TreeSet(new FrequencyIgnoringSetComparator()); - for (Tupel> tupel : iteratorTupels) { - currentSets.add(tupel.getFirst()); - } - if (currentSets.size() == 1) { - // not unique: deletion - ArrayList>> newTupels = new ArrayList>>( - 2); - for (Tupel> tupel : iteratorTupels) { - Iterator currentIterator = tupel.getSecond(); - currentIterator.remove(); - if (currentIterator.hasNext()) { - newTupels.add(new Tupel>(currentIterator.next(), - currentIterator)); - } - } - iteratorTupels = newTupels; - } else { - // unique: no deletion but forward smallest iterator - Collections.sort(iteratorTupels, new TupelComparator()); - Iterator currentIterator = iteratorTupels.get(0).getSecond(); - if (currentIterator.hasNext()) { - iteratorTupels.add(new Tupel>(currentIterator.next(), - currentIterator)); + // Item names only of the duplicates + Set> duplicates = findDuplicates(allSets); + + // Store modified sets as results + List results = new ArrayList<>(); + + // Remove duplicates + for (FrequentItemSets sets : allSets) { + FrequentItemSets clonedSet = (FrequentItemSets) sets.clone(); + Iterator iterator = clonedSet.iterator(); + while (iterator.hasNext()) { + if (duplicates.contains(getItemNames(iterator.next()))) { + iterator.remove(); } - iteratorTupels.remove(0); } + results.add(clonedSet); } - portExtender.deliver(sets); + portExtender.deliver(results); } - private boolean haveNext(ArrayList>> iterators) { - boolean hasNext = iterators.size() > 0; - for (Tupel> iterator : iterators) { - hasNext = hasNext || iterator.getSecond().hasNext(); + /** + * Returns the item names in a list, does not contain the frequency information + * + * @param set + * the set + * @return item names + * @since 9.0.2 + */ + private static List getItemNames(FrequentItemSet set) { + List setAsStrings = new ArrayList<>(set.getNumberOfItems()); + for (Item item : set.getItems()) { + setAsStrings.add(item.toString()); } - return hasNext; + return setAsStrings; } + + /** + * Find duplicates in the item sets + * + * @param allItemSets + * all {@link FrequentItemSets} + * @return the names of the duplicated item sets + * @since 9.0.2 + */ + private static Set> findDuplicates(List allItemSets) { + Set> duplicates = new HashSet<>(); + Set> all = new HashSet<>(); + + // Find duplicates + for (FrequentItemSets sets : allItemSets) { + for (FrequentItemSet set : sets) { + List itemNames = getItemNames(set); + if (!all.add(itemNames)) { + duplicates.add(itemNames); + } + } + } + + return duplicates; + } + } diff --git a/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSets.java b/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSets.java index 941be521e..62e6d913c 100644 --- a/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSets.java +++ b/src/main/java/com/rapidminer/operator/learner/associations/FrequentItemSets.java @@ -18,21 +18,22 @@ */ package com.rapidminer.operator.learner.associations; -import com.rapidminer.operator.ResultObjectAdapter; -import com.rapidminer.tools.Tools; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; +import com.rapidminer.operator.IOObject; +import com.rapidminer.operator.ResultObjectAdapter; +import com.rapidminer.tools.Tools; + /** * Contains a collection of {@link FrequentItemSet}s. * * @author Sebastian Land, Ingo Mierswa */ -public class FrequentItemSets extends ResultObjectAdapter implements Iterable { +public class FrequentItemSets extends ResultObjectAdapter implements Iterable, Cloneable { private static final long serialVersionUID = -6195363961857170621L; @@ -46,7 +47,20 @@ public class FrequentItemSets extends ResultObjectAdapter implements Iterable(); + this.frequentSets = new ArrayList<>(); + } + + /** + * Clone constructor. + * @since 9.0.2 + */ + private FrequentItemSets(FrequentItemSets other) { + this.numberOfTransactions = other.numberOfTransactions; + this.frequentSets = new ArrayList<>(); + this.maximumSetSize = other.maximumSetSize; + for (FrequentItemSet set : other.frequentSets) { + frequentSets.add((FrequentItemSet) set.clone()); + } } /** @@ -139,4 +153,14 @@ public String toString(int maxNumber) { return output.toString(); } + @Override + public IOObject copy() { + return (IOObject) clone(); + } + + @Override + public Object clone() { + return new FrequentItemSets(this); + } + } diff --git a/src/main/java/com/rapidminer/operator/learner/functions/neuralnet/ImprovedNeuralNetLearner.java b/src/main/java/com/rapidminer/operator/learner/functions/neuralnet/ImprovedNeuralNetLearner.java index f14c433b4..2065be3eb 100644 --- a/src/main/java/com/rapidminer/operator/learner/functions/neuralnet/ImprovedNeuralNetLearner.java +++ b/src/main/java/com/rapidminer/operator/learner/functions/neuralnet/ImprovedNeuralNetLearner.java @@ -166,26 +166,26 @@ public List getParameterTypes() { new ParameterTypeInt( "hidden_layer_sizes", "The size of the hidden layers. A size of < 0 leads to a layer size of (number_of_attributes + number of classes) / 2 + 1.", - -1, Integer.MAX_VALUE, -1)); + -1, Integer.MAX_VALUE, 2)); type.setExpert(false); type.setPrimary(true); types.add(type); type = new ParameterTypeInt(PARAMETER_TRAINING_CYCLES, - "The number of training cycles used for the neural network training.", 1, Integer.MAX_VALUE, 500); + "The number of training cycles used for the neural network training.", 1, Integer.MAX_VALUE, 200); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_LEARNING_RATE, "The learning rate determines by how much we change the weights at each step. May not be 0.", - Double.MIN_VALUE, 1.0d, 0.3d); + Double.MIN_VALUE, 1.0d, 0.01d); type.setExpert(false); types.add(type); types.add(new ParameterTypeDouble( PARAMETER_MOMENTUM, "The momentum simply adds a fraction of the previous weight update to the current one (prevent local maxima and smoothes optimization directions).", - 0.0d, 1.0d, 0.2d)); + 0.0d, 1.0d, 0.9d)); types.add(new ParameterTypeBoolean(PARAMETER_DECAY, "Indicates if the learning rate should be decreased during learningh", false)); @@ -202,7 +202,7 @@ public List getParameterTypes() { types.add(new ParameterTypeDouble(PARAMETER_ERROR_EPSILON, "The optimization is stopped if the training error gets below this epsilon value.", 0.0d, - Double.POSITIVE_INFINITY, 0.00001d)); + Double.POSITIVE_INFINITY, 0.0001d)); types.addAll(RandomGenerator.getRandomGeneratorParameters(this)); diff --git a/src/main/java/com/rapidminer/operator/learner/lazy/KNNLearner.java b/src/main/java/com/rapidminer/operator/learner/lazy/KNNLearner.java index e4acb85ad..a93249f55 100644 --- a/src/main/java/com/rapidminer/operator/learner/lazy/KNNLearner.java +++ b/src/main/java/com/rapidminer/operator/learner/lazy/KNNLearner.java @@ -149,12 +149,12 @@ public List getParameterTypes() { List types = super.getParameterTypes(); ParameterType type = new ParameterTypeInt(PARAMETER_K, "The used number of nearest neighbors.", 1, - Integer.MAX_VALUE, 1); + Integer.MAX_VALUE, 5); type.setExpert(false); types.add(type); types.add(new ParameterTypeBoolean(PARAMETER_WEIGHTED_VOTE, - "Indicates if the votes should be weighted by similarity.", false, false)); + "Indicates if the votes should be weighted by similarity.", true, false)); types.addAll(DistanceMeasures.getParameterTypes(this)); return types; diff --git a/src/main/java/com/rapidminer/operator/learner/meta/StackingModel.java b/src/main/java/com/rapidminer/operator/learner/meta/StackingModel.java index 391d6cece..c24ac7439 100644 --- a/src/main/java/com/rapidminer/operator/learner/meta/StackingModel.java +++ b/src/main/java/com/rapidminer/operator/learner/meta/StackingModel.java @@ -153,7 +153,9 @@ public void update(Observable observable, OperatorProgress arg stackingExampleSet.getExampleTable().removeAttribute(tempPrediction); } - progress.complete(); + if (progress != null) { + progress.complete(); + } return exampleSet; } diff --git a/src/main/java/com/rapidminer/operator/learner/tree/AbstractParallelTreeLearner.java b/src/main/java/com/rapidminer/operator/learner/tree/AbstractParallelTreeLearner.java index 4d52f2934..f03b9dd48 100644 --- a/src/main/java/com/rapidminer/operator/learner/tree/AbstractParallelTreeLearner.java +++ b/src/main/java/com/rapidminer/operator/learner/tree/AbstractParallelTreeLearner.java @@ -395,7 +395,7 @@ public List getParameterTypes() { types.add(type); type = new ParameterTypeDouble(PARAMETER_CONFIDENCE, - "The confidence level used for the pessimistic error calculation of pruning.", 0.0000001, 0.5, 0.25); + "The confidence level used for the pessimistic error calculation of pruning.", 0.0000001, 0.5, 0.1); type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_PRUNING, false, true)); type.setExpert(false); types.add(type); @@ -406,7 +406,7 @@ public List getParameterTypes() { types.add(type); type = new ParameterTypeDouble(PARAMETER_MINIMAL_GAIN, - "The minimal gain which must be achieved in order to produce a split.", 0.0d, Double.POSITIVE_INFINITY, 0.1d); + "The minimal gain which must be achieved in order to produce a split.", 0.0d, Double.POSITIVE_INFINITY, 0.01d); type.registerDependencyCondition(new BooleanParameterCondition(this, PARAMETER_PRE_PRUNING, false, true)); type.setExpert(false); types.add(type); diff --git a/src/main/java/com/rapidminer/operator/learner/tree/CHAIDLearner.java b/src/main/java/com/rapidminer/operator/learner/tree/CHAIDLearner.java index b31dfc61b..614452358 100644 --- a/src/main/java/com/rapidminer/operator/learner/tree/CHAIDLearner.java +++ b/src/main/java/com/rapidminer/operator/learner/tree/CHAIDLearner.java @@ -133,10 +133,18 @@ public List getParameterTypes() { // remove criterion selection Iterator i = types.iterator(); while (i.hasNext()) { - if (i.next().getKey().equals(PARAMETER_CRITERION)) { + ParameterType type = i.next(); + if (PARAMETER_CRITERION.equals(type.getKey())) { i.remove(); + } else if (PARAMETER_CONFIDENCE.equals(type.getKey())) { + type.setDefaultValue(0.1d); + } else if (PARAMETER_MINIMAL_GAIN.equals(type.getKey())) { + type.setDefaultValue(0.01d); + } else if (PARAMETER_MAXIMAL_DEPTH.equals(type.getKey())) { + type.setDefaultValue(10); } } + return types; } diff --git a/src/main/java/com/rapidminer/operator/learner/tree/ID3Learner.java b/src/main/java/com/rapidminer/operator/learner/tree/ID3Learner.java index 6ab482937..a259779fa 100644 --- a/src/main/java/com/rapidminer/operator/learner/tree/ID3Learner.java +++ b/src/main/java/com/rapidminer/operator/learner/tree/ID3Learner.java @@ -22,6 +22,7 @@ import com.rapidminer.operator.OperatorCapability; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.parameter.ParameterType; import java.util.LinkedList; import java.util.List; @@ -76,4 +77,16 @@ protected TreeBuilder getTreeBuilder(ExampleSet exampleSet) throws OperatorExcep getTerminationCriteria(exampleSet), getPruner(), getSplitPreprocessing(), new DecisionTreeLeafCreator(), true, 0, getParameterAsInt(PARAMETER_MINIMAL_SIZE_FOR_SPLIT), getParameterAsInt(PARAMETER_MINIMAL_LEAF_SIZE)); } + + @Override + public List getParameterTypes() { + List types = super.getParameterTypes(); + + for (ParameterType type: types) { + if (PARAMETER_MINIMAL_GAIN.equals(type.getKey())) { + type.setDefaultValue(0.01d); + } + } + return types; + } } diff --git a/src/main/java/com/rapidminer/operator/learner/tree/RelevanceTreeLearner.java b/src/main/java/com/rapidminer/operator/learner/tree/RelevanceTreeLearner.java index 2ddfea2f9..a6c2c70cc 100644 --- a/src/main/java/com/rapidminer/operator/learner/tree/RelevanceTreeLearner.java +++ b/src/main/java/com/rapidminer/operator/learner/tree/RelevanceTreeLearner.java @@ -235,7 +235,7 @@ public List getParameterTypes() { type.setExpert(false); types.add(type); type = new ParameterTypeDouble(DecisionTreeLearner.PARAMETER_CONFIDENCE, "The confidence level used for pruning.", - 0.0000001, 0.5, 0.25); + 0.0000001, 0.5, 0.1); type.setExpert(false); types.add(type); types.add(new ParameterTypeBoolean(DecisionTreeLearner.PARAMETER_NO_PRUNING, diff --git a/src/main/java/com/rapidminer/operator/nio/CSVExampleSource.java b/src/main/java/com/rapidminer/operator/nio/CSVExampleSource.java index 8dd0460eb..64e9cf0de 100644 --- a/src/main/java/com/rapidminer/operator/nio/CSVExampleSource.java +++ b/src/main/java/com/rapidminer/operator/nio/CSVExampleSource.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.operator.nio; import java.text.NumberFormat; @@ -23,10 +23,14 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang.ArrayUtils; + import com.rapidminer.core.io.data.DataSetException; import com.rapidminer.core.io.data.source.DataSource; +import com.rapidminer.example.ExampleSet; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.io.AbstractReader; import com.rapidminer.operator.nio.model.AbstractDataResultSetReader; import com.rapidminer.operator.nio.model.CSVResultSetConfiguration; @@ -65,6 +69,12 @@ public class CSVExampleSource extends AbstractDataResultSetReader { public static final String PARAMETER_ESCAPE_CHARACTER = "escape_character"; public static final String PARAMETER_STARTING_ROW = "starting_row"; + /** + * Values will be trimmed for guessing after this version + * @since 9.1.1 + */ + public static final OperatorVersion BEFORE_VALUE_TRIMMING_GUESSING = new OperatorVersion(9, 0, 3); + static { AbstractReader.registerReaderDescription(new ReaderDescription("csv", CSVExampleSource.class, PARAMETER_CSV_FILE)); } @@ -98,6 +108,28 @@ protected String getFileExtension() { return "csv"; } + + /** + * Whether attributes should be trimmed for guessing + * + * @return {@code true} if compatibility level is above {@link #BEFORE_VALUE_TRIMMING_GUESSING} + * @since 9.1.1 + */ + @Override + public boolean trimForGuessing() { + return getCompatibilityLevel().isAbove(BEFORE_VALUE_TRIMMING_GUESSING); + } + + @Override + public ExampleSet createExampleSet() throws OperatorException { + // Trim the date format, if the values are trimmed + String dateFormat = getParameter(ParameterTypeDateFormat.PARAMETER_DATE_FORMAT); + if (dateFormat != null && trimForGuessing()) { + setParameter(ParameterTypeDateFormat.PARAMETER_DATE_FORMAT, dateFormat.trim()); + } + return super.createExampleSet(); + } + @Override public List getParameterTypes() { LinkedList types = new LinkedList<>(); @@ -163,7 +195,8 @@ public void configure(DataSource dataSource) throws DataSetException { setParameter(PARAMETER_QUOTES_CHARACTER, configParameters.get(CSVResultSetConfiguration.CSV_QUOTE_CHARACTER)); setParameter(PARAMETER_TRIM_LINES, configParameters.get(CSVResultSetConfiguration.CSV_TRIM_LINES)); - int rowOffset = Integer.parseInt(configParameters.get(CSVResultSetConfiguration.CSV_STARTING_ROW)); + // the backend uses technical row values starting with 0 but the operator parameters show human readable versions thus +1 + int rowOffset = Integer.parseInt(configParameters.get(CSVResultSetConfiguration.CSV_STARTING_ROW)) + 1; int headerRowIndex = Integer.parseInt(configParameters.get(CSVResultSetConfiguration.CSV_HEADER_ROW)); if (rowOffset < 0) { @@ -175,11 +208,21 @@ public void configure(DataSource dataSource) throws DataSetException { if (headerRowEqualsStartingRow) { rowOffset++; } - setParameter(PARAMETER_FIRST_ROW_AS_NAMES, String.valueOf(headerRowEqualsStartingRow)); + setParameter(PARAMETER_FIRST_ROW_AS_NAMES, String.valueOf(Boolean.valueOf(configParameters.get(CSVResultSetConfiguration.CSV_HAS_HEADER_ROW)) || headerRowEqualsStartingRow)); setParameter(PARAMETER_STARTING_ROW, String.valueOf(rowOffset)); // set meta data ImportWizardUtils.setMetaData(dataSource, this); + + // update compatibility level to latest version + setCompatibilityLevel(OperatorVersion.getLatestVersion(getOperatorDescription())); } + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + return (OperatorVersion[]) ArrayUtils.addAll(super.getIncompatibleVersionChanges(), + new OperatorVersion[]{ + BEFORE_VALUE_TRIMMING_GUESSING + }); + } } diff --git a/src/main/java/com/rapidminer/operator/nio/CSVExampleSourceConfigurationWizardCreator.java b/src/main/java/com/rapidminer/operator/nio/CSVExampleSourceConfigurationWizardCreator.java index 6e6168f28..639a59914 100644 --- a/src/main/java/com/rapidminer/operator/nio/CSVExampleSourceConfigurationWizardCreator.java +++ b/src/main/java/com/rapidminer/operator/nio/CSVExampleSourceConfigurationWizardCreator.java @@ -26,7 +26,6 @@ import com.rapidminer.parameter.ParameterType; import com.rapidminer.studio.io.data.internal.file.csv.CSVDataSourceFactory; import com.rapidminer.studio.io.gui.internal.DataImportWizardBuilder; -import com.rapidminer.studio.io.gui.internal.DataImportWizardUtils; /** diff --git a/src/main/java/com/rapidminer/operator/nio/CSVSyntaxConfigurationWizardStep.java b/src/main/java/com/rapidminer/operator/nio/CSVSyntaxConfigurationWizardStep.java index c44b2ddbc..0e5dbd075 100644 --- a/src/main/java/com/rapidminer/operator/nio/CSVSyntaxConfigurationWizardStep.java +++ b/src/main/java/com/rapidminer/operator/nio/CSVSyntaxConfigurationWizardStep.java @@ -138,41 +138,25 @@ public CSVSyntaxConfigurationWizardStep(CSVImportWizard csvImportWizard, CSVResu } private void registerListeners() { - encodingComboBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - configuration.setEncoding(Encoding.getEncoding(encodingComboBox.getSelectedItem().toString())); - settingsChanged(); - } + encodingComboBox.addActionListener(e -> { + configuration.setEncoding(Encoding.getEncoding(encodingComboBox.getSelectedItem().toString())); + settingsChanged(); }); - trimLinesBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - configuration.setTrimLines(trimLinesBox.isSelected()); - settingsChanged(); - } + trimLinesBox.addActionListener(e -> { + configuration.setTrimLines(trimLinesBox.isSelected()); + settingsChanged(); }); - skipCommentsBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - commentCharacterTextField.setEnabled(skipCommentsBox.isSelected()); - configuration.setSkipComments(skipCommentsBox.isSelected()); - settingsChanged(); - } + skipCommentsBox.addActionListener(e -> { + commentCharacterTextField.setEnabled(skipCommentsBox.isSelected()); + configuration.setSkipComments(skipCommentsBox.isSelected()); + settingsChanged(); }); - useQuotesBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - quoteCharacterTextField.setEnabled(useQuotesBox.isSelected()); - escapeCharacterTextField.setEnabled(useQuotesBox.isSelected()); - configuration.setUseQuotes(useQuotesBox.isSelected()); - settingsChanged(); - } + useQuotesBox.addActionListener(e -> { + quoteCharacterTextField.setEnabled(useQuotesBox.isSelected()); + escapeCharacterTextField.setEnabled(useQuotesBox.isSelected()); + configuration.setUseQuotes(useQuotesBox.isSelected()); + settingsChanged(); }); quoteCharacterTextField.addKeyListener(new KeyAdapter() { diff --git a/src/main/java/com/rapidminer/operator/nio/DateFormatGuesser.java b/src/main/java/com/rapidminer/operator/nio/DateFormatGuesser.java new file mode 100644 index 000000000..b566300b7 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/nio/DateFormatGuesser.java @@ -0,0 +1,256 @@ +/** + * Copyright (C) 2001-2018 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.operator.nio; + +import java.text.DateFormat; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import com.rapidminer.core.io.data.DataSet; +import com.rapidminer.core.io.data.DataSetException; +import com.rapidminer.core.io.data.DataSetRow; +import com.rapidminer.operator.nio.model.CSVResultSet; +import com.rapidminer.parameter.ParameterTypeDateFormat; +import com.rapidminer.tools.LogService; + +/** + * The DateFormatGuesser provides a constructor for basic initialization and a count method to read data. + * The counting will check known dateformats from {@link ParameterTypeDateFormat#PREDEFINED_DATE_FORMATS} and the results + * are then available in form of methods for the best matching {@link SimpleDateFormat}, the results with confidences and + * the probably date typable attribute IDs. + * + * @author Andreas Timm, Jan Czogalla + * @since 9.1.0 + */ +public class DateFormatGuesser { + + /** keeping the initialized SimpleDateFormats for this instance */ + private SimpleDateFormat[] dateFormats; + /** counting matches for the different dateFormats */ + private Map dateFormatMatches = new HashMap<>(); + /** counting matches for dateFormats for every Attribute */ + private Map dateFormatAttributeMatchCount = new HashMap<>(); + /** keeping the bestMatchingFormat until an update happens */ + private String bestMatchingFormat = null; + /** amount of attribute, requires this many elements when counting */ + private int attributeCount; + /** count of the amount of rows */ + private int countedRows = 0; + /** preferred date formats */ + private String preferredDateFormat; + + /** + * Construct an instance, initializes data structures. + * + * @param attributeCount + * amount of attributes that will be handled, not less than 1 + * @param customFormats + * optional, can be used to pass additional date format which are not part of {@link + * ParameterTypeDateFormat#PREDEFINED_DATE_FORMATS} + * @param preferredDateFormat a preferred Date Format + */ + public DateFormatGuesser(int attributeCount, List customFormats, String preferredDateFormat) { + if (attributeCount < 1) { + throw new IllegalArgumentException("Date format guessing requires at least one column"); + } + Set allFormats = new HashSet<>(customFormats != null ? customFormats : Collections.emptyList()); + allFormats.addAll(Arrays.asList(ParameterTypeDateFormat.PREDEFINED_DATE_FORMATS)); + allFormats.add(preferredDateFormat); + this.preferredDateFormat = preferredDateFormat; + Set dateFormatList = new LinkedHashSet<>(); + for (String dateFormat : allFormats) { + if (dateFormat != null && !dateFormat.trim().isEmpty()) { + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); + simpleDateFormat.setLenient(false); + dateFormatList.add(simpleDateFormat); + dateFormatMatches.put(dateFormat, new double[attributeCount]); + dateFormatAttributeMatchCount.put(dateFormat, new int[attributeCount]); + } catch (Exception e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.import.could_not_create_dateformat", e); + } + } + } + dateFormats = dateFormatList.toArray(new SimpleDateFormat[0]); + this.attributeCount = attributeCount; + } + + /** + * Add these entries to the calculation. content.length needs to be equal to attributeCount fed to the constructor. + * + * @param content + * elements to be counted, may contain nulls + * @throws IllegalArgumentException + * if the given {@code content} array's length is not equal to the configured {@link #attributeCount} + */ + public void count(String[] content) { + if (content == null) { + return; + } + if (content.length != attributeCount) { + throw new IllegalArgumentException("Expected " + attributeCount + " elements to count but got " + content.length); + } + bestMatchingFormat = null; + for (int partNr = 0; partNr < content.length; partNr++) { + String part = content[partNr]; + if (part == null || part.trim().isEmpty()) { + continue; + } + part = part.trim(); + for (SimpleDateFormat dateFormat : dateFormats) { + ParsePosition pos = new ParsePosition(0); + if (dateFormat.parse(part, pos) != null) { + // match both full and partial; weigh by percentage of used pattern + double weight = (double) pos.getIndex() / part.length(); + dateFormatMatches.get(dateFormat.toPattern())[partNr] += weight; + dateFormatAttributeMatchCount.get(dateFormat.toPattern())[partNr]++; + } + } + } + countedRows++; + } + + /** + * After counting from given data, the best matching date format is available. Custom formats given to the constructor + * will be preferred. + * + * @param confidence + * percentage at which a column is considered a potential date/time column + * @return a {@link SimpleDateFormat} with the most matches over the complete previously given data. If no match + * could be found, returns {@code null} + */ + public SimpleDateFormat getBestMatch(double confidence) { + if (bestMatchingFormat == null) { + Map results = getResults(confidence); + Stream> resultStream = results.entrySet().stream(); + boolean usePreferredFormat = preferredDateFormat != null; + if (usePreferredFormat) { + resultStream = resultStream.filter(e -> preferredDateFormat.equals(e.getKey())); + } + Optional> bestMatch = resultStream.min(Comparator.comparingDouble(e -> -e.getValue())); + if (!usePreferredFormat) { + double maxValue = bestMatch.map(Entry::getValue).orElse(0d); + if (Double.isNaN(maxValue) || maxValue <= 0d) { + return null; + } + } + bestMatchingFormat = bestMatch.map(Entry::getKey).orElse(null); + } + return bestMatchingFormat == null ? null : new SimpleDateFormat(bestMatchingFormat); + } + + /** + * The results contain all known date formats with their performance which is amount of matches of one date format + * divided by sum of all date format matches (i.e. maximum number of date/time columns times number of rows counted). + * + * @param confidence + * percentage at which a column is considered a potential date/time column + * @return the mapping for date format patterns to their performance + */ + public Map getResults(double confidence) { + int[] matchMask = new int[attributeCount]; + // find maximum match count per column + dateFormatAttributeMatchCount.values().forEach(matches -> + IntStream.range(0, matchMask.length).filter(i -> matches[i] > matchMask[i]).forEach(i -> matchMask[i] = matches[i])); + + // find potential date/time columns (confidence based) and create a 0/1 mask + double minimumRows = confidence * countedRows; + Arrays.setAll(matchMask, i -> matchMask[i] >= minimumRows ? 1 : 0); + + int maxColumns = Arrays.stream(matchMask).sum(); + // calculate matching percentage; weighted sum over all potential date/time columns + return dateFormatMatches.entrySet().stream().collect(Collectors.toMap(Entry::getKey, + e -> dot(e.getValue(), matchMask) / (maxColumns * countedRows))); + } + + /** + * The different attributes may fit better or worse for one date format. The attribute IDs which have at least the + * given confidence matching the pattern will be returned. The confidence is compared to the amount of matches of + * the attribute divided by the amount of rows. + * + * @param pattern + * one of the known date formats + * @param confidence + * number between 0.0 and 1.0 (inclusive) to get reasonable results + * @return the attribute indices that are probably of the type date. Based on the number of attribute fed to the + * constructor and the string array fed to {@link #count(String[])} + */ + public List getDateAttributes(String pattern, double confidence) { + final int[] matches = dateFormatAttributeMatchCount.get(pattern); + if (matches == null) { + return Collections.emptyList(); + } + double minimumRows = confidence * countedRows; + return IntStream.range(0, matches.length).filter(i -> matches[i] >= minimumRows).boxed().collect(Collectors.toList()); + } + + /** + * This factory method runs a data guessing procedure for the given {@link DataSet}. + * The data will be checked for usual {@link DateFormat DateFormats}. + * The result can afterwards be collected from the returned {@link DateFormatGuesser}. + * + * @param data + * the data set that may contain dates + * @return a {@link DateFormatGuesser} with preprocessed results. + * @throws DataSetException if an error occurs when accessing the data set + * @see ParameterTypeDateFormat#PREDEFINED_DATE_FORMATS + */ + public static DateFormatGuesser guessDateFormat(DataSet data, List existingDateFormats, String preferredDateFormat) throws DataSetException { + if (data == null) { + return null; + } + DateFormatGuesser dfg = new DateFormatGuesser(data.getNumberOfColumns(), existingDateFormats, preferredDateFormat); + data.reset(); + int lineCount = 0; + while (data.hasNext() && lineCount < CSVResultSet.LINES_FOR_GUESSING) { + final DataSetRow dataSetRow = data.nextRow(); + String[] row = new String[data.getNumberOfColumns()]; + for (int i = 0; i < data.getNumberOfColumns(); i++) { + try { + row[i] = dataSetRow.getString(i); + } catch (com.rapidminer.core.io.data.ParseException e) { + LogService.getRoot().log(Level.INFO, "com.rapidminer.gui.import.could_not_read_from_dataset", e); + } + } + dfg.count(row); + lineCount++; + } + return dfg; + } + + /** Create dot product of the given arguments. The arrays must be the same length. */ + private static double dot(double[] values, int[] matchMask) { + return IntStream.range(0, matchMask.length).mapToDouble(i -> matchMask[i] * values[i]).sum(); + } +} diff --git a/src/main/java/com/rapidminer/operator/nio/DateTimeTypeGuesser.java b/src/main/java/com/rapidminer/operator/nio/DateTimeTypeGuesser.java new file mode 100644 index 000000000..bb9ef1946 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/nio/DateTimeTypeGuesser.java @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2001-2018 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.operator.nio; + +import java.util.regex.Pattern; + +import com.rapidminer.core.io.data.ColumnMetaData; + + +/** + * Detects if SimpleDateFormat pattern is a Date, Time or DateTime format + * + * @author Jan Czogalla, Jonas Wilms-Pfau + * @since 9.1 + */ +public final class DateTimeTypeGuesser { + + private static final int DATE = 1; + private static final int TIME = 2; + + // date indicators as defined by SimpleDateFormat javadoc + private static final Pattern DATE_PATTERN = Pattern.compile(".*[yYMwWDdFEu].*"); + // time indicators as defined by SimpleDateFormat javadoc + private static final Pattern TIME_PATTERN = Pattern.compile(".*[aHkKhmsS].*"); + // replacement match for escaped parts of simple date format + private static final String REPLACE_PATTERN = "'.*?'"; + // replacement match for escaped single quotes ' asdas '' asdsda ' + private static final String REPLACE_SINGLE_QUOTES = "''"; + + private DateTimeTypeGuesser(){ + throw new AssertionError("Utility class"); + } + + /** + * Detects the ColumnType for a date pattern + * + * @param pattern a SimpleDateFormat pattern + * @return the ColumnType.DATE, ColumnType.TIME or ColumnType.DATETIME + */ + public static ColumnMetaData.ColumnType patternToColumnType(String pattern) { + // first remove escaped single quotes '' + pattern = pattern.replaceAll(REPLACE_SINGLE_QUOTES, ""); + // remove escaped strings + pattern = pattern.replaceAll(REPLACE_PATTERN, ""); + int result = (DATE_PATTERN.matcher(pattern).matches() ? DATE : 0) + + (TIME_PATTERN.matcher(pattern).matches() ? TIME : 0); + switch (result) { + case DATE: return ColumnMetaData.ColumnType.DATE; + case TIME: return ColumnMetaData.ColumnType.TIME; + default: return ColumnMetaData.ColumnType.DATETIME; + } + } +} diff --git a/src/main/java/com/rapidminer/operator/nio/ExcelDateTimeTypeGuesser.java b/src/main/java/com/rapidminer/operator/nio/ExcelDateTimeTypeGuesser.java new file mode 100644 index 000000000..100e48b2d --- /dev/null +++ b/src/main/java/com/rapidminer/operator/nio/ExcelDateTimeTypeGuesser.java @@ -0,0 +1,156 @@ +/** + * Copyright (C) 2001-2018 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.operator.nio; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoField; +import java.util.Arrays; +import java.util.Date; +import java.util.stream.IntStream; + +import com.rapidminer.core.io.data.ColumnMetaData; +import com.rapidminer.core.io.data.DataSet; +import com.rapidminer.core.io.data.DataSetException; +import com.rapidminer.core.io.data.DataSetMetaData; +import com.rapidminer.core.io.data.DataSetRow; +import com.rapidminer.operator.nio.model.CSVResultSet; + + +/** + * Detects if a Excel DateTime is either a Date, Time or just a DateTime + * + * @author Jonas Wilms-Pfau + * @since 9.1.0 + */ +public final class ExcelDateTimeTypeGuesser { + + private static final int HAS_DATE = 0x01; + private static final int HAS_TIME = 0x02; + private static final int DATETIME = HAS_DATE | HAS_TIME; + /** XLS time is stored on the 30.12.1899 */ + private static final long TIME_1900_XLS = LocalDate.of(1899, 12, 30).getLong(ChronoField.EPOCH_DAY); + /** XLSX time is stored on the 31.12.1899 */ + private static final long TIME_1900_XLSX = TIME_1900_XLS + 1; + /** 1904 times are stored on the 1.1.1904 for both XLS and XLSX */ + private static final long TIME_1904 = LocalDate.ofYearDay(1904, 1).getLong(ChronoField.EPOCH_DAY); + /** Dates have no time */ + private static final long DATE_MICRO_OF_DAY = 0; + + private ExcelDateTimeTypeGuesser() { + throw new AssertionError("Utility class"); + } + + /** + * Determines if the DateTime columns of the given DataSet are actually Date or Time columns + * + * @param data The DataSet + * @param metaData The original MetaData + * @return The adjusted MetaData + * @throws DataSetException in case the data could not be loaded + */ + public static DataSetMetaData guessDateTimeColumnType(DataSet data, DataSetMetaData metaData) throws DataSetException { + DataSetMetaData copiedMetaData = metaData.copy(); + int[] dateColumns = IntStream.range(0, copiedMetaData.getColumnMetaData().size()).filter(c -> copiedMetaData.getColumnMetaData().get(c).getType() == ColumnMetaData.ColumnType.DATETIME).toArray(); + ColumnMetaData.ColumnType[] dateMetaData = guessDateTimeColumnType(data, dateColumns); + for (int dateColumn : dateColumns) { + copiedMetaData.getColumnMetaData(dateColumn).setType(dateMetaData[dateColumn]); + } + return copiedMetaData; + } + + /** + * Checks if the given dateTimeColumns are ColumnType.DATE, ColumnType.TIME or ColumnType.DATETIME + * + * @param data + * the data + * @param dateTimeColumns + * index of datetime columns to predict + * @return array containing ColumnType.DATE, ColumnType.TIME or ColumnType.DATETIME for each column + * @throws DataSetException in case the data could not be loaded + */ + public static ColumnMetaData.ColumnType[] guessDateTimeColumnType(DataSet data, int... dateTimeColumns) throws DataSetException { + int initialIndex = data.getCurrentRowIndex(); + data.reset(); + int[] type = new int[data.getNumberOfColumns()]; + for (int lineCount = 0; lineCount < CSVResultSet.LINES_FOR_GUESSING && data.hasNext(); lineCount++) { + DataSetRow row = data.nextRow(); + for (int col : dateTimeColumns) { + if (type[col] == DATETIME || col >= data.getNumberOfColumns() || row.isMissing(col)) { + continue; + } + try { + type[col] |= guessDateTimeType(row.getDate(col), type[col]); + } catch (Exception e) { + // do nothing + } + } + } + // Rewind iterator to initial position + data.reset(); + while (data.getCurrentRowIndex() < initialIndex && data.hasNext()) { + data.nextRow(); + } + return Arrays.stream(type).mapToObj(ExcelDateTimeTypeGuesser::toColumnType).toArray(ColumnMetaData.ColumnType[]::new); + } + + /** + * Guess the type for the given date + * + * @param date the date + * @param type the currently guessed type + * @return the guessed type + */ + private static int guessDateTimeType(Date date, int type) { + LocalDateTime localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + + // Check if it has a time + if (type != HAS_TIME && localDate.getLong(ChronoField.MICRO_OF_DAY) != DATE_MICRO_OF_DAY) { + type |= HAS_TIME; + } + + // Check if it has a date + if (type != HAS_DATE) { + long day = localDate.getLong(ChronoField.EPOCH_DAY); + if (day != TIME_1900_XLSX && day != TIME_1900_XLS && day != TIME_1904) { + type |= HAS_DATE; + } + } + return type; + } + + /** + * Converts an internal type to an ColumnType + * + * @param type + * the internal type HAS_DATE, HAS_TIME or DATE_TIME + * @return a ColumnType + */ + private static ColumnMetaData.ColumnType toColumnType(int type) { + switch (type) { + case HAS_TIME: + return ColumnMetaData.ColumnType.TIME; + case HAS_DATE: + return ColumnMetaData.ColumnType.DATE; + default: + return ColumnMetaData.ColumnType.DATETIME; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/rapidminer/operator/nio/ExcelExampleSourceConfigurationWizardCreator.java b/src/main/java/com/rapidminer/operator/nio/ExcelExampleSourceConfigurationWizardCreator.java index 72894a038..e1bb8395c 100644 --- a/src/main/java/com/rapidminer/operator/nio/ExcelExampleSourceConfigurationWizardCreator.java +++ b/src/main/java/com/rapidminer/operator/nio/ExcelExampleSourceConfigurationWizardCreator.java @@ -26,7 +26,6 @@ import com.rapidminer.parameter.ParameterType; import com.rapidminer.studio.io.data.internal.file.excel.ExcelDataSourceFactory; import com.rapidminer.studio.io.gui.internal.DataImportWizardBuilder; -import com.rapidminer.studio.io.gui.internal.DataImportWizardUtils; /** @@ -45,7 +44,6 @@ public void createConfigurationWizard(ParameterType type, ConfigurationListener DataImportWizardBuilder builder = new DataImportWizardBuilder(); JDialog wizard = builder.forOperator(sourceOperator, ExcelDataSourceFactory.EXCEL_DATA_SOURCE_FACTORY_I18N_KEY).build(RapidMinerGUI.getMainFrame()).getDialog(); wizard.setVisible(true); - } @Override diff --git a/src/main/java/com/rapidminer/operator/nio/MetaDataDeclarationWizardStep.java b/src/main/java/com/rapidminer/operator/nio/MetaDataDeclarationWizardStep.java index 298fbe173..c16f6b8a1 100644 --- a/src/main/java/com/rapidminer/operator/nio/MetaDataDeclarationWizardStep.java +++ b/src/main/java/com/rapidminer/operator/nio/MetaDataDeclarationWizardStep.java @@ -54,6 +54,7 @@ import com.rapidminer.datatable.DataTableExampleSetAdapter; import com.rapidminer.example.ExampleSet; import com.rapidminer.gui.tools.CellColorProviderAlternating; +import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ExtendedJTable; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ResourceAction; @@ -270,7 +271,7 @@ public void valueChanged(ListSelectionEvent e) { } } }); - final JScrollPane errorScrollPane = new JScrollPane(errorTable); + final JScrollPane errorScrollPane = new ExtendedJScrollPane(errorTable); errorScrollPane.setPreferredSize(new Dimension(500, 80)); c.weighty = 1; c.gridwidth = GridBagConstraints.REMAINDER; diff --git a/src/main/java/com/rapidminer/operator/nio/model/AbstractDataResultSetReader.java b/src/main/java/com/rapidminer/operator/nio/model/AbstractDataResultSetReader.java index bdf08b78f..a2d58cdfd 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/AbstractDataResultSetReader.java +++ b/src/main/java/com/rapidminer/operator/nio/model/AbstractDataResultSetReader.java @@ -36,7 +36,6 @@ import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.OperatorVersion; -import com.rapidminer.operator.io.AbstractDataReader.AttributeColumn; import com.rapidminer.operator.io.AbstractExampleSource; import com.rapidminer.operator.nio.file.FileInputPortHandler; import com.rapidminer.operator.nio.file.FileObject; @@ -315,7 +314,7 @@ public List getParameterTypes() { new ParameterTypeCategory(PARAMETER_COLUMN_VALUE_TYPE, "Indicates the value type of an attribute", Ontology.VALUE_TYPE_NAMES, Ontology.NOMINAL), // new ParameterTypeStringCategory(PARAMETER_COLUMN_ROLE, "Indicates the role of an attribute", - Attributes.KNOWN_ATTRIBUTE_TYPES, AttributeColumn.REGULAR)), + Attributes.KNOWN_ATTRIBUTE_TYPES, Attributes.KNOWN_ATTRIBUTE_TYPES[0])), true); type.registerDependencyCondition(dependsOnGuessValue); @@ -338,6 +337,16 @@ public boolean shouldTrimAttributeNames() { return getCompatibilityLevel().isAbove(DataResultSetTranslator.BEFORE_ATTRIBUTE_TRIMMING); } + /** + * Whether values should be trimmed for guessing + * + * @return if this operator requires trimming for guessing + * @since 9.1.1 + */ + public boolean trimForGuessing() { + return false; + } + @Override public OperatorVersion[] getIncompatibleVersionChanges() { OperatorVersion[] changes = super.getIncompatibleVersionChanges(); diff --git a/src/main/java/com/rapidminer/operator/nio/model/CSVResultSet.java b/src/main/java/com/rapidminer/operator/nio/model/CSVResultSet.java index 1ab48c354..37ac248a8 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/CSVResultSet.java +++ b/src/main/java/com/rapidminer/operator/nio/model/CSVResultSet.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.operator.nio.model; import java.io.File; @@ -51,17 +51,14 @@ /** - * * @author Simon Fischer - * */ public class CSVResultSet implements DataResultSet { /** - * specifies how many rows should be read to guess the column separator, 1 headline + 10 further - * rows + * specifies how many rows should be read to guess the column separator, 1 headline + 99 further rows */ - private static final int LINES_FOR_GUESSING = 11; + public static final int LINES_FOR_GUESSING = 100; private static final int MAX_LOG_COUNT = 100; private CSVResultSetConfiguration configuration; private LineReader reader; @@ -110,7 +107,7 @@ public enum TextQualifier { private final String qualifier; - TextQualifier(String qualifier, Pattern pattern){ + TextQualifier(String qualifier, Pattern pattern) { this.pattern = pattern; this.qualifier = qualifier; } @@ -140,7 +137,7 @@ public String getString() { return character; } - DecimalCharacter(String character, Pattern pattern){ + DecimalCharacter(String character, Pattern pattern) { this.character = character; this.pattern = pattern; } @@ -168,26 +165,15 @@ public CSVResultSet(CSVResultSetConfiguration configuration, Operator operator) private void open() throws OperatorException { getErrors().clear(); close(); + + if (operator == null) { + init(); + } + InputStream in = openStream(); logCount = 0; - // if encoding is UTF-8, we will have to check whether the stream starts with a BOM. If not - // restart stream - - if (configuration.getEncoding().name().equals("UTF-8")) { - try { - if (in.read() != 239 || in.read() != 187 || in.read() != 191) { - in.close(); - in = openStream(); - } - } catch (IOException e) { - try { - in.close(); - } catch (IOException e1) { - } - throw new UserError(operator, e, 321, configuration.getCsvFile(), e.toString()); - } - } + in = cleanInputStream(in); reader = new LineReader(in, configuration.getEncoding()); parser = new LineParser(configuration); @@ -205,6 +191,7 @@ private void open() throws OperatorException { try { int startingRow = configuration.getStartingRow(); + do { // if we read via operator, skip until we reach the starting row // if starting row equals 1 (aka start from the first row), this just prepares the column meta data @@ -223,16 +210,91 @@ private void open() throws OperatorException { // "No valid line found."); columnNames = new String[0]; valueTypes = new int[0]; + numColumns = 0; + currentRow = 0; + } else if (operator != null) { + initConfiguration(next); + } + } + + /** + * Initialize the settings for numColumns, columnNames and valueTypes from the configuration. Uses {@link CSVResultSet#openStream()} + * to get the {@link InputStream}. + * + * @throws OperatorException + */ + private void init() throws OperatorException { + InputStream in = openStream(); + in = cleanInputStream(in); + final LineReader lineReader = new LineReader(in, configuration.getEncoding()); + final LineParser lineParser = new LineParser(configuration); + String[] strings; + try { + int initFromRow = configuration.hasHeaderRow() ? configuration.getHeaderRow() : configuration.getStartingRow(); + do { + // skip until we reach the starting row + strings = readNext(lineReader, lineParser); + } while (initFromRow-- > 0); + } catch (IOException e) { + try { + in.close(); + } catch (IOException e1) { + } + throw new UserError(operator, e, 321, configuration.getCsvFile(), e.toString()); + } + if (strings != null) { + initConfiguration(strings); } else { - numColumns = next.length; - columnNames = new String[next.length]; - for (int i = 0; i < next.length; i++) { - columnNames[i] = "att" + (i + 1); + columnNames = new String[0]; + valueTypes = new int[0]; + } + } + + /** + * Set the configuration about columns using the given array of {@link String Strings} + * + * @param strings + * usually gets the parsed headerRow to set up internal data structures + * @since 9.1 + */ + private void initConfiguration(String[] strings) { + numColumns = strings.length; + columnNames = new String[strings.length]; + for (int i = 0; i < strings.length; i++) { + columnNames[i] = "att" + (i + 1); + } + valueTypes = new int[strings.length]; + Arrays.fill(valueTypes, Ontology.NOMINAL); + currentRow = -1; + } + + /** + * If the configuration's encoding is UTF-8, we will have to check whether the stream starts with a BOM. If not it + * will be restarted once. + * + * @param in + * the {@link InputStream} that needs to be checked + * @return the original or a restarted stream using openStream + * @throws UserError + * in case there was a problem reading or restarting the {@link InputStream} + * @since 9.1 + */ + private InputStream cleanInputStream(InputStream in) throws UserError { + if (configuration.getEncoding().name().equals("UTF-8")) { + try { + if (in.read() != 239 || in.read() != 187 || in.read() != 191) { + in.close(); + in = openStream(); + } + } catch (IOException e) { + try { + in.close(); + } catch (IOException e1) { + } + throw new UserError(operator, e, 321, configuration.getCsvFile(), e.toString()); } - valueTypes = new int[next.length]; - Arrays.fill(valueTypes, Ontology.NOMINAL); - currentRow = -1; } + return in; } /** @@ -240,7 +302,7 @@ private void open() throws OperatorException { * the most in the first rows. * * @param csvFile - * the csv file + * the csv file * @return the most frequent column separator */ public static String guessColumnSeperator(File csvFile) { @@ -252,7 +314,7 @@ public static String guessColumnSeperator(File csvFile) { * the most in the first rows. * * @param csvFile - * the path to the file to analyze + * the path to the file to analyze * @return the most frequent column separator */ public static String guessColumnSeperator(String csvFile) { @@ -264,7 +326,7 @@ public static String guessColumnSeperator(String csvFile) { * the most in the first rows. * * @param csvFile - * the path to the file to analyze + * the path to the file to analyze * @return the most frequent {@link ColumnSplitter} */ public static ColumnSplitter guessColumnSplitter(String csvFile) { @@ -276,7 +338,7 @@ public static ColumnSplitter guessColumnSplitter(String csvFile) { * the most in the first rows. * * @param csvFile - * the file to analyze + * the file to analyze * @return the most frequent {@link ColumnSplitter} */ public static ColumnSplitter guessColumnSplitter(File csvFile) { @@ -293,7 +355,7 @@ public static ColumnSplitter guessColumnSplitter(File csvFile) { while (lineCount < LINES_FOR_GUESSING) { String line = tempReader.readLine(); - for(ColumnSplitter splitter : ColumnSplitter.values()){ + for (ColumnSplitter splitter : ColumnSplitter.values()) { splitterValues.put(splitter, splitterValues.get(splitter) + getTokenCount(splitter.getPattern(), line)); } @@ -323,10 +385,10 @@ public static ColumnSplitter guessColumnSplitter(File csvFile) { /** * Guesses the Text Qualifier (quotes) being used by counting which one has the most pairs * - * @since 9.0.0 * @param csvFile - * the path to the file to analyze + * the path to the file to analyze * @return the most frequent {@link ColumnSplitter} + * @since 9.0.0 */ public static TextQualifier guessTextQualifier(String csvFile) { return guessTextQualifier(new File(csvFile)); @@ -335,11 +397,11 @@ public static TextQualifier guessTextQualifier(String csvFile) { /** * Guesses the {@link TextQualifier} (quotes) being used by counting which one has the most pairs * - * @since 9.0.0 * @param csvFile * @return the most frequent {@link TextQualifier} + * @since 9.0.0 */ - public static TextQualifier guessTextQualifier(File csvFile){ + public static TextQualifier guessTextQualifier(File csvFile) { try (LineReader tempReader = new LineReader(csvFile, StandardCharsets.UTF_8)) { //Set Default @@ -366,7 +428,7 @@ public static TextQualifier guessTextQualifier(File csvFile){ int maxValue = 0; for (TextQualifier qualifier : TextQualifier.values()) { int numberOfOccurrences = qualifierValues.get(qualifier); - if (numberOfOccurrences > maxValue && numberOfOccurrences%2==0) { + if (numberOfOccurrences > maxValue && numberOfOccurrences % 2 == 0) { maxValue = numberOfOccurrences; guessedQualifier = qualifier; } @@ -380,11 +442,11 @@ public static TextQualifier guessTextQualifier(File csvFile){ } } - public static DecimalCharacter guessDecimalSeparator(String csvFile){ + public static DecimalCharacter guessDecimalSeparator(String csvFile) { return guessDecimalSeparator(new File(csvFile)); } - public static DecimalCharacter guessDecimalSeparator(File csvFile){ + public static DecimalCharacter guessDecimalSeparator(File csvFile) { try (LineReader tempReader = new LineReader(csvFile, StandardCharsets.UTF_8)) { //Set Default DecimalCharacter guessedCharacter = DecimalCharacter.PERIOD; @@ -491,9 +553,40 @@ private void readNext() throws IOException { } } logCount++; - next = new String[] { line }; + next = new String[]{line}; + } + } while (true); + } + + /** + * Gets the next rows parts using the given {@link LineParser} + * + * @param lineReader + * to be used for reading the next row + * @param lineParser + * to be used to parse the row + * @return the output of the parser or an array with one entry being the whole rows content. Can be {@code null} if the lineReader returned {@code null}. + * @throws IOException + * in case the lineReader got an error + * @since 9.1 + */ + private static String[] readNext(LineReader lineReader, LineParser lineParser) throws IOException { + String[] myNext; + do { + String line = lineReader == null ? null : lineReader.readLine(); + if (line == null) { + return null; + } + try { + myNext = lineParser.parse(line); + if (myNext != null) { // no comment read + break; + } + } catch (CSVParseException e) { + continue; } } while (true); + return myNext; } @Override diff --git a/src/main/java/com/rapidminer/operator/nio/model/CSVResultSetConfiguration.java b/src/main/java/com/rapidminer/operator/nio/model/CSVResultSetConfiguration.java index d96013c5f..312f46377 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/CSVResultSetConfiguration.java +++ b/src/main/java/com/rapidminer/operator/nio/model/CSVResultSetConfiguration.java @@ -23,7 +23,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.swing.table.TableModel; import com.rapidminer.operator.Operator; @@ -55,6 +54,7 @@ public class CSVResultSetConfiguration implements DataResultSetFactory { public static final String CSV_TRIM_LINES = "trimLines"; public static final String CSV_ENCODING = "encoding"; public static final String CSV_SKIP_UTF_8_BOM = "skipUTF8BOM"; + public static final String CSV_TRIM_VALUES_PARSING = "trimValuesForParsing"; private String csvFile; private boolean skipComments = true; @@ -62,6 +62,7 @@ public class CSVResultSetConfiguration implements DataResultSetFactory { private boolean skipUTF8BOM = false; private boolean trimLines = false; private boolean hasHeaderRow = true; + private boolean trimValuesForParsing = true; private String columnSeparators = ";"; @@ -105,6 +106,7 @@ public CSVResultSetConfiguration(CSVExampleSource csvExampleSource) throws Opera setQuoteCharacter(csvExampleSource.getParameterAsChar(CSVExampleSource.PARAMETER_QUOTES_CHARACTER)); } encoding = Encoding.getEncoding(csvExampleSource); + trimValuesForParsing = csvExampleSource.trimForGuessing(); } @Override @@ -252,6 +254,27 @@ public void setHeaderRow(int headerRow) { this.headerRow = headerRow; } + /** + * Whether values should be trimmed for parsing + * + * @return {@code true} if they should be trimmed + * @since 9.1.1 + */ + public boolean trimValuesForParsing() { + return trimValuesForParsing; + } + + /** + * Set whether values should be trimmed for parsing + * + * @param trimValuesForParsing + * {@code true} if they should be trimmed + * @since 9.1.1 + */ + public void setTrimValuesForParsing(boolean trimValuesForParsing) { + this.trimValuesForParsing = trimValuesForParsing; + } + @Override public String getResourceName() { return getCsvFile(); @@ -288,6 +311,7 @@ public Map getParameterMap() { parameterMap.put(CSV_TRIM_LINES, String.valueOf(isTrimLines())); parameterMap.put(CSV_ENCODING, String.valueOf(getEncoding())); parameterMap.put(CSV_SKIP_UTF_8_BOM, String.valueOf(isSkippingUTF8BOM())); + parameterMap.put(CSV_TRIM_VALUES_PARSING, String.valueOf(trimValuesForParsing)); return parameterMap; } } diff --git a/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslationConfiguration.java b/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslationConfiguration.java index 302a04213..1b5fb866c 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslationConfiguration.java +++ b/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslationConfiguration.java @@ -39,6 +39,7 @@ import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; +import java.util.stream.IntStream; import com.rapidminer.example.Attributes; import com.rapidminer.example.table.DataRowFactory; @@ -82,6 +83,8 @@ public class DataResultSetTranslationConfiguration { private boolean trimAttributeNames = true; + private boolean trimForGuessing = true; + /** * This constructor can be used to generate an empty configuration just depending on the given * resultSet @@ -91,9 +94,6 @@ public class DataResultSetTranslationConfiguration { */ public DataResultSetTranslationConfiguration(AbstractDataResultSetReader readerOperator) { this(readerOperator, null); - if (readerOperator != null) { - trimAttributeNames = readerOperator.shouldTrimAttributeNames(); - } } /** @@ -172,8 +172,12 @@ public void reconfigure(AbstractDataResultSetReader readerOperator) { columnMetaData = readColumnMetaData(readerOperator); setFaultTolerant(readerOperator.getParameterAsBoolean(AbstractDataResultSetReader.PARAMETER_ERROR_TOLERANT)); + trimAttributeNames = readerOperator.shouldTrimAttributeNames(); + trimForGuessing = readerOperator.trimForGuessing(); } else { annotationsMap.put(0, ANNOTATION_NAME); + trimAttributeNames = true; + trimForGuessing = true; } } @@ -236,21 +240,8 @@ public ColumnMetaData getColumnMetaData(int col) { * This will return all indices of each selected column */ public int[] getSelectedIndices() { - int numberOfSelected = 0; - int[] selectedIndices = new int[columnMetaData.length]; - for (int i = 0; i < selectedIndices.length; i++) { - if (columnMetaData[i].isSelected()) { - selectedIndices[numberOfSelected] = i; - numberOfSelected++; - } - } - if (numberOfSelected < selectedIndices.length) { - int[] result = new int[numberOfSelected]; - System.arraycopy(selectedIndices, 0, result, 0, numberOfSelected); - return result; - } else { - return selectedIndices; - } + return IntStream.range(0, columnMetaData.length). + filter(i -> columnMetaData[i].isSelected()).toArray(); } /** @@ -261,9 +252,7 @@ public String getAnnotation(int line) { } public SortedSet getAnnotatedRowIndices() { - SortedSet result = new TreeSet<>(); - result.addAll(annotationsMap.keySet()); - return result; + return new TreeSet<>(annotationsMap.keySet()); } public Map getAnnotationsMap() { @@ -275,16 +264,12 @@ public Map getAnnotationsMap() { * selected. */ public int getNameRow() { - if (annotationsMap == null) { - return -1; - } else { - for (Entry entry : annotationsMap.entrySet()) { - if (Annotations.ANNOTATION_NAME.equals(entry.getValue())) { - return entry.getKey(); - } + for (Entry entry : annotationsMap.entrySet()) { + if (Annotations.ANNOTATION_NAME.equals(entry.getValue())) { + return entry.getKey(); } - return -1; } + return -1; } public int getNumerOfColumns() { @@ -304,7 +289,7 @@ public boolean isFaultTolerant() { } public int getLastAnnotatedRowIndex() { - if (annotationsMap == null || annotationsMap.isEmpty()) { + if (annotationsMap.isEmpty()) { return -1; } SortedSet annotatedRows = getAnnotatedRowIndices(); @@ -437,6 +422,27 @@ public static ColumnMetaData[] readColumnMetaData(AbstractDataResultSetReader re return columnMetaData; } + /** + * Indicates if values should be trimmed for type guessing + * + * @return {@code true} if values should be trimmed for type guessing + * @since 9.1.1 + */ + public boolean trimForGuessing() { + return trimForGuessing; + } + + /** + * Indicates if values should be trimmed for type guessing + * + * @param trimForGuessing + * if parameters should be trimmed for guessing + * @since 9.1.1 + */ + public void setTrimForGuessing(boolean trimForGuessing) { + this.trimForGuessing = trimForGuessing; + } + /** * Simple wrapper class for a {@link UserError}. * diff --git a/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslator.java b/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslator.java index 5793c9749..5ea2f28b3 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslator.java +++ b/src/main/java/com/rapidminer/operator/nio/model/DataResultSetTranslator.java @@ -22,7 +22,6 @@ import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -391,7 +390,7 @@ private double getStringIndex(Attribute attribute, DataResultSet dataResultSet, private String getString(DataResultSet dataResultSet, int row, int column, boolean isFaultTolerant) throws UserError { try { String string = dataResultSet.getString(column); - if (operator.getCompatibilityLevel().isAbove(BEFORE_ATTRIBUTE_TRIMMING)) { + if (operator == null || operator.getCompatibilityLevel().isAbove(BEFORE_ATTRIBUTE_TRIMMING)) { string = string == null ? null : string.trim(); } return string; @@ -504,8 +503,6 @@ private int[] guessValueTypes(int[] definedTypes, DataResultSetTranslationConfig if (listener != null) { listener.setCompleted(1); } - int[] columnValueTypes = new int[dataResultSet.getNumberOfColumns()]; - Arrays.fill(columnValueTypes, Ontology.INTEGER); // TODO: The following could be made more efficient using an indirect indexing to access the // columns: would @@ -601,6 +598,10 @@ private int[] guessValueTypes(int[] definedTypes, DataResultSetTranslationConfig } else { // for strings, we try parsing ourselves // fill value buffer for binominal assessment + // trim value + if (stringRepresentation != null && configuration.trimForGuessing()) { + stringRepresentation = stringRepresentation.trim(); + } definedTypes[column] = guessValueType(definedTypes[column], stringRepresentation, !nominalValues[column].moreThanTwo, dateFormat, numberFormat); } @@ -615,28 +616,19 @@ private int[] guessValueTypes(int[] definedTypes, DataResultSetTranslationConfig return definedTypes; } + /** * This method tries to guess the value type by taking into account the current guessed type and * the string value. The type will be transformed to more general ones. */ private int guessValueType(int currentValueType, String value, boolean onlyTwoValues, DateFormat dateFormat, NumberFormat numberFormat) { - if (operator != null && operator.getCompatibilityLevel().isAtMost(VERSION_6_0_3)) { - if (currentValueType == Ontology.POLYNOMINAL) { - return currentValueType; - } - if (currentValueType == Ontology.BINOMINAL) { - if (onlyTwoValues) { - return Ontology.BINOMINAL; - } else { - return Ontology.POLYNOMINAL; - } - } - } else { - if (currentValueType == Ontology.BINOMINAL || currentValueType == Ontology.POLYNOMINAL) { - // Don't set to binominal type, it fails too often. - return Ontology.POLYNOMINAL; - } + if (onlyTwoValues && operator != null && operator.getCompatibilityLevel().isAtMost(VERSION_6_0_3) + && currentValueType == Ontology.BINOMINAL) { + return Ontology.BINOMINAL; + } else if (currentValueType == Ontology.BINOMINAL || currentValueType == Ontology.POLYNOMINAL) { + // Don't set to binominal type, it fails too often. + return Ontology.POLYNOMINAL; } if (currentValueType == Ontology.DATE) { @@ -655,14 +647,14 @@ private int guessValueType(int currentValueType, String value, boolean onlyTwoVa if (numberFormat != null) { try { numberFormat.parse(value); - return currentValueType; + return Ontology.REAL; } catch (ParseException e) { return guessValueType(Ontology.DATE, value, onlyTwoValues, dateFormat, numberFormat); } } else { try { Double.parseDouble(value); - return currentValueType; + return Ontology.REAL; } catch (NumberFormatException e) { return guessValueType(Ontology.DATE, value, onlyTwoValues, dateFormat, null); } @@ -710,9 +702,6 @@ public Collection getErrors() { } public ParsingError getErrorByExampleIndexAndColumn(int row, int column) { - if (errors == null) { - return null; - } return errors.get(new Pair<>(row, column)); } diff --git a/src/main/java/com/rapidminer/operator/nio/model/DefaultPreview.java b/src/main/java/com/rapidminer/operator/nio/model/DefaultPreview.java index 4216df65d..1a71d2e5a 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/DefaultPreview.java +++ b/src/main/java/com/rapidminer/operator/nio/model/DefaultPreview.java @@ -60,7 +60,7 @@ public void read(DataResultSet resultSet, ProgressListener listener) throws Oper if (listener != null) { listener.setTotal(previewSize); } - List dataList = new LinkedList(); + List dataList = new LinkedList<>(); resultSet.reset(listener); while (resultSet.hasNext() && dataList.size() < previewSize) { resultSet.next(listener); diff --git a/src/main/java/com/rapidminer/operator/nio/model/ExcelResultSet.java b/src/main/java/com/rapidminer/operator/nio/model/ExcelResultSet.java index 533707cc7..936301189 100644 --- a/src/main/java/com/rapidminer/operator/nio/model/ExcelResultSet.java +++ b/src/main/java/com/rapidminer/operator/nio/model/ExcelResultSet.java @@ -318,10 +318,8 @@ public Date getDate(int columnIndex) throws ParseException { Date date = ((DateCell) cell).getDate(); // hack to get actual date written in excel sheet. converts date to UTC - int offset = TimeZone.getDefault().getOffset(date.getTime()); - date.setTime(date.getTime() - offset); - - return date; + int offset = TimeZone.getDefault().getOffset(date.getTime()); + return new Date(date.getTime() - offset); } else { String valueString = cell.getContents(); DateFormat dateFormat = dateFormatProvider.geDateFormat(); diff --git a/src/main/java/com/rapidminer/operator/performance/cost/ClassificationCostCriterion.java b/src/main/java/com/rapidminer/operator/performance/cost/ClassificationCostCriterion.java index 172630f1b..b1f212baf 100644 --- a/src/main/java/com/rapidminer/operator/performance/cost/ClassificationCostCriterion.java +++ b/src/main/java/com/rapidminer/operator/performance/cost/ClassificationCostCriterion.java @@ -23,13 +23,14 @@ import com.rapidminer.example.Attribute; import com.rapidminer.example.Example; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.performance.MeasuredPerformance; import com.rapidminer.tools.math.Averagable; /** * This performance Criterion works with a given cost matrix. Every classification result creates - * costs. Costs should be minimized since that the fitness is - cost. + * costs. Costs should be minimized since that the fitness is - cost (-getMikroAverage()). * * @author Sebastian Land */ @@ -46,6 +47,22 @@ public class ClassificationCostCriterion extends MeasuredPerformance { Attribute predictedLabel; private final Map classOrderMap; + /** + * Behaves like the pre 9.0.3 + * @since 9.0.3 + */ + private static final int BROKEN_FITNESS = 0; + /** + * Reserved for future use + * @since 9.0.3 + */ + private static final int AFTER_BROKEN_FITNESS = 1; + /** + * If the version field is missing from a serialized object, the default value is used (0 = BROKEN_FITNESS) + * @since 9.0.3 + */ + private int version = AFTER_BROKEN_FITNESS; + /** * Clone constructor * @@ -89,6 +106,9 @@ public ClassificationCostCriterion(ClassificationCostCriterion other) { } else { this.costMatrix = null; } + this.totalCosts = other.totalCosts; + this.totalExampleCount = other.totalExampleCount; + this.version = other.version; } /** @@ -145,12 +165,20 @@ public void countExample(Example example) { @Override public double getExampleCount() { - return exampleCount; + if (version == BROKEN_FITNESS) { + return exampleCount; + } else { + return totalExampleCount; + } } @Override public double getFitness() { - return -costs; + if (version == BROKEN_FITNESS) { + return -costs; + } else { + return -getMikroAverage(); + } } @Override @@ -167,7 +195,11 @@ public double getMikroAverage() { @Override public double getMikroVariance() { - return 0; + if (version == BROKEN_FITNESS) { + return 0; + } else { + return Double.NaN; + } } /** @@ -188,4 +220,18 @@ protected double getTotalCosts() { return totalCosts; } + /** + * Makes this criterion behave like the given version + * + * @param compatibilityLevel + * the compatibility level + * @since 9.0.3 + */ + public void setVersion(OperatorVersion compatibilityLevel) { + if (compatibilityLevel.isAtMost(CostEvaluator.WRONG_FITNESS)) { + this.version = BROKEN_FITNESS; + } else { + this.version = AFTER_BROKEN_FITNESS; + } + } } diff --git a/src/main/java/com/rapidminer/operator/performance/cost/CostEvaluator.java b/src/main/java/com/rapidminer/operator/performance/cost/CostEvaluator.java index dc6d8973b..4c7616008 100644 --- a/src/main/java/com/rapidminer/operator/performance/cost/CostEvaluator.java +++ b/src/main/java/com/rapidminer/operator/performance/cost/CostEvaluator.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang.ArrayUtils; + import com.rapidminer.example.Attribute; import com.rapidminer.example.Attributes; import com.rapidminer.example.Example; @@ -30,9 +32,9 @@ import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.UserError; import com.rapidminer.operator.ValueDouble; -import com.rapidminer.operator.performance.MeasuredPerformance; import com.rapidminer.operator.performance.PerformanceVector; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.OutputPort; @@ -59,6 +61,9 @@ public class CostEvaluator extends Operator { private static final String PARAMETER_CLASS_NAME = "class_name"; private static final String PARAMETER_CLASS_DEFINITION = "class_order_definition"; + /** Up to and including version 9.0.2 the wrong fitness was returned by the ClassificationCostCriterion */ + static final OperatorVersion WRONG_FITNESS = new OperatorVersion(9, 0, 2); + private InputPort exampleSetInput = getInputPorts().createPort("example set"); private OutputPort exampleSetOutput = getOutputPorts().createPort("example set"); @@ -103,7 +108,7 @@ public void doWork() throws OperatorException { .transformString2Enumeration(getParameterAsString(PARAMETER_CLASS_DEFINITION)); if (enumeratedValues.length > 0) { - classOrderMap = new HashMap(); + classOrderMap = new HashMap<>(); int i = 0; for (String className : enumeratedValues) { @@ -126,7 +131,8 @@ public void doWork() throws OperatorException { } } - MeasuredPerformance criterion = new ClassificationCostCriterion(costMatrix, classOrderMap, label, predictedLabel); + ClassificationCostCriterion criterion = new ClassificationCostCriterion(costMatrix, classOrderMap, label, predictedLabel); + criterion.setVersion(getCompatibilityLevel()); PerformanceVector performance = new PerformanceVector(); performance.addCriterion(criterion); // now measuring costs @@ -160,4 +166,10 @@ public List getParameterTypes() { new ParameterTypeString(PARAMETER_CLASS_NAME, "The name of the class."), false)); return types; } + + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + return (OperatorVersion[]) ArrayUtils.addAll(super.getIncompatibleVersionChanges(), + new OperatorVersion[]{WRONG_FITNESS}); + } } diff --git a/src/main/java/com/rapidminer/operator/performance/cost/RankingCriterion.java b/src/main/java/com/rapidminer/operator/performance/cost/RankingCriterion.java index 45c71f57e..3592e454b 100644 --- a/src/main/java/com/rapidminer/operator/performance/cost/RankingCriterion.java +++ b/src/main/java/com/rapidminer/operator/performance/cost/RankingCriterion.java @@ -24,6 +24,7 @@ import com.rapidminer.example.Attributes; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.performance.MeasuredPerformance; import com.rapidminer.tools.math.Averagable; @@ -38,6 +39,22 @@ public class RankingCriterion extends MeasuredPerformance { private static final long serialVersionUID = -7466139591781285005L; + /** + * Behaves like the pre 9.0.3 + * @since 9.0.3 + */ + private static final int BROKEN_FITNESS = 0; + /** + * Reserved for future use + * @since 9.0.3 + */ + private static final int AFTER_BROKEN_FITNESS = 1; + /** + * If the version field is missing from a serialized object, the default value is used (0 = BROKEN_FITNESS) + * @since 9.0.3 + */ + private int version = AFTER_BROKEN_FITNESS; + private double costs; private Attribute label; private Attribute[] confidenceAttributes; @@ -46,6 +63,33 @@ public class RankingCriterion extends MeasuredPerformance { private double[] rankIntervallCost; private HashMap confidenceAttributesMap = new HashMap(); + /** + * Clone Constructor + * @since 9.0.3 + */ + public RankingCriterion(RankingCriterion other) { + super(other); + this.costs = other.costs; + if (other.label != null) { + this.label = (Attribute) other.label.clone(); + } + if (other.confidenceAttributes != null) { + this.confidenceAttributes = new Attribute[other.confidenceAttributes.length]; + for (int i = 0; i < other.confidenceAttributes.length; i++) { + if (other.confidenceAttributes[i] != null) { + this.confidenceAttributes[i] = (Attribute) other.confidenceAttributes[i].clone(); + } else { + this.confidenceAttributes[i] = null; + } + } + } + this.exampleCount = other.exampleCount; + this.rankIntervallStarts = other.rankIntervallStarts != null ? other.rankIntervallStarts.clone() : null; + this.rankIntervallCost = other.rankIntervallCost != null ? other.rankIntervallCost.clone() : null; + this.confidenceAttributesMap = other.confidenceAttributesMap != null ? new HashMap<>(other.confidenceAttributesMap) : null; + this.version = other.version; + } + public RankingCriterion(int[] rankIntervallStarts, double[] rankIntervallCost, ExampleSet exampleSet) { label = exampleSet.getAttributes().getLabel(); this.rankIntervallStarts = rankIntervallStarts; @@ -102,11 +146,21 @@ public double getExampleCount() { @Override public double getFitness() { - return -costs; + if (version == BROKEN_FITNESS) { + return -costs; + } else { + return -getMikroAverage(); + } } @Override - protected void buildSingleAverage(Averagable averagable) {} + protected void buildSingleAverage(Averagable averagable) { + if (version != BROKEN_FITNESS) { + RankingCriterion criterion = (RankingCriterion) averagable; + this.costs += criterion.costs; + this.exampleCount += criterion.exampleCount; + } + } @Override public double getMikroAverage() { @@ -115,7 +169,26 @@ public double getMikroAverage() { @Override public double getMikroVariance() { - return 0; + if (version == BROKEN_FITNESS) { + return 0; + } else { + return Double.NaN; + } + } + + /** + * Makes this criterion behave like the given version + * + * @param compatibilityLevel + * The compatibility level + * @since 9.0.3 + */ + public void setVersion(OperatorVersion compatibilityLevel) { + if (compatibilityLevel.isAtMost(RankingEvaluator.WRONG_FITNESS)) { + this.version = BROKEN_FITNESS; + } else { + this.version = AFTER_BROKEN_FITNESS; + } } } diff --git a/src/main/java/com/rapidminer/operator/performance/cost/RankingEvaluator.java b/src/main/java/com/rapidminer/operator/performance/cost/RankingEvaluator.java index 4a8d0a616..d17af898e 100644 --- a/src/main/java/com/rapidminer/operator/performance/cost/RankingEvaluator.java +++ b/src/main/java/com/rapidminer/operator/performance/cost/RankingEvaluator.java @@ -19,9 +19,12 @@ package com.rapidminer.operator.performance.cost; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.logging.Level; +import org.apache.commons.lang.ArrayUtils; + import com.rapidminer.example.Attributes; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; @@ -29,10 +32,10 @@ import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.ProcessSetupError; import com.rapidminer.operator.SimpleProcessSetupError; import com.rapidminer.operator.ValueDouble; -import com.rapidminer.operator.performance.MeasuredPerformance; import com.rapidminer.operator.performance.PerformanceCriterion; import com.rapidminer.operator.performance.PerformanceVector; import com.rapidminer.operator.ports.InputPort; @@ -62,6 +65,9 @@ public class RankingEvaluator extends Operator { private static final String PARAMETER_RANK_START = "rank_interval_start"; private static final String PARAMETER_RANK_COST = "costs"; + /** Up to and including version 9.0.2 the wrong fitness was returned by the RankingCriterion */ + static final OperatorVersion WRONG_FITNESS = new OperatorVersion(9, 0, 2); + private InputPort exampleSetInput = getInputPorts().createPort("example set"); private OutputPort exampleSetOutput = getOutputPorts().createPort("example set"); @@ -100,17 +106,21 @@ public void doWork() throws OperatorException { ExampleSet exampleSet = exampleSetInput.getData(ExampleSet.class); Tools.hasNominalLabels(exampleSet, getOperatorClassName()); List rankings = getParameterList(PARAMETER_RANKING_COSTS); + // Sort rankings + if (getCompatibilityLevel().isAbove(WRONG_FITNESS)) { + rankings.sort(Comparator.comparingInt(o -> Integer.parseInt(o[0]))); + } int i = 0; double[] costs = new double[rankings.size()]; int[] indices = new int[rankings.size()]; for (String[] pair : rankings) { - indices[i] = Integer.valueOf(pair[0]); - costs[i] = Double.valueOf(pair[1]); - // TODO: Check if correctly sorted or sort automatically + indices[i] = Integer.parseInt(pair[0]); + costs[i] = Double.parseDouble(pair[1]); i++; } - MeasuredPerformance criterion = new RankingCriterion(indices, costs, exampleSet); + RankingCriterion criterion = new RankingCriterion(indices, costs, exampleSet); + criterion.setVersion(getCompatibilityLevel()); performance = new PerformanceVector(); performance.addCriterion(criterion); // now measuring costs @@ -158,4 +168,10 @@ public List getParameterTypes() { types.add(type); return types; } + + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + return (OperatorVersion[]) ArrayUtils.addAll(super.getIncompatibleVersionChanges(), + new OperatorVersion[]{WRONG_FITNESS}); + } } diff --git a/src/main/java/com/rapidminer/operator/ports/DeliveringPortIdentifier.java b/src/main/java/com/rapidminer/operator/ports/DeliveringPortIdentifier.java new file mode 100644 index 000000000..a3b3e9d38 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/ports/DeliveringPortIdentifier.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2001-2018 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.operator.ports; + +import com.rapidminer.operator.Operator; +import com.rapidminer.operator.UserData; + + +/** + * This class helps to identify an {@link OutputPort}. Resolving can be done using the {@link DeliveringPortManager}. + * + * @author Andreas Timm + * @since 9.1 + */ +public class DeliveringPortIdentifier implements UserData { + /** + * A default ID for an {@link OutputPort} that is an outer {@link OutputPort}. + */ + static final int DEFAULT_SUBPROCESS_ID = -1; + + private final String operatorName; + private final String portName; + private final int subprocessId; + + + /** + * Constructor to identify an {@link OutputPort} of a normal {@link Operator} + * + * @param operatorName + * that equals {@link Operator#getName()} + * @param portName + * that equals {@link Port#getName()} + */ + DeliveringPortIdentifier(String operatorName, String portName) { + this(operatorName, portName, DEFAULT_SUBPROCESS_ID); + } + + /** + * Constructor to identify an internal {@link Port} of a {@link com.rapidminer.operator.OperatorChain OperatorChain} + * and therefore requires the ID of the subprocess. + * + * @param operatorName + * that equals {@link Operator#getName()} + * @param portName + * that equals {@link Port#getName()} + * @param subprocessId + * ID of the subprocess that is the {@link Ports} -> {@link PortOwner#getPortHandler()} in the operatorName's {@link Operator} + */ + DeliveringPortIdentifier(String operatorName, String portName, int subprocessId) { + this.operatorName = operatorName; + this.portName = portName; + if (subprocessId < 0) { + this.subprocessId = DEFAULT_SUBPROCESS_ID; + } else { + this.subprocessId = subprocessId; + } + } + + /** + * {@link Operator Operator's} name to be resolvable using + * {@link com.rapidminer.Process#getOperator(String) Process.getOperator(String)} + */ + public String getOperatorName() { + return operatorName; + } + + /** + * Name of the {@link OutputPort} to be resolvable using {@link OutputPorts#getPortByName(String)} + */ + public String getPortName() { + return portName; + } + + /** + * ID of the {@link com.rapidminer.operator.ExecutionUnit ExecutionUnit} (subprocess) if the + * {@link OutputPort} resides inside an {@link com.rapidminer.operator.OperatorChain OperatorChain} + */ + public int getSubprocessId() { + return subprocessId; + } + + @Override + public String toString() { + String subprocessPart = subprocessId != DEFAULT_SUBPROCESS_ID ? ":" + subprocessId : ""; + return operatorName + subprocessPart + "/" + portName; + } + + @Override + public UserData copyUserData(Object newParent) { + return new DeliveringPortIdentifier(operatorName, portName, subprocessId); + } +} diff --git a/src/main/java/com/rapidminer/operator/ports/DeliveringPortManager.java b/src/main/java/com/rapidminer/operator/ports/DeliveringPortManager.java new file mode 100644 index 000000000..cb881f784 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/ports/DeliveringPortManager.java @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2001-2018 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.operator.ports; + +import com.rapidminer.Process; +import com.rapidminer.operator.IOObject; +import com.rapidminer.operator.Operator; +import com.rapidminer.operator.OperatorChain; + + +/** + * This util helps resolving the {@link OutputPort} that is identified by an {@link DeliveringPortIdentifier} + * + * @author Andreas Timm + * @since 9.1 + */ +public final class DeliveringPortManager { + /** + * Key for the last delivering port which can be used in {@link IOObject}s + */ + public static final String LAST_DELIVERING_PORT = "last_delivering_port"; + + /** + * Util class, instantiation not supported + */ + private DeliveringPortManager() { + throw new UnsupportedOperationException("Instantiation not supported"); + } + + /** + * Store the {@link Operator} and {@link Port} as last delivering port in the user data of the {@link IOObject}. + * If the given port is an {@link InputPort}, it's {@link InputPort#getSource() source} will be stored instead. + * + * @param ioObject + * which passed through the {@link Port} and should hold this information in its {@link IOObject#getUserData(String)} + * @param port + * the {@link Port} that delivered this ioObject + * @see #resolve(Process, DeliveringPortIdentifier) + */ + public static void setLastDeliveringPort(IOObject ioObject, Port port) { + if (port instanceof InputPort) { + // always store an output port + port = ((InputPort) port).getSource(); + } + PortOwner owner = port.getPorts().getOwner(); + OperatorChain portHandler = owner.getPortHandler(); + Operator operator = owner.getOperator(); + int executionUnitId = DeliveringPortIdentifier.DEFAULT_SUBPROCESS_ID; + if (operator == portHandler) { + executionUnitId = portHandler.getSubprocesses().indexOf(owner.getConnectionContext()); + } + ioObject.setUserData(LAST_DELIVERING_PORT, new DeliveringPortIdentifier(operator.getName(), port.getName(), executionUnitId)); + } + + /** + * Find an {@link OutputPort} using the information in a {@link DeliveringPortIdentifier} from the currently + * visible Process in Studio. + * + * @param process + * the {@link Process} in which the {@link OutputPort} should be searched + * @param identifier + * with sufficient information to find the {@link OutputPort} + * @return the identified {@link OutputPort} or null + */ + public static OutputPort resolve(Process process, DeliveringPortIdentifier identifier) { + if (identifier == null || identifier.getOperatorName() == null || identifier.getPortName() == null || process == null) { + return null; + } + final Operator operator = process.getOperator(identifier.getOperatorName()); + if (operator == null) { + return null; + } + if (identifier.getSubprocessId() >= 0) { + if (operator instanceof OperatorChain && identifier.getSubprocessId() < ((OperatorChain) operator).getNumberOfSubprocesses()) { + return ((OperatorChain) operator).getSubprocess(identifier.getSubprocessId()).getInnerSources().getPortByName(identifier.getPortName()); + } + return null; + } else { + return operator.getOutputPorts().getPortByName(identifier.getPortName()); + } + } + + /** + * Shorthand method to get the last delivering {@link OutputPort} from the given process which was stored in the + * ioObject's userdata. + * + * @param process + * the {@link Process} that contains the to be returned {@link OutputPort} + * @param ioObject + * the {@link IOObject} that was delivered lately + * @return the last registered {@link OutputPort} from the ioObject's userdata, may be null + */ + public static OutputPort getLastDeliveringPort(Process process, IOObject ioObject) { + if (process == null || ioObject == null) { + return null; + } + return resolve(process, (DeliveringPortIdentifier) ioObject.getUserData(LAST_DELIVERING_PORT)); + } +} diff --git a/src/main/java/com/rapidminer/operator/ports/impl/OutputPortImpl.java b/src/main/java/com/rapidminer/operator/ports/impl/OutputPortImpl.java index 05a237b79..6bc464885 100644 --- a/src/main/java/com/rapidminer/operator/ports/impl/OutputPortImpl.java +++ b/src/main/java/com/rapidminer/operator/ports/impl/OutputPortImpl.java @@ -22,6 +22,7 @@ import com.rapidminer.adaption.belt.AtPortConverter; import com.rapidminer.operator.DebugMode; import com.rapidminer.operator.IOObject; +import com.rapidminer.operator.ports.DeliveringPortManager; import com.rapidminer.operator.ports.OutputPorts; import com.rapidminer.operator.ports.Port; import com.rapidminer.operator.ports.Ports; @@ -34,7 +35,7 @@ public class OutputPortImpl extends AbstractOutputPort { - /** Use the factory method {@link OutputPorts#createPort()} to create OutputPorts. */ + /** Use the factory method {@link OutputPorts#createPort(String)} to create OutputPorts. */ protected OutputPortImpl(Ports owner, String name, boolean simulatesStack) { super(owner, name, simulatesStack); } @@ -48,7 +49,7 @@ public void deliver(IOObject object) { // registering history of object if (object != null) { object.appendOperatorToHistory(getPorts().getOwner().getOperator(), this); - + DeliveringPortManager.setLastDeliveringPort(object, this); // set source if not yet set if (object.getSource() == null) { if (getPorts().getOwner().getOperator() != null) { diff --git a/src/main/java/com/rapidminer/operator/preprocessing/filter/Date2Numerical.java b/src/main/java/com/rapidminer/operator/preprocessing/filter/Date2Numerical.java index 8a888bb4c..2f8a106ba 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/filter/Date2Numerical.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/filter/Date2Numerical.java @@ -18,6 +18,7 @@ */ package com.rapidminer.operator.preprocessing.filter; +import java.util.Arrays; import java.util.Calendar; import java.util.List; @@ -28,6 +29,7 @@ import com.rapidminer.example.table.AttributeFactory; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.UserError; import com.rapidminer.operator.annotation.ResourceConsumptionEstimator; import com.rapidminer.operator.error.AttributeNotFoundError; @@ -66,6 +68,12 @@ public class Date2Numerical extends AbstractDateDataProcessing { public static final String PARAMETER_KEEP_OLD_ATTRIBUTE = "keep_old_attribute"; + /** + * Last version to use {@link Ontology#INTEGER}, afterwards {@link Ontology#REAL} is used + * @since 9.0.2 + */ + public static final OperatorVersion VERSION_USING_INTEGER = new OperatorVersion(9, 0, 1); + Calendar calendar = null; public Date2Numerical(OperatorDescription description) { @@ -83,7 +91,7 @@ protected MetaData modifyMetaData(ExampleSetMetaData metaData) throws UndefinedP AttributeMetaData amd = metaData.getAttributeByName(getParameterAsString(PARAMETER_ATTRIBUTE_NAME)); if (amd != null) { AttributeMetaData newAttribute = amd.clone(); - newAttribute.setType(Ontology.INTEGER); + newAttribute.setType(getTargetType()); newAttribute.getMean().setUnkown(); newAttribute.setValueSetRelation(SetRelation.UNKNOWN); if (!getParameterAsBoolean(PARAMETER_KEEP_OLD_ATTRIBUTE)) { @@ -111,7 +119,7 @@ public ExampleSet apply(ExampleSet exampleSet) throws OperatorException { throw new UserError(this, 218, dateAttribute.getName(), Ontology.ATTRIBUTE_VALUE_TYPE.mapIndex(valueType)); } - Attribute newAttribute = AttributeFactory.createAttribute(Ontology.INTEGER); + Attribute newAttribute = AttributeFactory.createAttribute(getTargetType()); exampleSet.getExampleTable().addAttribute(newAttribute); exampleSet.getAttributes().addRegular(newAttribute); @@ -270,4 +278,20 @@ public ResourceConsumptionEstimator getResourceConsumptionEstimator() { return OperatorResourceConsumptionHandler .getResourceConsumptionEstimator(getInputPort(), Date2Numerical.class, null); } + + @Override + public OperatorVersion[] getIncompatibleVersionChanges() { + OperatorVersion[] changes = super.getIncompatibleVersionChanges(); + changes = Arrays.copyOf(changes, changes.length + 1); + changes[changes.length - 1] = VERSION_USING_INTEGER; + return changes; + } + + /** + * Returns the version dependent target type + * @return either {@link Ontology#INTEGER} or {@link Ontology#REAL} + */ + private int getTargetType(){ + return getCompatibilityLevel().isAtMost(VERSION_USING_INTEGER) ? Ontology.INTEGER : Ontology.REAL; + } } diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/Example2AttributePivoting.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/Example2AttributePivoting.java index 9f07721b1..515705802 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/transformation/Example2AttributePivoting.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/Example2AttributePivoting.java @@ -70,6 +70,7 @@ *

    * * @author Tobias Malbrecht + * @deprecated since 9.1.0, use {@link com.rapidminer.operator.preprocessing.transformation.pivot.PivotOperator} instead */ public class Example2AttributePivoting extends ExampleSetTransformationOperator { diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationFunction.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationFunction.java index 561212e98..ab24565ed 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationFunction.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationFunction.java @@ -20,6 +20,7 @@ import java.lang.reflect.Constructor; import java.util.AbstractMap; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -80,38 +81,48 @@ public abstract class AggregationFunction { public static final String FUNCTION_NAME_MAXIMUM = "maximum"; public static final String FUNCTION_NAME_LOG_PRODUCT = "log product"; public static final String FUNCTION_NAME_PRODOCT = "product"; + public static final String FUNCTION_NAME_PERCENTILE = "percentile (75)"; public static final String FUNCTION_NAME_MODE = "mode"; public static final String FUNCTION_NAME_LEAST = "least"; public static final String FUNCTION_NAME_LEAST_ONLY_OCCURRING = "least (only occurring)"; public static final String FUNCTION_NAME_CONCATENATION = "concatenation"; - public static final Map> AGGREATION_FUNCTIONS = new TreeMap<>(); + private static final List CUSTOMIZABLE_AGGREGATION_FUNCTIONS = new ArrayList<>(); + + private static final Map> AGGREGATION_FUNCTIONS = new TreeMap<>(); + static { // numerical/date - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_SUM, SumAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_SUM_FRACTIONAL, SumFractionalAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_MEDIAN, MedianAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_AVERAGE, MeanAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_VARIANCE, VarianceAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_STANDARD_DEVIATION, StandardDeviationAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_MINIMUM, MinAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_MAXIMUM, MaxAggregationFunction.class); - - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_LOG_PRODUCT, LogProductAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_PRODOCT, ProductAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_SUM, SumAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_SUM_FRACTIONAL, SumFractionalAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_MEDIAN, MedianAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_AVERAGE, MeanAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_VARIANCE, VarianceAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_STANDARD_DEVIATION, StandardDeviationAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_MINIMUM, MinAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_MAXIMUM, MaxAggregationFunction.class); + + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_LOG_PRODUCT, LogProductAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_PRODOCT, ProductAggregationFunction.class); + + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_PERCENTILE, PercentileAggregationFunction.class); // numerical/date/nominal - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_IGNORE_MISSINGS, CountIgnoringMissingsAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_INCLUDE_MISSINGS, CountIncludingMissingsAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_COUNT, CountAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_FRACTIONAL, CountFractionalAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_PERCENTAGE, CountPercentageAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_IGNORE_MISSINGS, CountIgnoringMissingsAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_INCLUDE_MISSINGS, CountIncludingMissingsAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_COUNT, CountAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_FRACTIONAL, CountFractionalAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_COUNT_PERCENTAGE, CountPercentageAggregationFunction.class); // Nominal Aggregations - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_MODE, ModeAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_LEAST, LeastAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_LEAST_ONLY_OCCURRING, LeastOccurringAggregationFunction.class); - AGGREATION_FUNCTIONS.put(FUNCTION_NAME_CONCATENATION, ConcatAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_MODE, ModeAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_LEAST, LeastAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_LEAST_ONLY_OCCURRING, LeastOccurringAggregationFunction.class); + AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_CONCATENATION, ConcatAggregationFunction.class); + + // customizable + CUSTOMIZABLE_AGGREGATION_FUNCTIONS.add(new PercentileAggregationFunction( + AttributeFactory.createAttribute("none", Ontology.NUMERICAL), true, true)); } /** @@ -126,7 +137,7 @@ public abstract class AggregationFunction { LEGACY_AGGREGATION_FUNCTIONS.put(FUNCTION_NAME_CONCATENATION, new AbstractMap.SimpleEntry<>(AggregationOperator.VERSION_8_2_0, ConcatAggregationFunctionLegacy.class)); } - public static final Map AGGREGATION_FUNCTIONS_META_DATA_PROVIDER = new HashMap<>(); + private static final Map AGGREGATION_FUNCTIONS_META_DATA_PROVIDER = new HashMap<>(); static { HashMap transformationRules = new HashMap() { @@ -297,13 +308,25 @@ public static final AggregationFunction createAggregationFunction(String name, A */ public static final AggregationFunction createAggregationFunction(String name, Attribute sourceAttribute, boolean ignoreMissings, boolean countOnlyDistinct, OperatorVersion version) throws OperatorException { + if (name == null) { + throw new UserError(null, "aggregation.illegal_function_name", name); + } + Class aggregationFunctionClass = null; // check if the legacy version should be used if (version != null && LEGACY_AGGREGATION_FUNCTIONS.containsKey(name) && version.isAtMost(LEGACY_AGGREGATION_FUNCTIONS.get(name).getKey())) { aggregationFunctionClass = LEGACY_AGGREGATION_FUNCTIONS.get(name).getValue(); } + // the percentile aggregation is customizable so Map.get() will not find it, so we look for it here if (aggregationFunctionClass == null) { - aggregationFunctionClass = AGGREATION_FUNCTIONS.get(name); + for (AggregationFunction function : CUSTOMIZABLE_AGGREGATION_FUNCTIONS) { + if(function.matches(name)) { + return function.newInstance(name, sourceAttribute, ignoreMissings, countOnlyDistinct); + } + } + } + if (aggregationFunctionClass == null) { + aggregationFunctionClass = AGGREGATION_FUNCTIONS.get(name); } if (aggregationFunctionClass == null) { throw new UserError(null, "aggregation.illegal_function_name", name); @@ -318,7 +341,7 @@ public static final AggregationFunction createAggregationFunction(String name, A return constructor.newInstance(sourceAttribute, ignoreMissings, countOnlyDistinct); } catch (Exception e) { throw new RuntimeException( - "All implementations of AggregationFunction need to have a constructor accepting an Attribute and boolean. Other reasons for this error may be class loader problems.", + "All implementations of AggregationFunction need to have a constructor accepting an Attribute and two boolean. Other reasons for this error may be class loader problems.", e); } } @@ -334,8 +357,16 @@ public static final AggregationFunction createAggregationFunction(String name, A */ public static final AttributeMetaData getAttributeMetaData(String aggregationFunctionName, AttributeMetaData sourceAttributeMetaData, InputPort inputPort) { - AggregationFunctionMetaDataProvider metaDataProvider = AGGREGATION_FUNCTIONS_META_DATA_PROVIDER - .get(aggregationFunctionName); + AggregationFunctionMetaDataProvider metaDataProvider = null; + // check if it is a customizable aggregation function like percentile + for (AggregationFunction function : CUSTOMIZABLE_AGGREGATION_FUNCTIONS) { + if(function.matches(aggregationFunctionName)){ + metaDataProvider = function.createMetaDataProvider(aggregationFunctionName); + } + } + if (metaDataProvider == null) { + metaDataProvider = AGGREGATION_FUNCTIONS_META_DATA_PROVIDER.get(aggregationFunctionName); + } if (metaDataProvider != null) { return metaDataProvider.getTargetAttributeMetaData(sourceAttributeMetaData, inputPort); } else { @@ -348,19 +379,62 @@ public static final AttributeMetaData getAttributeMetaData(String aggregationFun } } + /** + * If this implementation subclass is included in the CUSTOMIZABLE_AGGREGATION_FUNCTIONS list, during collecting + * metadata information this method gets called and gives the possibility to generate specialized metadata + * information based on the aggregationFunctionName from the parameters. + * + * @param aggregationFunctionName + * the customizable aggregation function name (like "percentile(23)") + * @return a specialized {@link com.rapidminer.parameter.MetaDataProvider} or null + * @since 9.0.3 + */ + protected AggregationFunctionMetaDataProvider createMetaDataProvider(String aggregationFunctionName) { + return null; + } + + /** + * If this implementation subclass is included in the CUSTOMIZABLE_AGGREGATION_FUNCTIONS list, this method can be + * overridden to match the customizable aggregationFunctionName. + * + * @param aggregationFunctionName + * the customizable aggregation function name (like "percentile(23)") + * @return true if this is a valid customized aggregationFunctionName + * @since 9.0.3 + */ + protected boolean matches(String aggregationFunctionName) { + // equals would be nice here but this function seems to have no name + return false; + } + + /** + * If this implementation subclass is included in the CUSTOMIZABLE_AGGREGATION_FUNCTIONS list, this method gets called + * to generate a new instance of the implementation with the customized aggregationFunctionName which needs to be parsed + * by the factory method to make use of the provided input. + * + * @param aggregationFunctionName + * the customizable aggregation function name (like "percentile(23)") + * @param sourceAttribute + * see AggregationFunction constructor + * @param ignoreMissings + * see AggregationFunction constructor + * @param countOnlyDistinct + * see AggregationFunction constructor + * @return an AggregationFunction instance + * @throws UserError + * in case the instantiation is not possible + */ + protected T newInstance(String aggregationFunctionName, Attribute sourceAttribute, + boolean ignoreMissings, boolean countOnlyDistinct) throws UserError { + return null; + } + /** * This method will return the array containing the names of all available aggregation * functions. The names are sorted according to natural ordering. */ public static String[] getAvailableAggregationFunctionNames() { - String[] names = new String[AGGREATION_FUNCTIONS.size()]; - int i = 0; - for (String name : AGGREATION_FUNCTIONS.keySet()) { - names[i] = name; - i++; - } - - return names; + return AGGREGATION_FUNCTIONS.keySet().toArray(new String[0]); } /** @@ -393,7 +467,7 @@ public static List getCompatibleAggregationFunctionNames(int valueType) */ public static void registerNewAggregationFunction(String name, Class clazz, AggregationFunctionMetaDataProvider metaDataProvider) { - AGGREATION_FUNCTIONS.put(name, clazz); + AGGREGATION_FUNCTIONS.put(name, clazz); AGGREGATION_FUNCTIONS_META_DATA_PROVIDER.put(name, metaDataProvider); } diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationOperator.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationOperator.java index 059bc9e6f..cdedf6fac 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationOperator.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/AggregationOperator.java @@ -269,7 +269,7 @@ protected MetaData modifyMetaData(ExampleSetMetaData metaData) throws UndefinedP if (amd.isNumerical() && getCompatibilityLevel().isAtMost(VERSION_5_1_6)) { // converting type to mimic NumericalToPolynomial used below amd.setType(Ontology.NOMINAL); - amd.setValueSet(Collections. emptySet(), SetRelation.SUPERSET); + amd.setValueSet(Collections.emptySet(), SetRelation.SUPERSET); } resultMD.addAttribute(amd); } @@ -576,8 +576,8 @@ public ExampleSet apply(ExampleSet exampleSet) throws OperatorException { } private void parseLeaf(LeafAggregationTreeNode node, double[] dataOfUpperLevels, List allGroupCombinations, - List> allAggregators, DataRowFactory factory, Attribute[] newAttributes, - List aggregationFunctions) { + List> allAggregators, DataRowFactory factory, Attribute[] newAttributes, + List aggregationFunctions) { // first copying data from groups double[] newGroupCombination = new double[dataOfUpperLevels.length]; System.arraycopy(dataOfUpperLevels, 0, newGroupCombination, 0, dataOfUpperLevels.length); @@ -609,8 +609,8 @@ private void parseLeaf(LeafAggregationTreeNode node, double[] dataOfUpperLevels, } private void parseTree(AggregationTreeNode node, Attribute[] groupAttributes, double[] dataOfUpperLevels, int groupLevel, - List allGroupCombinations, List> allAggregators, DataRowFactory factory, - Attribute[] newAttributes, boolean isCountingAllCombinations, List aggregationFunctions) + List allGroupCombinations, List> allAggregators, DataRowFactory factory, + Attribute[] newAttributes, boolean isCountingAllCombinations, List aggregationFunctions) throws UserError { Attribute currentAttribute = groupAttributes[groupLevel]; if (currentAttribute.isNominal()) { @@ -775,7 +775,7 @@ public List getParameterTypes() { @Override public OperatorVersion[] getIncompatibleVersionChanges() { return (OperatorVersion[]) ArrayUtils.addAll(super.getIncompatibleVersionChanges(), - new OperatorVersion[] { VERSION_5_1_6, VERSION_5_2_8, VERSION_6_0_6, VERSION_7_4_0, VERSION_8_2_0 }); + new OperatorVersion[]{VERSION_5_1_6, VERSION_5_2_8, VERSION_6_0_6, VERSION_7_4_0, VERSION_8_2_0}); } @Override diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/MedianAggregator.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/MedianAggregator.java index 4d9e6c4b4..fd433343d 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/MedianAggregator.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/MedianAggregator.java @@ -38,7 +38,7 @@ public class MedianAggregator extends NumericalAggregator { * This class implements an array of primitive doubles and provides getter, adder and size * methods. It is used by the {@link MedianAggregator} as a lightweight data structure. */ - private static class VariableDoubleArray { + public static class VariableDoubleArray { private static final int INITIAL_ARRAY_SIZE = 64; @@ -65,6 +65,15 @@ public void add(double value) { data[size] = value; size++; } + + public void addAll(VariableDoubleArray other) { + if (data.length < size + other.size) { + int newSize = size + other.size; + data = Arrays.copyOf(data, newSize); + } + System.arraycopy(other.data, 0, data, size, other.size); + size +=other.size; + } } private VariableDoubleArray values = null; @@ -126,7 +135,7 @@ public double getValue() { * The nth value will be selected * @return The nth value */ - private double quickNth(VariableDoubleArray values, double n) { + public static double quickNth(VariableDoubleArray values, double n) { // Choose pivot from the middle of the list double pivot = values.getArray()[values.size() / 2]; diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/NumericalAggregationFunction.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/NumericalAggregationFunction.java index 9b2221360..922ec4343 100644 --- a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/NumericalAggregationFunction.java +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/NumericalAggregationFunction.java @@ -30,11 +30,11 @@ */ public abstract class NumericalAggregationFunction extends AggregationFunction { - private Attribute targetAttribute; + protected Attribute targetAttribute; - public NumericalAggregationFunction(Attribute sourceAttribute, boolean ignoreMissings, boolean countOnlyDisctinct, + public NumericalAggregationFunction(Attribute sourceAttribute, boolean ignoreMissings, boolean countOnlyDistinct, String functionName, String separatorOpen, String separatorClose) { - super(sourceAttribute, ignoreMissings, countOnlyDisctinct); + super(sourceAttribute, ignoreMissings, countOnlyDistinct); this.targetAttribute = AttributeFactory.createAttribute(functionName + separatorOpen + getSourceAttribute().getName() + separatorClose, getTargetValueType(sourceAttribute.getValueType())); } diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregationFunction.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregationFunction.java new file mode 100644 index 000000000..2f59edb08 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregationFunction.java @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2001-2018 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.operator.preprocessing.transformation.aggregation; + +import com.rapidminer.example.Attribute; +import com.rapidminer.operator.UserError; +import com.rapidminer.tools.Ontology; + + +/** + * Percentile Aggregation Function can be used from the Aggregate Operator + * + * @author Andreas Timm + * @since 9.1.0 + */ +public class PercentileAggregationFunction extends NumericalAggregationFunction { + + public static final String FUNCTION_PERCENTILE = "percentile"; + + private double percentileValue = -1; + + public PercentileAggregationFunction(Attribute sourceAttribute, boolean ignoreMissings, boolean countOnlyDistinct) { + super(sourceAttribute, ignoreMissings, countOnlyDistinct, FUNCTION_PERCENTILE, FUNCTION_SEPARATOR_OPEN, FUNCTION_SEPARATOR_CLOSE); + } + + @Override + public Aggregator createAggregator() { + final PercentileAggregator percentileAggregator = new PercentileAggregator(this); + percentileAggregator.setPercentile(percentileValue); + return percentileAggregator; + } + + @Override + public boolean isCompatible() { + return getSourceAttribute().isNumerical(); + } + + private void setPercentile(double value) { + this.percentileValue = value; + } + + @Override + protected int getTargetValueType(int sourceValueType) { + return Ontology.REAL; + } + + @Override + protected boolean matches(String aggregationFunctionName) { + return aggregationFunctionName != null && aggregationFunctionName.startsWith(FUNCTION_PERCENTILE) + && aggregationFunctionName.indexOf('(') >= 0 && aggregationFunctionName.indexOf(')') >= 0; + } + + @Override + protected AggregationFunctionMetaDataProvider createMetaDataProvider(String aggregationFunctionName) { + return new DefaultAggregationFunctionMetaDataProvider(aggregationFunctionName, + aggregationFunctionName, FUNCTION_SEPARATOR_OPEN, + FUNCTION_SEPARATOR_CLOSE, new int[]{Ontology.NUMERICAL}, Ontology.REAL); + } + + @Override + protected PercentileAggregationFunction newInstance(String aggregationFunctionName, Attribute sourceAttribute, + boolean ignoreMissings, boolean countOnlyDistinct) throws UserError { + PercentileAggregationFunction paf = new PercentileAggregationFunction(sourceAttribute, ignoreMissings, countOnlyDistinct); + paf.setPercentile(parseAndCheckValue(aggregationFunctionName)); + String suffix = FUNCTION_SEPARATOR_OPEN + sourceAttribute.getName() + FUNCTION_SEPARATOR_CLOSE; + paf.targetAttribute.setName(aggregationFunctionName + suffix); + return paf; + } + + /** + * Read the percentile value from the input and check if the value is > 0 and <= 100 + * + * @param aggregationFunctionName + * some input that needs to have the format 'percentile (23)' or 'percentile (23.5)' + * @return the percentile as double, which is 23.5 for the input 'percentile (23.5)' + * @throws UserError + * in case the customized aggregation function is used wrongly + */ + private double parseAndCheckValue(String aggregationFunctionName) throws UserError { + aggregationFunctionName = String.valueOf(aggregationFunctionName); + int leftBracket = aggregationFunctionName.indexOf('(') + 1; + int rightBracket = aggregationFunctionName.indexOf(')'); + if (aggregationFunctionName.startsWith(FUNCTION_PERCENTILE) && leftBracket < rightBracket) { + final double aDouble; + final String doubleString = aggregationFunctionName.substring(leftBracket, rightBracket); + try { + aDouble = Double.parseDouble(doubleString); + } catch (NumberFormatException nfe) { + throw new UserError(null, nfe, "aggregation.percentile.numberformat", doubleString); + } + if (aDouble <= 0 || aDouble > 100) { + throw new UserError(null, "aggregation.percentile.outofbounds", aDouble); + } + return aDouble; + } + throw new UserError(null, "aggregation.percentile.notparsable", FUNCTION_NAME_PERCENTILE, aggregationFunctionName); + } +} diff --git a/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregator.java b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregator.java new file mode 100644 index 000000000..de217e2e7 --- /dev/null +++ b/src/main/java/com/rapidminer/operator/preprocessing/transformation/aggregation/PercentileAggregator.java @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2001-2018 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.operator.preprocessing.transformation.aggregation; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.math3.stat.descriptive.rank.Percentile; + + +/** + * Aggregator for Percentile aggregation, using apache commons math lib implementation + * + * @author Andreas Timm + * @since 9.1.0 + */ +public class PercentileAggregator extends NumericalAggregator { + + private double percentile; + private List elements = new ArrayList(); + + public PercentileAggregator(AggregationFunction function) { + super(function); + } + + /** + * Set the percentile to be calculated, is checked during execution + * + * @param value + * > 0 and value <= 100 + */ + public void setPercentile(double value) { + this.percentile = value; + } + + @Override + protected void count(double value) { + elements.add(value); + } + + @Override + protected void count(double value, double weight) { + count(value); + } + + @Override + protected double getValue() { + Percentile percentileCalc = new Percentile(); + percentileCalc.setData(ArrayUtils.toPrimitive(elements.toArray(new Double[0]))); + return percentileCalc.evaluate(percentile); + } +} diff --git a/src/main/java/com/rapidminer/operator/validation/clustering/exampledistribution/ExampleDistributionEvaluator.java b/src/main/java/com/rapidminer/operator/validation/clustering/exampledistribution/ExampleDistributionEvaluator.java index e47ea559c..cd78cc65f 100644 --- a/src/main/java/com/rapidminer/operator/validation/clustering/exampledistribution/ExampleDistributionEvaluator.java +++ b/src/main/java/com/rapidminer/operator/validation/clustering/exampledistribution/ExampleDistributionEvaluator.java @@ -18,6 +18,8 @@ */ package com.rapidminer.operator.validation.clustering.exampledistribution; +import java.util.List; + import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; @@ -34,8 +36,6 @@ import com.rapidminer.parameter.ParameterTypeStringCategory; import com.rapidminer.tools.ClassNameMapper; -import java.util.List; - /** * Evaluates flat cluster models on how well the examples are distributed over the clusters. @@ -47,11 +47,11 @@ public class ExampleDistributionEvaluator extends Operator { public static final String PARAMETER_MEASURE = "measure"; - private final static String[] DEFAULT_MEASURES = { - "com.rapidminer.operator.validation.clustering.exampledistribution.SumOfSquares", - "com.rapidminer.operator.validation.clustering.exampledistribution.GiniCoefficient" }; + private static final String[] DEFAULT_MEASURES = { + SumOfSquares.class.getName(), + GiniCoefficient.class.getName()}; - private ClassNameMapper MEASURE_MAP; + private static final ClassNameMapper MEASURE_MAP = new ClassNameMapper(DEFAULT_MEASURES); private double distribution = 0; @@ -111,11 +111,11 @@ public void doWork() throws OperatorException { @Override public List getParameterTypes() { - MEASURE_MAP = new ClassNameMapper(DEFAULT_MEASURES); List types = super.getParameterTypes(); - + String[] shortClassNames = MEASURE_MAP.getShortClassNames(); + String defaultValue = shortClassNames.length > 0 ? shortClassNames[0] : SumOfSquares.class.getSimpleName(); ParameterType type = new ParameterTypeStringCategory(PARAMETER_MEASURE, "the item distribution measure to apply", - MEASURE_MAP.getShortClassNames(), "SumOfSquares", true); + shortClassNames, defaultValue, true); type.setExpert(false); types.add(type); diff --git a/src/main/java/com/rapidminer/parameter/ParameterType.java b/src/main/java/com/rapidminer/parameter/ParameterType.java index 4a5c1181f..9b33db9b6 100644 --- a/src/main/java/com/rapidminer/parameter/ParameterType.java +++ b/src/main/java/com/rapidminer/parameter/ParameterType.java @@ -20,7 +20,6 @@ import java.io.Serializable; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; @@ -216,11 +215,7 @@ public void setExpert(boolean expert) { * invocations, because it relies on getting the Parameters object, which is then not created. */ public boolean isHidden() { - boolean conditionsMet = true; - for (ParameterCondition condition : conditions) { - conditionsMet &= condition.dependencyMet(); - } - return isDeprecated || isHidden || !conditionsMet; + return isHidden || isDeprecated || !conditions.stream().allMatch(ParameterCondition::dependencyMet); } public Collection getConditions() { @@ -492,19 +487,11 @@ private void loadDefinitionFromXML(Element typeElement) throws XMLException { Constructor constructor = conditionClass.getConstructor(Element.class); conditions.add((ParameterCondition) constructor.newInstance(conditionElement)); } - } catch (ClassNotFoundException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (IllegalArgumentException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (InstantiationException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (IllegalAccessException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (InvocationTargetException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (SecurityException e) { + } catch (SecurityException | IllegalArgumentException e) { throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); - } catch (NoSuchMethodException e) { + } catch (XMLException | RuntimeException e) { + throw e; + } catch (Exception e) { throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CONDITION_CLASS, e); } } @@ -521,21 +508,11 @@ public static ParameterType createType(Element element) throws XMLException { Constructor constructor = typeClass.getConstructor(Element.class); Object type = constructor.newInstance(element); return (ParameterType) type; - } catch (ClassNotFoundException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (SecurityException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (NoSuchMethodException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (IllegalArgumentException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (InstantiationException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (IllegalAccessException e) { - throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (InvocationTargetException e) { + } catch (SecurityException | IllegalArgumentException e) { throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); - } catch (ClassCastException e) { + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { throw new XMLException("Illegal value for attribute " + ATTRIBUTE_CLASS, e); } } diff --git a/src/main/java/com/rapidminer/parameter/ParameterTypeDateFormat.java b/src/main/java/com/rapidminer/parameter/ParameterTypeDateFormat.java index 19f6e59ad..293c9cc41 100644 --- a/src/main/java/com/rapidminer/parameter/ParameterTypeDateFormat.java +++ b/src/main/java/com/rapidminer/parameter/ParameterTypeDateFormat.java @@ -50,13 +50,14 @@ public class ParameterTypeDateFormat extends ParameterTypeStringCategory { public static final String TIME_FORMAT_H_MM_A = "h:mm a"; public static final String DATE_FORMAT_MM_DD_YYYY = "MM/dd/yyyy"; + public static final String DATE_FORMAT_DD_DOT_MM_DOT_YYYY = "dd.MM.yyyy"; public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd"; public static final String DATE_TIME_FORMAT_MM_DD_YYYY_H_MM_A = DATE_FORMAT_MM_DD_YYYY + " " + TIME_FORMAT_H_MM_A; public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MM_SS = DATE_FORMAT_YYYY_MM_DD + " HH:mm:ss"; public static final String DATE_TIME_FORMAT_ISO8601_UTC_MS = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; public static final String DATE_TIME_FORMAT_M_D_YY_H_MM_A = "M/d/yy " + TIME_FORMAT_H_MM_A; - public static final String[] PREDEFINED_DATE_FORMATS = new String[]{"", DATE_FORMAT_MM_DD_YYYY, DATE_TIME_FORMAT_MM_DD_YYYY_H_MM_A, - "dd/MM/yyyy", "dd/MM/yyyy HH:mm", "yyyy.MM.dd G 'at' HH:mm:ss z", "EEE, MMM d, ''yy", TIME_FORMAT_H_MM_A, + public static final String[] PREDEFINED_DATE_FORMATS = new String[]{"", DATE_FORMAT_MM_DD_YYYY, DATE_FORMAT_DD_DOT_MM_DOT_YYYY, DATE_TIME_FORMAT_MM_DD_YYYY_H_MM_A, + "yyyy/MM/dd", "dd/MM/yyyy", "dd/MM/yyyy HH:mm", "yyyy.MM.dd G 'at' HH:mm:ss z", "EEE, MMM d, ''yy", TIME_FORMAT_H_MM_A, "hh 'o''clock' a, zzzz", "K:mm a, z", "yyyy.MMMMM.dd GGG hh:mm aaa", "EEE, d MMM yyyy HH:mm:ss Z", "yyMMddHHmmssZ", DATE_TIME_FORMAT_ISO8601_UTC_MS, DATE_TIME_FORMAT_YYYY_MM_DD_HH_MM_SS, DATE_TIME_FORMAT_M_D_YY_H_MM_A, DATE_FORMAT_YYYY_MM_DD}; diff --git a/src/main/java/com/rapidminer/parameter/Parameters.java b/src/main/java/com/rapidminer/parameter/Parameters.java index 552f2eaca..d7bbc9cf6 100644 --- a/src/main/java/com/rapidminer/parameter/Parameters.java +++ b/src/main/java/com/rapidminer/parameter/Parameters.java @@ -354,6 +354,7 @@ public boolean isSpecified(String key) { public void copyFrom(Parameters parameters) { this.keyToValueMap.putAll(parameters.keyToValueMap); + fireUpdate(); } /** diff --git a/src/main/java/com/rapidminer/parameter/SimpleListBasedParameterHandler.java b/src/main/java/com/rapidminer/parameter/SimpleListBasedParameterHandler.java new file mode 100644 index 000000000..9c9ba2def --- /dev/null +++ b/src/main/java/com/rapidminer/parameter/SimpleListBasedParameterHandler.java @@ -0,0 +1,215 @@ +/** + * Copyright (C) 2001-2018 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.parameter; + +import java.awt.Color; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.function.Function; + +import com.rapidminer.operator.OperatorException; +import com.rapidminer.tools.WebServiceTools; +import com.rapidminer.tools.math.StringToMatrixConverter; + + +/** + * Simple {@link ParameterHandler} that relies on a list of {@link ParameterType ParameterTypes} + * specified by {@link #getParameterTypes()}. Subclasses only need to implement that method. + * + * @author Simon Fischer, Dominik Halfkann, Marco Boeck, Adrian Wilke, Jan Czogalla + */ +public abstract class SimpleListBasedParameterHandler implements ParameterHandler { + private Parameters parameters; + + @Override + public String getParameter(String key) throws UndefinedParameterError { + return this.parameters.getParameter(key); + } + + @Override + public boolean getParameterAsBoolean(String key) { + try { + return Boolean.valueOf(getParameter(key)); + } catch (UndefinedParameterError e) { + return false; + } + } + + @Override + public char getParameterAsChar(String key) throws UndefinedParameterError { + String parameterValue = getParameter(key); + if (parameterValue != null && parameterValue.length() > 0) { + return parameterValue.charAt(0); + } + return 0; + } + + @Override + public Color getParameterAsColor(String key) throws UndefinedParameterError { + String parameterValue = getParameter(key); + if (parameterValue == null) { + return Color.BLACK; + } + return ParameterTypeColor.string2Color(parameterValue); + } + + @Override + public double getParameterAsDouble(String key) throws UndefinedParameterError { + String value = getParameter(key); + if (value == null) { + throw new UndefinedParameterError(key); + } + try { + return Double.valueOf(value); + } catch (NumberFormatException e) { + throw new UndefinedParameterError(key, "Expected real number but found '" + value + "'."); + } + } + + @Override + public InputStream getParameterAsInputStream(String key) throws UndefinedParameterError, IOException { + String urlString = getParameter(key); + if (urlString == null) { + return null; + } + + try { + URL url = new URL(urlString); + return WebServiceTools.openStreamFromURL(url); + } catch (MalformedURLException e) { + // URL did not work? Try as file... + File file = getParameterAsFile(key); + return file != null ? new FileInputStream(file) : null; + } + } + + @Override + public File getParameterAsFile(String key) throws UndefinedParameterError { + return getParameterAsFile(key, false); + } + + @Override + public File getParameterAsFile(String key, boolean createMissingDirectories) throws UndefinedParameterError { + String filename = getParameter(key); + if (filename == null) { + return null; + } + File file = new File(filename); + return !file.exists() ? null : file; + } + + @Override + public int getParameterAsInt(String key) throws UndefinedParameterError { + return (int) getParameterAsIntegerType(key, s -> Integer.valueOf(s).longValue()); + } + + @Override + public long getParameterAsLong(String key) throws UndefinedParameterError { + return getParameterAsIntegerType(key, Long::valueOf); + } + + @Override + public double[][] getParameterAsMatrix(String key) throws UndefinedParameterError { + String matrixLine = getParameter(key); + try { + return StringToMatrixConverter.parseMatlabString(matrixLine); + } catch (OperatorException e) { + throw new UndefinedParameterError(e.getMessage()); + } + } + + @Override + public String getParameterAsString(String key) throws UndefinedParameterError { + return getParameter(key); + } + + @Override + public List getParameterList(String key) throws UndefinedParameterError { + String value = getParameter(key); + if (value == null) { + throw new UndefinedParameterError(key); + } + return ParameterTypeList.transformString2List(value); + } + + @Override + public String[] getParameterTupel(String key) throws UndefinedParameterError { + String value = getParameter(key); + if (value == null) { + throw new UndefinedParameterError(key); + } + return ParameterTypeTupel.transformString2Tupel(value); + } + + @Override + public boolean isParameterSet(String key) throws UndefinedParameterError { + return getParameter(key) != null; + } + + @Override + public void setListParameter(String key, List list) { + this.parameters.setParameter(key, ParameterTypeList.transformList2String(list)); + } + + @Override + public void setParameter(String key, String value) { + this.parameters.setParameter(key, value); + } + + @Override + public void setParameters(Parameters parameters) { + this.parameters = parameters; + } + + @Override + public Parameters getParameters() { + if (this.parameters == null) { + this.parameters = new Parameters(getParameterTypes()); + } + return this.parameters; + } + + /** + * Parses and returns the value of the given parameter to long/int depending on the parser. + * + * @since 9.1 + */ + private long getParameterAsIntegerType(String key, Function parser) throws UndefinedParameterError { + ParameterType type = this.parameters.getParameterType(key); + String value = getParameter(key); + if (type instanceof ParameterTypeCategory) { + try { + return parser.apply(value); + } catch (NumberFormatException e) { + ParameterTypeCategory categoryType = (ParameterTypeCategory) type; + return categoryType.getIndex(value); + } + } + try { + return parser.apply(value); + } catch (NumberFormatException e) { + throw new UndefinedParameterError(key, "Expected integer/long but found '" + value + "'."); + } + } +} diff --git a/src/main/java/com/rapidminer/parameter/conditions/ParameterCondition.java b/src/main/java/com/rapidminer/parameter/conditions/ParameterCondition.java index 3dca67f23..db4628078 100644 --- a/src/main/java/com/rapidminer/parameter/conditions/ParameterCondition.java +++ b/src/main/java/com/rapidminer/parameter/conditions/ParameterCondition.java @@ -50,7 +50,7 @@ public abstract class ParameterCondition { * implemented by the subclasses. It will be called by reflection! * * Notice that conditions created with this constructor won't work until - * {@link #setOperator(Operator)} is called. + * {@link #setParameterHandler(ParameterHandler)} or {@link #setOperator(Operator)} is called. */ public ParameterCondition(Element conditionElement) { this.parameterHandler = null; @@ -79,25 +79,35 @@ public ParameterCondition(ParameterHandler parameterHandler, String conditionPar * parameterhandler was known. */ public void setOperator(Operator operator) { - this.parameterHandler = operator; + setParameterHandler(operator); + } + + /** + * This method sets the parameter handler from which the values to check the condition are + * retrieved, this is usually an operator. This can be used if during construction time no + * parameterhandler was known. + * + * @since 9.1 + */ + public void setParameterHandler(ParameterHandler handler) { + this.parameterHandler = handler; + } + + /** @since 9.1 */ + public String getConditionParameter() { + return conditionParameter; } /** * This returns true if the condition is met and if the ancestor type isn't hidden. */ - final public boolean dependencyMet() { - // if we don't can check: Return always true - if (parameterHandler == null) { - return true; - } - - // otherwise perform check - if (conditionParameter != null) { - if (parameterHandler.getParameters().getParameterType(conditionParameter).isHidden()) { - return false; - } - } - return isConditionFullfilled(); + public final boolean dependencyMet() { + // if we can't check: Return always true + return parameterHandler == null || + // sanity checks + (conditionParameter == null || !parameterHandler.getParameters().getParameterType(conditionParameter).isHidden()) + // otherwise perform check + && isConditionFullfilled(); } /** diff --git a/src/main/java/com/rapidminer/repository/RepositoryManager.java b/src/main/java/com/rapidminer/repository/RepositoryManager.java index 5056df118..28e865c54 100644 --- a/src/main/java/com/rapidminer/repository/RepositoryManager.java +++ b/src/main/java/com/rapidminer/repository/RepositoryManager.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.event.EventListenerList; @@ -96,7 +97,8 @@ public class RepositoryManager extends AbstractObservable { private static RepositoryProvider provider = new FileRepositoryProvider(); - private final List repositories = new LinkedList<>(); + // use copy-on-write to prevent modification exceptions on startup + private final List repositories = new CopyOnWriteArrayList<>(); private final EventListenerList listeners = new EventListenerList(); diff --git a/src/main/java/com/rapidminer/repository/gui/NewRepositoryDialog.java b/src/main/java/com/rapidminer/repository/gui/NewRepositoryDialog.java index 30f3692ba..f26d06acb 100644 --- a/src/main/java/com/rapidminer/repository/gui/NewRepositoryDialog.java +++ b/src/main/java/com/rapidminer/repository/gui/NewRepositoryDialog.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; - import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; @@ -114,6 +113,35 @@ protected void finish() { } } + @Override + protected void previous() { + // reset the finish button when going back, e.g. when selecting another type of repo + if (!localButton.isSelected() && finish.isEnabled()) { + updateFinishButton(false); + } + super.previous(); + } + + @Override + protected void next() { + super.next(); + // set the finish button when reaching the last page + if (!localButton.isSelected() && finish.isEnabled()) { + updateFinishButton(true); + } + } + + /** + * Sets or resets the {@link #finish} button for the selected repository panel + * + * @param set to set or reset the finish button + * @since 9.0.2 + */ + private void updateFinishButton(boolean set) { + repoConfigPanels.values().stream().filter(p -> p.getSecond().isSelected()) + .forEach(p -> p.getFirst().setOkButton(set ? finish : null)); + } + @Override protected String getNameForStep(int step) { switch (step) { diff --git a/src/main/java/com/rapidminer/repository/gui/RepositoryConfigurationDialog.java b/src/main/java/com/rapidminer/repository/gui/RepositoryConfigurationDialog.java index 51a41b9a8..ed78ff94a 100644 --- a/src/main/java/com/rapidminer/repository/gui/RepositoryConfigurationDialog.java +++ b/src/main/java/com/rapidminer/repository/gui/RepositoryConfigurationDialog.java @@ -20,11 +20,11 @@ import java.util.LinkedList; import java.util.List; - import javax.swing.AbstractButton; import javax.swing.JButton; import com.rapidminer.gui.ApplicationFrame; +import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.dialogs.ButtonDialog; import com.rapidminer.repository.Repository; @@ -35,7 +35,7 @@ /** * Dialog to configure an existing repository. * - * @author Simon Fischer + * @author Simon Fischer, Jan Czogalla * */ public class RepositoryConfigurationDialog extends ButtonDialog { @@ -46,9 +46,8 @@ public class RepositoryConfigurationDialog extends ButtonDialog { private Repository repository; public RepositoryConfigurationDialog(Repository repository) { - super(ApplicationFrame.getApplicationFrame(), RemoteRepository.class.isAssignableFrom(repository.getClass()) - ? "remoterepositoryconfigdialog" : "repositoryconfigdialog", ModalityType.APPLICATION_MODAL, - new Object[] {}); + super(ApplicationFrame.getApplicationFrame(), (repository instanceof RemoteRepository ? "remote" : "") + + "repositoryconfigdialog", ModalityType.APPLICATION_MODAL, new Object[0]); this.repository = repository; JButton okButton = makeOkButton("repository_configuration_dialog.save"); configurationPanel = repository.makeConfigurationPanel(); @@ -65,15 +64,23 @@ public RepositoryConfigurationDialog(Repository repository) { @Override protected void ok() { - if (!configurationPanel.configure(repository)) { - return; - } - try { - repository.refresh(); - super.ok(); - } catch (RepositoryException e) { - SwingTools.showSimpleErrorMessage(this, "repository_configuration_dialog.cannot_refresh_folder", e); - } + ProgressThread repoConfigurePT = new ProgressThread("configure_repository", false, repository.getName()) { + + @Override + public void run() { + if (!configurationPanel.configure(repository)) { + return; + } + try { + repository.refresh(); + } catch (RepositoryException e) { + SwingTools.showSimpleErrorMessage(RepositoryConfigurationDialog.this, "repository_configuration_dialog.cannot_refresh_folder", e); + } + } + }; + repoConfigurePT.setIndeterminate(true); + repoConfigurePT.start(); + super.ok(); } } diff --git a/src/main/java/com/rapidminer/repository/gui/RepositoryTree.java b/src/main/java/com/rapidminer/repository/gui/RepositoryTree.java index bb42489f9..d3ddbc4ee 100644 --- a/src/main/java/com/rapidminer/repository/gui/RepositoryTree.java +++ b/src/main/java/com/rapidminer/repository/gui/RepositoryTree.java @@ -40,6 +40,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.Action; @@ -433,14 +434,8 @@ private boolean executeCopyOrMoveOperation(RepositoryLocation location, boolean // For this case, select the element, which is the target of the drop // operation. if (overwriteIfExists && droppedOnEntry != null) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - RepositoryTree.this.setSelectionPath(RepositoryTreeModel.getPathTo(droppedOnEntry, - RepositoryManager.getInstance(null))); - } - }); + SwingUtilities.invokeLater(() -> RepositoryTree.this.setSelectionPath(RepositoryTreeModel.getPathTo(droppedOnEntry, + RepositoryManager.getInstance(null)))); } @@ -454,32 +449,28 @@ public void run() { return false; } // Do not show "cancel" option, if is is an single entry operation - int dialogMode = ConfirmDialog.YES_NO_CANCEL_OPTION; - if (isSingleEntryOperation) { - dialogMode = ConfirmDialog.YES_NO_OPTION; - } - - String locationName = location.getName(); - if (locationName == null) { - locationName = ""; - } - - ConfirmDialog dialog = null; - if (e.getMessage() != null && !e.getMessage().isEmpty()) { - dialog = new ConfirmDialog(ProgressThreadDialog.getInstance(), "error_in_copy_entry_with_cause", - dialogMode, false, locationName, e.getMessage()); - } else { - dialog = new ConfirmDialog(ProgressThreadDialog.getInstance(), "error_in_copy_entry", dialogMode, - false, locationName); - } - dialog.setVisible(true); - int retry = dialog.getReturnOption(); + final int dialogMode = isSingleEntryOperation ? ConfirmDialog.YES_NO_OPTION : ConfirmDialog.YES_NO_CANCEL_OPTION; + final String locationName = location.getName() == null ? "" : location.getName(); + final AtomicInteger result = new AtomicInteger(); + + SwingTools.invokeAndWait(() -> { + final ConfirmDialog dialog; + if (e.getMessage() != null && !e.getMessage().isEmpty()) { + dialog = new ConfirmDialog(ProgressThreadDialog.getInstance(), "error_in_copy_entry_with_cause", + dialogMode, false, locationName, e.getMessage()); + } else { + dialog = new ConfirmDialog(ProgressThreadDialog.getInstance(), "error_in_copy_entry", + dialogMode, false, locationName); + } + dialog.setVisible(true); + result.set(dialog.getReturnOption()); + }); - if (retry == ConfirmDialog.YES_OPTION) { + if (result.get() == ConfirmDialog.YES_OPTION) { return executeCopyOrMoveOperation(location, isRepositoryInLocations, isSingleEntryOperation, overwriteIfExists); - } else if (retry == ConfirmDialog.CANCEL_OPTION) { + } else if (result.get() == ConfirmDialog.CANCEL_OPTION) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.repository.RepositoryTree.error_during_copying", e); return false; diff --git a/src/main/java/com/rapidminer/repository/gui/RepositoryTreeUtil.java b/src/main/java/com/rapidminer/repository/gui/RepositoryTreeUtil.java index 431b5ce19..0d2edabe0 100644 --- a/src/main/java/com/rapidminer/repository/gui/RepositoryTreeUtil.java +++ b/src/main/java/com/rapidminer/repository/gui/RepositoryTreeUtil.java @@ -93,8 +93,9 @@ public void saveExpansionState(JTree tree) { TreePath path = tree.getPathForRow(i); boolean isExpanded = tree.isExpanded(path); boolean isSelected = tree.isPathSelected(path); - if (isExpanded ||isSelected) { - Entry entry = (Entry) path.getLastPathComponent(); + Object entryObject = path.getLastPathComponent(); + if ((isExpanded || isSelected) && entryObject instanceof Entry) { + Entry entry = (Entry) entryObject; String absoluteLocation = entry.getLocation().getAbsoluteLocation(); if (isExpanded) { expandedNodes.add(absoluteLocation); diff --git a/src/main/java/com/rapidminer/repository/gui/actions/ShowProcessInRepositoryAction.java b/src/main/java/com/rapidminer/repository/gui/actions/ShowProcessInRepositoryAction.java index dd0790580..57e1cc563 100644 --- a/src/main/java/com/rapidminer/repository/gui/actions/ShowProcessInRepositoryAction.java +++ b/src/main/java/com/rapidminer/repository/gui/actions/ShowProcessInRepositoryAction.java @@ -41,7 +41,7 @@ public class ShowProcessInRepositoryAction extends ResourceActionAdapter { public ShowProcessInRepositoryAction(RepositoryTree tree) { super(true, "link"); this.tree = tree; - setCondition(PROCESS_SAVED, ConditionalAction.MANDATORY); + setCondition(PROCESS_HAS_REPOSITORY_LOCATION, ConditionalAction.MANDATORY); } @Override diff --git a/src/main/java/com/rapidminer/repository/internal/remote/RemoteScheduler.java b/src/main/java/com/rapidminer/repository/internal/remote/RemoteScheduler.java index e18298597..80e0ca8a5 100644 --- a/src/main/java/com/rapidminer/repository/internal/remote/RemoteScheduler.java +++ b/src/main/java/com/rapidminer/repository/internal/remote/RemoteScheduler.java @@ -37,8 +37,9 @@ * * @author Nils Woehler * @since 6.5.0 - * + * @deprecated Use new REST APIs of the Execution Backend instead. */ +@Deprecated public interface RemoteScheduler { /** diff --git a/src/main/java/com/rapidminer/repository/search/RepositoryGlobalSearchManager.java b/src/main/java/com/rapidminer/repository/search/RepositoryGlobalSearchManager.java index 1064ab37e..9f43c7252 100644 --- a/src/main/java/com/rapidminer/repository/search/RepositoryGlobalSearchManager.java +++ b/src/main/java/com/rapidminer/repository/search/RepositoryGlobalSearchManager.java @@ -238,7 +238,9 @@ private void addEntriesUnderFolderToIndex(final Folder folder) { pgFast.start(); // if enabled, add full metadata to index afterwards, so user can search advanced things - if (Boolean.parseBoolean(ParameterService.getParameterValue(RepositoryGlobalSearch.PROPERTY_FULL_REPOSITORY_INDEXING))) { + // don't do it for RestRepositories, the full index is too expensive here + boolean isRestRepository = folder instanceof RESTRepository; + if (Boolean.parseBoolean(ParameterService.getParameterValue(RepositoryGlobalSearch.PROPERTY_FULL_REPOSITORY_INDEXING)) && !isRestRepository) { ProgressThread pgFull = createIndexingThread(folder, true); pgFull.addDependency(pgFast.getID()); pgFull.start(); diff --git a/src/main/java/com/rapidminer/search/GlobalSearchHandler.java b/src/main/java/com/rapidminer/search/GlobalSearchHandler.java index 56a35f93d..d000490be 100644 --- a/src/main/java/com/rapidminer/search/GlobalSearchHandler.java +++ b/src/main/java/com/rapidminer/search/GlobalSearchHandler.java @@ -101,6 +101,9 @@ enum GlobalSearchHandler { * if {@code true}, will try to make the query automatically user-friendly; {@code false} will not make any changes to the query * @param maxNumberOfResults * the maximum number of results + * @param moreResults + * the number of optional additional search results. Will add these results if there are no additional results. + * Will not be used if parameter 'after' is set. * @param highlightResult * if {@code true}, the {@link GlobalSearchResult#getBestFragments()} will be created * @param after @@ -110,7 +113,7 @@ enum GlobalSearchHandler { * @throws ParseException * if the searchQuery was invalid */ - protected GlobalSearchResult search(final String searchQueryString, final List categories, final boolean simpleMode, final int maxNumberOfResults, final boolean highlightResult, final ScoreDoc after) throws ParseException { + protected GlobalSearchResult search(final String searchQueryString, final List categories, final boolean simpleMode, final int maxNumberOfResults, final int moreResults, final boolean highlightResult, final ScoreDoc after) throws ParseException { if (searchQueryString == null || searchQueryString.trim().isEmpty()) { return GlobalSearchResult.createEmptyResult(searchQueryString); } @@ -132,7 +135,11 @@ protected GlobalSearchResult search(final String searchQueryString, final List 0 && (searcher.count(finalQuery) <= maxNumberOfResults + moreResults)) { + result = searcher.search(finalQuery, maxNumberOfResults + moreResults, SORT, true, false); + } else { + result = searcher.search(finalQuery, maxNumberOfResults, SORT, true, false); + } } else { result = searcher.searchAfter(after, finalQuery, maxNumberOfResults, SORT, true, false); } diff --git a/src/main/java/com/rapidminer/search/GlobalSearchResultBuilder.java b/src/main/java/com/rapidminer/search/GlobalSearchResultBuilder.java index fe41ce20b..15c49ae1e 100644 --- a/src/main/java/com/rapidminer/search/GlobalSearchResultBuilder.java +++ b/src/main/java/com/rapidminer/search/GlobalSearchResultBuilder.java @@ -35,9 +35,11 @@ public final class GlobalSearchResultBuilder { private static final int MAX_RESULTS_DEFAULT = 20; + private static final int MORE_RESULTS_DEFAULT = 0; private final String searchTerm; private int maxNumberOfResults; + private int showMoreResults; private boolean highlightResult; private boolean simpleMode; private ScoreDoc after; @@ -64,6 +66,7 @@ public GlobalSearchResultBuilder(final String searchQuery) { //set default values this.maxNumberOfResults = MAX_RESULTS_DEFAULT; + this.showMoreResults = MORE_RESULTS_DEFAULT; this.highlightResult = false; this.after = null; this.categories = null; @@ -86,6 +89,24 @@ public GlobalSearchResultBuilder setMaxNumberOfResults(final int maxNumberOfResu return this; } + /** + * Set the number of additional to the maximum number results to be returned with this search if there are not more + * than maxNumberOfResults + moreResults available. + * + *

    By default, {@value #MORE_RESULTS_DEFAULT} additional values are returned.

    + * + * @param moreResults + * the maximum number of additional results + * @return the builder instance + */ + public GlobalSearchResultBuilder setMoreResults(final int moreResults) { + if (moreResults < 0) { + throw new IllegalArgumentException("moreResults must be >= 0!"); + } + this.showMoreResults = moreResults; + return this; + } + /** * Set if result matches for the {@value GlobalSearchUtilities#FIELD_NAME} field should be returned as {@link * GlobalSearchResult#getBestFragments()}. @@ -172,6 +193,6 @@ public GlobalSearchResultBuilder setSimpleMode(final boolean simpleMode) { * if the searchQuery was invalid */ public GlobalSearchResult runSearch() throws ParseException { - return GlobalSearchHandler.INSTANCE.search(searchTerm, categories, simpleMode, maxNumberOfResults, highlightResult, after); + return GlobalSearchHandler.INSTANCE.search(searchTerm, categories, simpleMode, maxNumberOfResults, showMoreResults, highlightResult, after); } } diff --git a/src/main/java/com/rapidminer/security/PluginSandboxPolicy.java b/src/main/java/com/rapidminer/security/PluginSandboxPolicy.java index 50865a902..79dd54560 100644 --- a/src/main/java/com/rapidminer/security/PluginSandboxPolicy.java +++ b/src/main/java/com/rapidminer/security/PluginSandboxPolicy.java @@ -37,10 +37,14 @@ import java.security.PublicKey; import java.security.cert.Certificate; import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.PropertyPermission; import java.util.logging.Level; import java.util.logging.LoggingPermission; - +import java.util.stream.Collectors; import javax.sound.sampled.AudioPermission; import javax.xml.bind.DatatypeConverter; @@ -78,6 +82,12 @@ public final class PluginSandboxPolicy extends Policy { + "anxWScOfVW6yDxEjgEHJvMiMzZkGNklYC3ULBCkHfIrih5hO83k5FileuUWDNO4BrLrawmjo9AmYksPVOMmd4/DtDpnehpLy0hQtjBJsz61h" + "AGVDnPGpvbsW0rjFAjE4fR5+4RwUNo+SsD/44Jc8bui5seVH5vZuTj02XokybGR4BikrqvJZ4rHe4OGowl8uIr9sEN/+0eIJXQIDAQAB"; + /** the Base 64 encoded public key of our partner (#0001) which is used to verify their signed extensions */ + private static final String KEY_PARTNER_0001_B64_ENCODED = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqO43pd2Zzsn1Rx4+" + + "RiKtDnuxL7+lOEfwxGTpZcxeD+jXMA2n10rznXeSYmNSxn22678qCVcwJs9Hs+qH8cQ8iuEj6sxrP9W1QAZ+b0KeMh7G3jvuhw2zgRp/0PHbO9BK" + + "eJl+JDeXqkbmgf5+UQZaWZG73C+9XcDczgJWSvJuTuwalp+40z60qykFH87BFXLtzg/kg2FQ2zuQ3fA51aAUPMFx+uCg+5VJTGMSWcILiB5rYEWV" + + "Uedeq5Bf6Dz1MvAcZjXLZnXdT+V7V6BHAbvQFlYKM5006O+RgVTxkM92WI2Hs4Bqexso0UOS66cQacOH8y1gJ/SE1lUa4G51an3OVQIDAQAB"; + /** * the system property which can be set to {@code true} to enforce plugin sandboxing even on * SNAPSHOT versions @@ -85,7 +95,10 @@ public final class PluginSandboxPolicy extends Policy { private static final String PROPERTY_SECURITY_ENFORCED = "com.rapidminer.security.enforce"; /** Our public key used to verify the certificates */ - private static PublicKey key; + private static final PublicKey RAPIDMINER_KEY; + + /** The public key of partner (#0001) used to verify the certificates */ + private static final List KEY_PARTNERS; /** * if {@code true}, plugin sandboxing is enforced even on SNAPSHOT versions @@ -93,19 +106,17 @@ public final class PluginSandboxPolicy extends Policy { private static volatile Boolean enforced; static { - try { - KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); - X509EncodedKeySpec spec = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(KEY_B64_ENCODED)); - key = factory.generatePublic(spec); - } catch (GeneralSecurityException e) { - key = null; - // no log service available yet, so use syserr - System.err.println( - "Failed to initialize public key to verify extension certificates. Revoking permissions for all extensions!"); - e.printStackTrace(); - } + List tempList = new ArrayList<>(1); + // our own code-signing key + RAPIDMINER_KEY = createPublicKey(KEY_B64_ENCODED); + + // add all partner keys below + tempList.add(createPublicKey(KEY_PARTNER_0001_B64_ENCODED)); + + KEY_PARTNERS = Collections.unmodifiableList(tempList.stream().filter(Objects::nonNull).collect(Collectors.toList())); } + @Override public PermissionCollection getPermissions(ProtectionDomain domain) { if (isInternalPlugin(domain)) { @@ -137,6 +148,26 @@ public PermissionCollection getPermissions(CodeSource codesource) { return super.getPermissions(codesource); } + /** + * Creates the public key based on the Base64 encoded key string. + * + * @param base64EncodedKey + * the Base64 encoded public key + * @return the key or {@code null} if creation failed + */ + private static PublicKey createPublicKey(final String base64EncodedKey) { + try { + KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); + X509EncodedKeySpec spec = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(base64EncodedKey)); + return factory.generatePublic(spec); + } catch (GeneralSecurityException e) { + // no log service available yet, so use syserr + System.err.println("Failed to initialize public key to verify extension certificates!"); + e.printStackTrace(); + return null; + } + } + /** * Checks whether the given domain belongs to a special internal extension or not. * @@ -165,8 +196,8 @@ private static boolean isUnsignedPlugin(ProtectionDomain domain) { return false; } - // if the public key could not be initialized, we treat all plugins as unsafe - if (key == null) { + // if the public keys could not be initialized, we treat all plugins as unsafe + if (RAPIDMINER_KEY == null && KEY_PARTNERS.isEmpty()) { return true; } @@ -387,30 +418,36 @@ private static void addCommonPermissions(Permissions permissions) { * Verify the given certificates and see if at least one was signed by us. * * @param certificates - * the array of certificates to check + * the array of certificates to check * @throws GeneralSecurityException - * if no certificate could be verified, will throw the last exception that occured - * during verification of all certificates. Can be {@code null} + * if no certificate could be verified, will throw the last exception that occurred during verification of all + * certificates. */ private static void verifyCertificates(Certificate[] certificates) throws GeneralSecurityException { if (certificates == null || certificates.length == 0) { throw new GeneralSecurityException("No code certificates found!"); } - GeneralSecurityException lastException = null; - boolean verified = false; + GeneralSecurityException lastException = new GeneralSecurityException("Failed to verify code certificate!"); + List keysToCheck = new ArrayList<>(1 + KEY_PARTNERS.size()); + keysToCheck.add(RAPIDMINER_KEY); + keysToCheck.addAll(KEY_PARTNERS); for (Certificate certificate : certificates) { - try { - certificate.verify(key); - verified = true; - break; - } catch (GeneralSecurityException e) { - lastException = e; + // try all available keys + for (PublicKey key : keysToCheck) { + try { + certificate.verify(key); + // no exception? Verified successfully, can return now + return; + } catch (GeneralSecurityException e) { + lastException = e; + } } } - if (!verified) { - throw lastException; - } + + // if at any point we have not encountered an exception, we have already returned, so throw here + // if we end up here, neither our own nor any partner keys have verified the code signature + throw lastException; } /** diff --git a/src/main/java/com/rapidminer/studio/concurrency/internal/AbstractConcurrencyContext.java b/src/main/java/com/rapidminer/studio/concurrency/internal/AbstractConcurrencyContext.java new file mode 100644 index 000000000..9ff36a95a --- /dev/null +++ b/src/main/java/com/rapidminer/studio/concurrency/internal/AbstractConcurrencyContext.java @@ -0,0 +1,286 @@ +/** + * Copyright (C) 2001-2018 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.studio.concurrency.internal; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; + +import com.rapidminer.Process; +import com.rapidminer.core.concurrency.ConcurrencyContext; +import com.rapidminer.core.concurrency.ExecutionStoppedException; +import com.rapidminer.studio.internal.ProcessStoppedRuntimeException; + + +/** + * Simple {@link ConcurrencyContext} to be used with a single {@link Process}. + *

    + * The context does not implement the submission methods for {@link ForkJoinTask}s. + * + * @author Jonas Wilms-Pfau (internals by Gisa Schaefer, Michael Knopf) + * @since 9.1.0 + */ +abstract class AbstractConcurrencyContext implements ConcurrencyContext { + + /** The corresponding process. */ + private final Process process; + + /** The shared {@link ForkJoinPool} pool wrapper */ + private final LazyPool.Instance pool; + + /** + * Creates a new {@link ConcurrencyContext} for the given {@link Process}. + *

    + * The context assumes that only operators that belong to the corresponding process submit tasks + * to this context. + * + * @param process + * the corresponding process + */ + AbstractConcurrencyContext(Process process, LazyPool pool) { + if (process == null) { + throw new IllegalArgumentException("process must not be null"); + } + if (pool == null) { + throw new IllegalArgumentException("pool must not be null"); + } + this.process = process; + this.pool = pool.getInstance(this); + } + + @Override + public void run(List runnables) throws ExecutionException, ExecutionStoppedException { + if (runnables == null) { + throw new IllegalArgumentException("runnables must not be null"); + } + + // nothing to do if list is empty + if (runnables.isEmpty()) { + return; + } + + // check for null runnables + for (Runnable runnable : runnables) { + if (runnable == null) { + throw new IllegalArgumentException("runnables must not contain null"); + } + } + + // wrap runnables in callables + List> callables = new ArrayList<>(runnables.size()); + for (final Runnable runnable : runnables) { + callables.add(() -> { + runnable.run(); + return null; + }); + } + + // submit callables without further checks + call(callables); + } + + @Override + public List call(List> callables) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + if (callables == null) { + throw new IllegalArgumentException("callables must not be null"); + } + + // nothing to do if list is empty + if (callables.isEmpty()) { + return Collections.emptyList(); + } + + // check for null tasks + for (Callable callable : callables) { + if (callable == null) { + throw new IllegalArgumentException("callables must not contain null"); + } + } + + ForkJoinPool forkJoinPool = AccessController.doPrivileged( + (PrivilegedAction) this::getForkJoinPool); + // handle submissions from inside and outside the pool differently + Thread currentThread = Thread.currentThread(); + if (currentThread instanceof ForkJoinWorkerThread + && ((ForkJoinWorkerThread) currentThread).getPool() == forkJoinPool) { + return RecursiveWrapper.call(callables); + } else { + final List> futures = new ArrayList<>(callables.size()); + for (Callable callable : callables) { + futures.add(forkJoinPool.submit(callable)); + } + return collectResults(futures); + } + } + + @Override + public List> submit(List> callables) throws IllegalArgumentException { + if (callables == null) { + throw new IllegalArgumentException("callables must not be null"); + } + + // nothing to do if list is empty + if (callables.isEmpty()) { + return Collections.emptyList(); + } + + // check for null tasks + for (Callable callable : callables) { + if (callable == null) { + throw new IllegalArgumentException("callables must not contain null"); + } + } + + ForkJoinPool forkJoinPool = AccessController.doPrivileged( + (PrivilegedAction) this::getForkJoinPool); + // handle submissions from inside and outside the pool differently + Thread currentThread = Thread.currentThread(); + if (currentThread instanceof ForkJoinWorkerThread + && ((ForkJoinWorkerThread) currentThread).getPool() == forkJoinPool) { + final List> futures = new ArrayList<>(callables.size()); + for (Callable callable : callables) { + futures.add(ForkJoinTask.adapt(callable).fork()); + } + return futures; + } else { + // submit callables without further checks + final List> futures = new ArrayList<>(callables.size()); + for (Callable callable : callables) { + futures.add(forkJoinPool.submit(callable)); + } + return futures; + } + } + + @Override + public List collectResults(List> futures) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + if (futures == null) { + throw new IllegalArgumentException("futures must not be null"); + } + + // nothing to do if list is empty + if (futures.isEmpty()) { + return Collections.emptyList(); + } + + // check for null tasks + for (Future future : futures) { + if (future == null) { + throw new IllegalArgumentException("futures must not contain null"); + } + } + + List results = new ArrayList<>(futures.size()); + for (Future future : futures) { + try { + T result = future.get(); + results.add(result); + } catch (InterruptedException | RejectedExecutionException e) { + // The pool's invokeAll() method calls Future.get() internally. If the process is + // stopped by the user, these calls might be interrupted before calls to + // checkStatus() throw an ExecutionStoppedException. Thus, we need to check the + // current status again. + checkStatus(); + // InterruptedExceptions are very unlikely to happen at this point, since the above + // calls to get() will return immediately. A RejectedExectutionException is an + // extreme corner case as well. In both cases, there is no benefit for the API user + // if the exception is passed on directly. Thus, we can wrap it within a + // ExecutionException which is part of the API. + throw new ExecutionException(e); + } catch (ExecutionException e) { + // A ProcessStoppedRuntimeException is an internal exception thrown if the user + // requests the process to stop (see the checkStatus() implementation of this + // class). This exception should not be wrapped or consumed here, since it is + // handled by the operator implementation itself. + if (e.getCause() instanceof ProcessStoppedRuntimeException) { + throw (ExecutionStoppedException) e.getCause(); + } else { + throw e; + } + } + } + + return results; + } + + @Override + public int getParallelism() { + return pool.getParallelism(); + } + + @Override + public void checkStatus() throws ExecutionStoppedException { + if (process.shouldStop()) { + throw new ProcessStoppedRuntimeException(); + } + } + + @Override + public T invoke(ForkJoinTask task) throws ExecutionException, ExecutionStoppedException { + throw new UnsupportedOperationException(); + } + + @Override + public List invokeAll(final List> tasks) throws ExecutionException, + ExecutionStoppedException { + throw new UnsupportedOperationException(); + } + + /** + * This method verifies and returns a JVM-wide, static FJPool. Override if a different pool behavior is needed. + * + * @return the ForkJoinPool to use for this context instance for execution. + */ + protected ForkJoinPool getForkJoinPool(){ + return pool.getForkJoinPool(); + } + + /** + * Checks if the JVM-wide, static pool needs to be re-created. Override if a different pool behavior is needed. + * + * @return {@code true} if the current pool is {@code null} or the + * {@link #getDesiredParallelismLevel} is not equal to the current {@link #getPool} + * parallelism otherwise {@code false} + */ + protected boolean isPoolOutdated() { + return pool.isPoolOutdated(); + } + + /** + * Returns the desired number of cores to be used for concurrent computations for the JVM-wide, static pool. This + * number is always at least one and either bound by a license limit or by the user's configuration. Override if a + * different pool behavior is needed. + * + * @return the desired parallelism level + */ + protected int getDesiredParallelismLevel() { + return pool.getDesiredParallelismLevel(); + } +} diff --git a/src/main/java/com/rapidminer/studio/concurrency/internal/BackgroundConcurrencyContext.java b/src/main/java/com/rapidminer/studio/concurrency/internal/BackgroundConcurrencyContext.java new file mode 100644 index 000000000..00a62fdb7 --- /dev/null +++ b/src/main/java/com/rapidminer/studio/concurrency/internal/BackgroundConcurrencyContext.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2001-2018 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.studio.concurrency.internal; + +import com.rapidminer.Process; +import com.rapidminer.RapidMiner; + +/** + * Simple {@link com.rapidminer.core.concurrency.ConcurrencyContext} to be used with a single {@link Process}. + *

    + * The context does not implement the submission methods for {@link java.util.concurrent.ForkJoinTask}s. + * + * @author Jonas Wilms-Pfau + * @since 9.1.0 + */ +public class BackgroundConcurrencyContext extends AbstractConcurrencyContext { + + /** + * The pool used by this context + */ + private static final LazyPool BACKGROUND_POOL = new LazyPool(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS_BACKGROUND); + + /** + * Creates a new {@link BackgroundConcurrencyContext} for the given {@link Process}. + *

    + * The context assumes that only operators that belong to the corresponding process submit tasks to this context. + * + * @param process + * the corresponding process + */ + public BackgroundConcurrencyContext(Process process) { + super(process, BACKGROUND_POOL); + } +} diff --git a/src/main/java/com/rapidminer/studio/concurrency/internal/ConcurrencyExecutionService.java b/src/main/java/com/rapidminer/studio/concurrency/internal/ConcurrencyExecutionService.java index 80dc44d19..f9d77f02e 100644 --- a/src/main/java/com/rapidminer/studio/concurrency/internal/ConcurrencyExecutionService.java +++ b/src/main/java/com/rapidminer/studio/concurrency/internal/ConcurrencyExecutionService.java @@ -33,6 +33,7 @@ import com.rapidminer.studio.concurrency.internal.util.BackgroundExecutionServiceListener; import com.rapidminer.studio.concurrency.internal.util.ProcessBackgroundExecution; import com.rapidminer.studio.internal.ParameterServiceRegistry; +import com.rapidminer.studio.internal.Resources; /** @@ -62,7 +63,9 @@ public interface ConcurrencyExecutionService { * @return the recommended batch size. Will never be less than the user setting of * {@link RapidMiner#PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS} * @since 7.5 + * @deprecated Use {@link #getRecommendedConcurrencyBatchSize(Operator)} instead */ + @Deprecated public static int getRecommendedConcurrencyBatchSize() { String threadSettingString = ParameterServiceRegistry.INSTANCE .getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS); @@ -78,6 +81,24 @@ public static int getRecommendedConcurrencyBatchSize() { return Math.max(2_000, threadSetting); } + /** + * Calculates the recommended batch size for parallel operators. Use when deciding how many + * tasks to submit to + * {@link ConcurrencyExecutionService#executeOperatorTasks(Operator, java.util.List)} + * simultaneously. + * + * @return the recommended batch size. Will never be less than the user setting of + * {@link RapidMiner#PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS} or {@link RapidMiner#PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS_BACKGROUND} + * @since 9.1 + */ + public static int getRecommendedConcurrencyBatchSize(Operator operator) { + if (operator == null) { + return getRecommendedConcurrencyBatchSize(); + } + int threadSetting = Resources.getConcurrencyContext(operator).getParallelism(); + return Math.max(2_000, threadSetting); + } + /** * This method executes the given process in the background. This method does * not block. diff --git a/src/main/java/com/rapidminer/studio/concurrency/internal/LazyPool.java b/src/main/java/com/rapidminer/studio/concurrency/internal/LazyPool.java new file mode 100644 index 000000000..dffd1cea7 --- /dev/null +++ b/src/main/java/com/rapidminer/studio/concurrency/internal/LazyPool.java @@ -0,0 +1,205 @@ +/** + * Copyright (C) 2001-2018 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.studio.concurrency.internal; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Objects; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; + +import com.rapidminer.studio.internal.ParameterServiceRegistry; +import com.rapidminer.tools.I18N; +import com.rapidminer.tools.LogService; + + +/** + * Supplies a ForkJoinPool if needed Only usable by {@link AbstractConcurrencyContext} + * + * @author Jonas Wilms-Pfau (internals by Gisa Schaefer, Michael Knopf) + * @see AbstractConcurrencyContext + * @since 9.1.0 + */ +class LazyPool { + + /** + * The current ForkJoinPool implementation restricts the maximum number of running threads to 32767. Attempts to + * create pools with greater than the maximum number result in IllegalArgumentException. + */ + private static final int FJPOOL_MAXIMAL_PARALLELISM = 32767; + + /** + * Locks to handle access from different threads + */ + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + /** + * The fork join pool all task are submitted to. + */ + private ForkJoinPool pool = null; + + private final String key; + + /** + * Creates a new pool from the given settings key + * + * @param settingsKey + * used for logging and the default desired parallelism level + */ + LazyPool(String settingsKey) { + Objects.requireNonNull(settingsKey); + this.key = settingsKey; + } + + /** + * Returns a new instance that for the given context + * + * @param context + * the ConcurrencyContext + * @return a context specific instance + */ + LazyPool.Instance getInstance(AbstractConcurrencyContext context) { + return new LazyPool.Instance(context); + } + + /** + * Instance of this pool for a specific Context + */ + final class Instance { + + private final AbstractConcurrencyContext context; + + /** + * Creates a new Instance for this context + * + * @param context + * the context + */ + private Instance(AbstractConcurrencyContext context) { + Objects.requireNonNull(context); + this.context = context; + } + + /** + * This method verifies and returns a JVM-wide, static FJPool. Override if a different pool behavior is needed. + * + * @return the ForkJoinPool to use for this context instance for execution. + */ + ForkJoinPool getForkJoinPool() { + readLock.lock(); + try { + if (!context.isPoolOutdated()) { + // nothing to do + return pool; + } + } finally { + readLock.unlock(); + } + writeLock.lock(); + try { + if (!context.isPoolOutdated()) { + // pool has been updated in the meantime + // no reason to re-create the pool once again + return pool; + } + if (pool != null) { + pool.shutdown(); + } + int desiredParallelismLevel = context.getDesiredParallelismLevel(); + pool = new ForkJoinPool(desiredParallelismLevel); + LogService.getRoot().log(Level.CONFIG, + "com.rapidminer.concurrency.concurrency_context.pool_creation", + new Object[]{desiredParallelismLevel, I18N.getSettingsMessage(key, I18N.SettingsType.TITLE)}); + return pool; + } finally { + writeLock.unlock(); + } + } + + /** + * Checks if the JVM-wide, static pool needs to be re-created. Override if a different pool behavior is needed. + * + * @return {@code true} if the current pool is {@code null} or the {@link AbstractConcurrencyContext#getDesiredParallelismLevel} + * is not equal to the current {@link #pool} parallelism otherwise {@code false} + */ + boolean isPoolOutdated() { + return pool == null || context.getDesiredParallelismLevel() != pool.getParallelism(); + } + + /** + * Returns the targeted parallelism level of this pool. + *

    + * The targeted parallelism level provides an upper bound for the number of tasks that will be executed + * in parallel by this context. It does not guarantee that this bound will be matched during execution. Note + * that the targeted parallelism level need not match the number of processors available to the Java {@link + * Runtime}. + *

    + * You can use the targeted parallelism level as an indicator for partitioning your computation. For instance, a + * parallelism level of {@code 8} indicates that should partition your task into + * at least eight tasks to fully utilize the context. A parallelism level of {@code 1} + * indicates a single threaded execution of all submitted tasks. + * + * @return the targeted parallelism level + */ + int getParallelism() { + if (pool != null) { + return AccessController.doPrivileged((PrivilegedAction) context::getForkJoinPool) + .getParallelism(); + } else { + return context.getDesiredParallelismLevel(); + } + } + + /** + * Helper method to get the desired parallelism level for the given setting + * + * @return the desired parallelism level + */ + int getDesiredParallelismLevel() { + String numberOfThreads = ParameterServiceRegistry.INSTANCE.getParameterValue(key); + + int userLevel = 0; + + if (numberOfThreads != null) { + try { + userLevel = Integer.parseInt(numberOfThreads); + LogService.getRoot().log(Level.FINE, "com.rapidminer.concurrency.concurrency_context.parse_success", + new Object[]{userLevel, I18N.getSettingsMessage(key, I18N.SettingsType.TITLE)}); + } catch (NumberFormatException e) { + // ignore and use default value + LogService.getRoot().log(Level.FINE, "com.rapidminer.concurrency.concurrency_context.parse_failure", + new Object[]{numberOfThreads, I18N.getSettingsMessage(key, I18N.SettingsType.TITLE)}); + } + } + + if (userLevel <= 0) { + userLevel = Math.max(1, Runtime.getRuntime().availableProcessors() - 1); + } + + // should not happen, but we want to avoid any exception during pool creation + if (userLevel > FJPOOL_MAXIMAL_PARALLELISM) { + userLevel = FJPOOL_MAXIMAL_PARALLELISM; + } + return userLevel; + } + } +} diff --git a/src/main/java/com/rapidminer/studio/concurrency/internal/StudioConcurrencyContext.java b/src/main/java/com/rapidminer/studio/concurrency/internal/StudioConcurrencyContext.java index 54eb03819..db9545a2f 100644 --- a/src/main/java/com/rapidminer/studio/concurrency/internal/StudioConcurrencyContext.java +++ b/src/main/java/com/rapidminer/studio/concurrency/internal/StudioConcurrencyContext.java @@ -18,343 +18,34 @@ */ package com.rapidminer.studio.concurrency.internal; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.ForkJoinWorkerThread; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.logging.Level; - import com.rapidminer.Process; import com.rapidminer.RapidMiner; -import com.rapidminer.core.concurrency.ConcurrencyContext; -import com.rapidminer.core.concurrency.ExecutionStoppedException; -import com.rapidminer.studio.internal.ParameterServiceRegistry; -import com.rapidminer.studio.internal.ProcessStoppedRuntimeException; -import com.rapidminer.tools.LogService; /** - * Simple {@link ConcurrencyContext} to be used with a single {@link Process}. + * Simple {@link com.rapidminer.core.concurrency.ConcurrencyContext} to be used with a single {@link Process}. *

    - * The context does not implement the submission methods for {@link ForkJoinTask}s. + * The context does not implement the submission methods for {@link java.util.concurrent.ForkJoinTask}s. * * @author Gisa Schaefer, Michael Knopf * @since 6.2.0 */ -public class StudioConcurrencyContext implements ConcurrencyContext { +public class StudioConcurrencyContext extends AbstractConcurrencyContext { /** - * The current ForkJoinPool implementation restricts the maximum number of running threads to - * 32767. Attempts to create pools with greater than the maximum number result in - * IllegalArgumentException. + * The pool used by this context */ - private static final int FJPOOL_MAXIMAL_PARALLELISM = 32767; - - /** Locks to handle access from different threads */ - private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock(true); - private static final Lock READ_LOCK = LOCK.readLock(); - private static final Lock WRITE_LOCK = LOCK.writeLock(); - - /** The fork join pool all task are submitted to. */ - private static ForkJoinPool pool = null; - - /** The corresponding process. */ - private final Process process; - - + private static final LazyPool FOREGROUND_POOL = new LazyPool(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS); /** - * Creates a new {@link ConcurrencyContext} for the given {@link Process}. + * Creates a new {@link StudioConcurrencyContext} for the given {@link Process}. *

    - * The context assumes that only operators that belong to the corresponding process submit tasks - * to this context. + * The context assumes that only operators that belong to the corresponding process submit tasks to this context. * * @param process - * the corresponding process + * the corresponding process */ public StudioConcurrencyContext(Process process) { - if (process == null) { - throw new IllegalArgumentException("process must not be null"); - } - this.process = process; - } - - @Override - public void run(List runnables) throws ExecutionException, ExecutionStoppedException { - if (runnables == null) { - throw new IllegalArgumentException("runnables must not be null"); - } - - // nothing to do if list is empty - if (runnables.isEmpty()) { - return; - } - - // check for null runnables - for (Runnable runnable : runnables) { - if (runnable == null) { - throw new IllegalArgumentException("runnables must not contain null"); - } - } - - // wrap runnables in callables - List> callables = new ArrayList<>(runnables.size()); - for (final Runnable runnable : runnables) { - callables.add(() -> { - runnable.run(); - return null; - }); - } - - // submit callables without further checks - call(callables); - } - - @Override - public List call(List> callables) - throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { - if (callables == null) { - throw new IllegalArgumentException("callables must not be null"); - } - - // nothing to do if list is empty - if (callables.isEmpty()) { - return Collections.emptyList(); - } - - // check for null tasks - for (Callable callable : callables) { - if (callable == null) { - throw new IllegalArgumentException("callables must not contain null"); - } - } - - ForkJoinPool forkJoinPool = AccessController.doPrivileged( - (PrivilegedAction) this::getForkJoinPool); - // handle submissions from inside and outside the pool differently - Thread currentThread = Thread.currentThread(); - if (currentThread instanceof ForkJoinWorkerThread - && ((ForkJoinWorkerThread) currentThread).getPool() == forkJoinPool) { - return RecursiveWrapper.call(callables); - } else { - final List> futures = new ArrayList<>(callables.size()); - for (Callable callable : callables) { - futures.add(forkJoinPool.submit(callable)); - } - return collectResults(futures); - } - } - - @Override - public List> submit(List> callables) throws IllegalArgumentException { - if (callables == null) { - throw new IllegalArgumentException("callables must not be null"); - } - - // nothing to do if list is empty - if (callables.isEmpty()) { - return Collections.emptyList(); - } - - // check for null tasks - for (Callable callable : callables) { - if (callable == null) { - throw new IllegalArgumentException("callables must not contain null"); - } - } - - ForkJoinPool forkJoinPool = AccessController.doPrivileged( - (PrivilegedAction) this::getForkJoinPool); - // handle submissions from inside and outside the pool differently - Thread currentThread = Thread.currentThread(); - if (currentThread instanceof ForkJoinWorkerThread - && ((ForkJoinWorkerThread) currentThread).getPool() == forkJoinPool) { - final List> futures = new ArrayList<>(callables.size()); - for (Callable callable : callables) { - futures.add(ForkJoinTask.adapt(callable).fork()); - } - return futures; - } else { - // submit callables without further checks - final List> futures = new ArrayList<>(callables.size()); - for (Callable callable : callables) { - futures.add(forkJoinPool.submit(callable)); - } - return futures; - } - } - - @Override - public List collectResults(List> futures) - throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { - if (futures == null) { - throw new IllegalArgumentException("futures must not be null"); - } - - // nothing to do if list is empty - if (futures.isEmpty()) { - return Collections.emptyList(); - } - - // check for null tasks - for (Future future : futures) { - if (future == null) { - throw new IllegalArgumentException("futures must not contain null"); - } - } - - List results = new ArrayList<>(futures.size()); - for (Future future : futures) { - try { - T result = future.get(); - results.add(result); - } catch (InterruptedException | RejectedExecutionException e) { - // The pool's invokeAll() method calls Future.get() internally. If the process is - // stopped by the user, these calls might be interrupted before calls to - // checkStatus() throw an ExecutionStoppedException. Thus, we need to check the - // current status again. - checkStatus(); - // InterruptedExceptions are very unlikely to happen at this point, since the above - // calls to get() will return immediately. A RejectedExectutionException is an - // extreme corner case as well. In both cases, there is no benefit for the API user - // if the exception is passed on directly. Thus, we can wrap it within a - // ExecutionException which is part of the API. - throw new ExecutionException(e); - } catch (ExecutionException e) { - // A ProcessStoppedRuntimeException is an internal exception thrown if the user - // requests the process to stop (see the checkStatus() implementation of this - // class). This exception should not be wrapped or consumed here, since it is - // handled by the operator implementation itself. - if (e.getCause() instanceof ProcessStoppedRuntimeException) { - throw (ExecutionStoppedException) e.getCause(); - } else { - throw e; - } - } - } - - return results; + super(process, FOREGROUND_POOL); } - - @Override - public int getParallelism() { - if (pool != null) { - return AccessController.doPrivileged((PrivilegedAction) this::getForkJoinPool) - .getParallelism(); - } else { - return getDesiredParallelismLevel(); - } - } - - @Override - public void checkStatus() throws ExecutionStoppedException { - if (process.shouldStop()) { - throw new ProcessStoppedRuntimeException(); - } - } - - @Override - public T invoke(ForkJoinTask task) throws ExecutionException, ExecutionStoppedException { - throw new UnsupportedOperationException(); - } - - @Override - public List invokeAll(final List> tasks) throws ExecutionException, - ExecutionStoppedException { - throw new UnsupportedOperationException(); - } - - /** - * This method verifies and returns a JVM-wide, static FJPool. Override if a different pool behavior is needed. - * - * @return the ForkJoinPool to use for this context instance for execution. - */ - protected ForkJoinPool getForkJoinPool() { - READ_LOCK.lock(); - try { - if (!isPoolOutdated()) { - // nothing to do - return pool; - } - } finally { - READ_LOCK.unlock(); - } - WRITE_LOCK.lock(); - try { - if (!isPoolOutdated()) { - // pool has been updated in the meantime - // no reason to re-create the pool once again - return pool; - } - if (pool != null) { - pool.shutdown(); - } - int desiredParallelismLevel = getDesiredParallelismLevel(); - pool = new ForkJoinPool(desiredParallelismLevel); - LogService.getRoot().log(Level.CONFIG, - "com.rapidminer.concurrency.concurrency_context.pool_creation", - desiredParallelismLevel); - return pool; - } finally { - WRITE_LOCK.unlock(); - } - } - - /** - * Checks if the JVM-wide, static pool needs to be re-created. Override if a different pool behavior is needed. - * - * @return {@code true} if the current pool is {@code null} or the - * {@link #getDesiredParallelismLevel()} is not equal to the current {@link #pool} - * parallelism otherwise {@code false} - */ - protected boolean isPoolOutdated() { - return pool == null || getDesiredParallelismLevel() != pool.getParallelism(); - } - - /** - * Returns the desired number of cores to be used for concurrent computations for the JVM-wide, static pool. This - * number is always at least one and either bound by a license limit or by the user's configuration. Override if a - * different pool behavior is needed. - * - * @return the desired parallelism level - */ - protected int getDesiredParallelismLevel() { - String numberOfThreads = ParameterServiceRegistry.INSTANCE - .getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_NUMBER_OF_THREADS); - - int userLevel = 0; - - if (numberOfThreads != null) { - try { - userLevel = Integer.parseInt(numberOfThreads); - LogService.getRoot().log(Level.FINE, "com.rapidminer.concurrency.concurrency_context.parse_success", - userLevel); - } catch (NumberFormatException e) { - // ignore and use default value - LogService.getRoot().log(Level.FINE, "com.rapidminer.concurrency.concurrency_context.parse_failure", - numberOfThreads); - } - } - - if (userLevel <= 0) { - userLevel = Math.max(1, Runtime.getRuntime().availableProcessors() - 1); - } - - // should not happen, but we want to avoid any exception during pool creation - if (userLevel > FJPOOL_MAXIMAL_PARALLELISM) { - userLevel = FJPOOL_MAXIMAL_PARALLELISM; - } - return userLevel; - } - } diff --git a/src/main/java/com/rapidminer/studio/internal/Resources.java b/src/main/java/com/rapidminer/studio/internal/Resources.java index defaa7861..b03e58abe 100644 --- a/src/main/java/com/rapidminer/studio/internal/Resources.java +++ b/src/main/java/com/rapidminer/studio/internal/Resources.java @@ -40,7 +40,7 @@ */ public class Resources { - private static final String USER_DATA_KEY = "com.rapidminer.core.concurrency.ContextUserData"; + public static final String CONTEXT_KEY = "com.rapidminer.core.concurrency.ContextUserData"; /** * Wrapper to store {@link ConcurrencyContext} within the root operator of a process. @@ -73,11 +73,10 @@ private ConcurrencyContext getContext() { * * @author Marco Boeck */ - public static class OverridingContextUserData implements UserData { - - private final ConcurrencyContext context; + public static class OverridingContextUserData extends ContextUserData { public OverridingContextUserData(ConcurrencyContext context) { + super(context); // make sure this cannot be called without RapidMiner internal permissions try { if (System.getSecurityManager() != null) { @@ -86,18 +85,7 @@ public OverridingContextUserData(ConcurrencyContext context) { } catch (AccessControlException e) { throw new UnsupportedOperationException("Internal API, cannot be called by unauthorized sources."); } - this.context = context; - } - - @Override - public final UserData copyUserData(Object newParent) { - return this; - } - - private ConcurrencyContext getContext() { - return this.context; } - } /** @@ -116,20 +104,19 @@ public static ConcurrencyContext getConcurrencyContext(Operator operator) { // currently used by RapidMiner Server web services ProcessRootOperator rootOperator = operator.getProcess().getRootOperator(); if (rootOperator.getUserData(ConcurrencyExecutionService.OVERRIDING_CONTEXT) != null) { - OverridingContextUserData data = (OverridingContextUserData) rootOperator.getUserData(ConcurrencyExecutionService.OVERRIDING_CONTEXT); + ContextUserData data = (ContextUserData) rootOperator.getUserData(ConcurrencyExecutionService.OVERRIDING_CONTEXT); return data.getContext(); } - Operator root = operator.getRoot(); - if (root.getUserData(USER_DATA_KEY) != null) { - ContextUserData data = (ContextUserData) root.getUserData(USER_DATA_KEY); + if (rootOperator.getUserData(CONTEXT_KEY) != null) { + ContextUserData data = (ContextUserData) rootOperator.getUserData(CONTEXT_KEY); return data.getContext(); } Process process = operator.getProcess(); StudioConcurrencyContext context = new StudioConcurrencyContext(process); ContextUserData data = new ContextUserData(context); - root.setUserData(USER_DATA_KEY, data); + rootOperator.setUserData(CONTEXT_KEY, data); return context; } } diff --git a/src/main/java/com/rapidminer/studio/io/data/DefaultDataSetMetaData.java b/src/main/java/com/rapidminer/studio/io/data/DefaultDataSetMetaData.java index b346ad2f6..abc8dfac8 100644 --- a/src/main/java/com/rapidminer/studio/io/data/DefaultDataSetMetaData.java +++ b/src/main/java/com/rapidminer/studio/io/data/DefaultDataSetMetaData.java @@ -78,26 +78,14 @@ private DefaultDataSetMetaData(DefaultDataSetMetaData other) { @Override public DateFormat getDateFormat() { if (dateFormat == null) { - this.dateFormat = new ThreadLocal() { - - @Override - protected DateFormat initialValue() { - return Tools.DATE_TIME_FORMAT.get(); - } - }; + this.dateFormat = ThreadLocal.withInitial(Tools.DATE_TIME_FORMAT::get); } return this.dateFormat.get(); } @Override public void setDateFormat(final DateFormat dateFormat) { - this.dateFormat = new ThreadLocal() { - - @Override - protected DateFormat initialValue() { - return dateFormat; - } - }; + this.dateFormat = ThreadLocal.withInitial(() -> dateFormat); } @Override @@ -111,8 +99,8 @@ public void configure(DataSetMetaData other) { for (ColumnMetaData column : other.getColumnMetaData()) { columnList.add(new DefaultColumnMetaData(column)); } - - this.setDateFormat((DateFormat) other.getDateFormat().clone()); + DateFormat otherDateFormat = other.getDateFormat(); + this.setDateFormat(otherDateFormat != null ? (DateFormat) otherDateFormat.clone() : null); this.setFaultTolerant(other.isFaultTolerant()); } diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/ResultSetAdapterUtils.java b/src/main/java/com/rapidminer/studio/io/data/internal/ResultSetAdapterUtils.java index f41d3b971..fa41c5dfc 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/ResultSetAdapterUtils.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/ResultSetAdapterUtils.java @@ -108,7 +108,7 @@ public static DataSetMetaData createMetaData(DataResultSet resultSet, NumberForm * @param trimAttributeNames * whether to trim attribute names before creating meta data or not * @return the new {@link DataSetMetaData} instance which contains meta data retrieved from the - * column name extraction and column type guessing + * column name extraction and column type guessing * @throws HeaderRowNotFoundException * if the header row was not found * @throws StartRowNotFoundException @@ -121,6 +121,42 @@ public static DataSetMetaData createMetaData(DataResultSet resultSet, NumberForm */ public static DataSetMetaData createMetaData(DataResultSet resultSet, NumberFormat numberFormat, int startingRowIndex, int headerRowIndex, boolean trimAttributeNames) throws HeaderRowNotFoundException, StartRowNotFoundException, HeaderRowBehindStartRowException, DataSetException { + return createMetaData(resultSet, numberFormat, startingRowIndex, headerRowIndex, trimAttributeNames, false); + } + + /** + * Creates a new {@link DataSetMetaData} instance for the provided {@link DataResultSet} based + * on the provided data range and header row index (if any). This includes reading the column + * names and guessing the column types for the selected columns. For guessing the column types + * the logic from {@link DataResultSetTranslator} is used. + * + * @param resultSet + * the {@link DataResultSet} that should be used to extract the meta data + * @param numberFormat + * the number format that should be used during column type guessing + * @param startingRowIndex + * the 0-based index of the first data row (not including the header row) + * @param headerRowIndex + * the 0-based index for the header row (if any, + * {@link ResultSetAdapter#NO_HEADER_ROW} otherwise) + * @param trimAttributeNames + * whether to trim attribute names before creating meta data or not + * @param trimForGuessing + * whether values should be trimmed for type guessing + * @return the new {@link DataSetMetaData} instance which contains meta data retrieved from the + * column name extraction and column type guessing + * @throws HeaderRowNotFoundException + * if the header row was not found + * @throws StartRowNotFoundException + * if the data start row was not found + * @throws HeaderRowBehindStartRowException + * in case the headerRowIndex > startingRowIndex + * @throws DataSetException + * if the meta data fetching fails + * @since 9.1.1 + */ + public static DataSetMetaData createMetaData(DataResultSet resultSet, NumberFormat numberFormat, int startingRowIndex, int headerRowIndex, boolean trimAttributeNames, boolean trimForGuessing) + throws HeaderRowNotFoundException, StartRowNotFoundException, HeaderRowBehindStartRowException, DataSetException { // check whether the header row index is lower or equal to the starting row if (headerRowIndex > startingRowIndex) { @@ -132,12 +168,11 @@ public static DataSetMetaData createMetaData(DataResultSet resultSet, NumberForm String[] columnNames = getColumnNames(resultSet, headerRowIndex, startingRowIndex, numberOfColumns, trimAttributeNames); List columnTypes = guessColumnTypes(resultSet, startingRowIndex, headerRowIndex, numberOfColumns, - numberFormat); + numberFormat, trimForGuessing); return new DefaultDataSetMetaData(Arrays.asList(columnNames), columnTypes); } catch (OperatorException e) { throw new DataSetException(e.getMessage(), e); } - } /** @@ -244,10 +279,10 @@ private static String[] getColumnNames(DataResultSet resultSet, int headerRowInd * logic and transforming the guessed value types into {@link ColumnType}s. */ private static List guessColumnTypes(DataResultSet dataResultSet, int startingRow, int headerRow, - int numberOfColumns, NumberFormat numberFormat) throws DataSetException { + int numberOfColumns, NumberFormat numberFormat, boolean trimForGuessing) throws DataSetException { try { - int[] valueTypes = getValueTypes(dataResultSet, startingRow, headerRow, numberOfColumns, numberFormat); + int[] valueTypes = getValueTypes(dataResultSet, startingRow, headerRow, numberOfColumns, numberFormat, trimForGuessing); List columnTypes = new ArrayList<>(valueTypes.length); for (int type : valueTypes) { columnTypes.add(transformValueType(type)); @@ -325,12 +360,13 @@ public static int transformColumnType(ColumnType columnType) { * if the guessing failed because of an IOException */ private static int[] getValueTypes(DataResultSet dataResultSet, int startingRow, int headerRow, int numberOfColumns, - NumberFormat numberFormat) throws OperatorException { + NumberFormat numberFormat, boolean trimForGuessing) throws OperatorException { // generate a DataResultSetTranslationConfiguration DataResultSetTranslationConfiguration translationConfiguration = new DataResultSetTranslationConfiguration( dataResultSet, getAnnotations(startingRow, headerRow)); translationConfiguration.setNumberFormat(numberFormat); + translationConfiguration.setTrimForGuessing(trimForGuessing); // use a translator to guess value types given the configuration new DataResultSetTranslator(null).guessValueTypes(translationConfiguration, dataResultSet, null); diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/file/LocalFileDataSource.java b/src/main/java/com/rapidminer/studio/io/data/internal/file/LocalFileDataSource.java index ac4a4fb5a..7f7695edb 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/file/LocalFileDataSource.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/file/LocalFileDataSource.java @@ -26,6 +26,7 @@ import com.rapidminer.core.io.data.source.DataSource; import com.rapidminer.core.io.data.source.DataSourceConfiguration; import com.rapidminer.core.io.data.source.DataSourceFactoryRegistry; +import com.rapidminer.core.io.data.source.DataSourceFeature; import com.rapidminer.core.io.data.source.FileDataSource; import com.rapidminer.core.io.data.source.FileDataSourceFactory; @@ -155,4 +156,8 @@ public void configure(DataSourceConfiguration configuration) throws DataSetExcep throw new DataSetException("Unknown file data source for key '" + fileDatasourceKey + "'"); } + @Override + public boolean supportsFeature(DataSourceFeature feature) { + return fileDataSource != null ? fileDataSource.supportsFeature(feature) : super.supportsFeature(feature); + } } diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSource.java b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSource.java index 77a4dc9e3..6797ea32d 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSource.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSource.java @@ -163,12 +163,16 @@ public void createMetaData() throws DataSetException { configuration.setColumnSeparators(getResultSetConfiguration().getColumnSeparators()); configuration.setHasHeaderRow(getResultSetConfiguration().hasHeaderRow()); configuration.setHeaderRow(getResultSetConfiguration().getHeaderRow()); + configuration.setTrimValuesForParsing(getResultSetConfiguration().trimValuesForParsing()); + configuration.setStartingRow(getResultSetConfiguration().getStartingRow()); + configuration.setTrimLines(getResultSetConfiguration().isTrimLines()); + configuration.setSkipUTF8BOM(getResultSetConfiguration().isSkippingUTF8BOM()); int headerRowIndex = configuration.hasHeaderRow() ? configuration.getHeaderRow() : ResultSetAdapter.NO_HEADER_ROW; try (DataResultSet dataSet = configuration.makeDataResultSet(null)) { this.metaData = ResultSetAdapterUtils.createMetaData(dataSet, getNumberFormat(), getDataStartRow(), - headerRowIndex); + headerRowIndex, false, configuration.trimValuesForParsing()); } catch (OperatorException e) { throw new DataSetException(e.getMessage(), e); } diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVFormatSpecificationPanel.java b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVFormatSpecificationPanel.java index d347738e1..67d934903 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVFormatSpecificationPanel.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVFormatSpecificationPanel.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.studio.io.data.internal.file.csv; import java.awt.BorderLayout; @@ -65,6 +65,7 @@ import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.tools.CharTextField; import com.rapidminer.gui.tools.ColoredTableCellRenderer; +import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ExtendedJTable; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ResourceAction; @@ -246,8 +247,7 @@ private void registerListeners() { Boolean.toString(headerRow.isSelected())); configuration.setHasHeaderRow(headerRow.isSelected()); headerRowSpinner.setEnabled(headerRow.isSelected()); - previewTable.repaint(); - fireStateChanged(); + settingsChanged(); }); encodingComboBox.addItemListener(e -> { @@ -424,11 +424,9 @@ public void focusLost(FocusEvent e) { }); startRowSpinner.addChangeListener(e -> { updateStartingRow(); - fireStateChanged(); }); headerRowSpinner.addChangeListener(e -> { updateHeaderRow(); - fireStateChanged(); }); } @@ -512,7 +510,7 @@ private JComponent makePreviewTable() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { + int row, int column) { JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); adjustCell(row, label, boldFont); return label; @@ -522,7 +520,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole loadingContentPane = new LoadingContentPane("loading_data", previewTable); - tablePane = new JScrollPane(loadingContentPane); + tablePane = new ExtendedJScrollPane(loadingContentPane); tablePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); tablePane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); tablePane.setBorder(null); @@ -646,7 +644,7 @@ private void settingsChanged() { public void run() { try { final TableModel model = configuration.makePreviewTableModel(getProgressListener()); - SwingUtilities.invokeAndWait(() -> { + SwingTools.invokeAndWait(() -> { previewTable.setModel(model); tablePane.setRowHeaderView(new RowNumberTable(previewTable)); if (model.getRowCount() > 0) { @@ -718,16 +716,20 @@ private void adjustCell(int row, JLabel cell, Font boldFont) { private void updateStartingRow() { int startingRow = (int) startRowSpinner.getValue(); configuration.setStartingRow(startingRow - 1); - previewTable.repaint(); + settingsChanged(); } /** * Sets the header row as defined in the headerRowSpinner and repaints the table. */ private void updateHeaderRow() { - int headerRow = (int) headerRowSpinner.getValue(); - configuration.setHeaderRow(headerRow - 1); - previewTable.repaint(); + int headerRowNumber = (int) headerRowSpinner.getValue(); + configuration.setHeaderRow(headerRowNumber - 1); + if (headerRowNumber > configuration.getStartingRow()) { + startRowSpinner.getModel().setValue(headerRowNumber); + configuration.setStartingRow(headerRowNumber - 1); + } + settingsChanged(); } /** @@ -744,18 +746,18 @@ void killCurrentErrorBubbleWindow() { * Creates an error bubble for the component and kills other error bubbles. * * @param component - * the component for which to show the bubble + * the component for which to show the bubble * @param i18n - * the i18n key + * the i18n key * @param arguments - * arguments for the i18n + * arguments for the i18n */ private void createErrorBubbleWindow(JComponent component, String i18n, Object... arguments) { killCurrentErrorBubbleWindow(); JButton okayButton = new JButton(I18N.getGUILabel("io.dataimport.step.excel.sheet_selection.got_it")); final ComponentBubbleWindow errorWindow = new ComponentBubbleWindow(component, BubbleStyle.ERROR, SwingUtilities.getWindowAncestor(this), AlignedSide.BOTTOM, i18n, null, null, false, true, - new JButton[] { okayButton }, arguments); + new JButton[]{okayButton}, arguments); okayButton.addActionListener(e -> errorWindow.killBubble(false)); // show and remember error window @@ -792,29 +794,28 @@ void notifyHeaderRowBehindStartRow() { * Sets the column separator associated to the splitter. * * @param splitter - * a {@link ColumnSplitter} + * a {@link ColumnSplitter} */ void setColumnSeparator(ColumnSplitter splitter) { - switch (splitter) { - case COMMA: - separationComboBox.setSelectedItem(ColumnSeparator.COMMA); - break; - case TAB: - separationComboBox.setSelectedItem(ColumnSeparator.TAB); - break; - case PIPE: - regexTextField.setText(splitter.getPattern().pattern()); - separationComboBox.setSelectedItem(ColumnSeparator.REGULAR_EXPRESSION); - break; - case TILDE: - regexTextField.setText(splitter.getPattern().pattern()); - separationComboBox.setSelectedItem(ColumnSeparator.REGULAR_EXPRESSION); - break; - default: - case SEMI_COLON: - separationComboBox.setSelectedItem(ColumnSeparator.SEMICOLON); - break; - } + SwingTools.invokeLater(() -> { + switch (splitter) { + case COMMA: + separationComboBox.setSelectedItem(ColumnSeparator.COMMA); + break; + case TAB: + separationComboBox.setSelectedItem(ColumnSeparator.TAB); + break; + case PIPE: + case TILDE: + regexTextField.setText(splitter.getPattern().pattern()); + separationComboBox.setSelectedItem(ColumnSeparator.REGULAR_EXPRESSION); + break; + default: + case SEMI_COLON: + separationComboBox.setSelectedItem(ColumnSeparator.SEMICOLON); + break; + } + }); } @@ -822,29 +823,33 @@ void setColumnSeparator(ColumnSplitter splitter) { * Sets the text qualifier * * @param qualifier - * a {@link com.rapidminer.operator.nio.model.CSVResultSet.TextQualifier} + * a {@link com.rapidminer.operator.nio.model.CSVResultSet.TextQualifier} */ - void setTextQualifier(CSVResultSet.TextQualifier qualifier){ - quoteCharacterTextField.setText(qualifier.getString()); - configuration.setQuoteCharacter(quoteCharacterTextField.getText().charAt(0)); + void setTextQualifier(CSVResultSet.TextQualifier qualifier) { + SwingTools.invokeLater(() -> { + quoteCharacterTextField.setText(qualifier.getString()); + configuration.setQuoteCharacter(quoteCharacterTextField.getText().charAt(0)); + }); } /** * Sets the Decimal Separator * * @param character - * a {@link com.rapidminer.operator.nio.model.CSVResultSet.DecimalCharacter} + * a {@link com.rapidminer.operator.nio.model.CSVResultSet.DecimalCharacter} */ - void setDecimalCharacter(CSVResultSet.DecimalCharacter character){ - decimalCharacterTextField.setText(character.getString()); - configuration.setDecimalCharacter(decimalCharacterTextField.getText().charAt(0)); + void setDecimalCharacter(CSVResultSet.DecimalCharacter character) { + SwingTools.invokeLater(() -> { + decimalCharacterTextField.setText(character.getString()); + configuration.setDecimalCharacter(decimalCharacterTextField.getText().charAt(0)); + }); } /** * Checks that the table has content and the header row is not behind the start row. * * @throws InvalidConfigurationException - * if the conditions are not fulfilled + * if the conditions are not fulfilled */ void validateConfiguration() throws InvalidConfigurationException { if (previewTable.getModel().getRowCount() == 0) { @@ -865,7 +870,7 @@ void validateConfiguration() throws InvalidConfigurationException { * Registers a new change listener. * * @param changeListener - * the listener to register + * the listener to register */ void addChangeListener(ChangeListener changeListener) { this.changeListeners.add(changeListener); diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVResultSetAdapter.java b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVResultSetAdapter.java index 1c0610ae1..566fd28d2 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVResultSetAdapter.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/file/csv/CSVResultSetAdapter.java @@ -43,12 +43,17 @@ class CSVResultSetAdapter extends ResultSetAdapter { @Override public Date getDate(int columnIndex) throws ParseException { String value = getString(columnIndex); + String trimmedValue = value == null ? "" : value.trim(); // check for missing value - if (value == null || value.trim().isEmpty()) { + if (trimmedValue.isEmpty()) { return null; } + if (dataSource.getResultSetConfiguration().trimValuesForParsing()) { + value = trimmedValue; + } + // parse to Date try { return dataSource.getMetadata().getDateFormat().parse(value); @@ -76,12 +81,17 @@ public String getString(int columnIndex) throws ParseException { @Override public double getDouble(int columnIndex) throws ParseException { String value = getString(columnIndex); + String trimmedValue = value == null ? "" : value.trim(); // check for missing value - if (value == null || value.trim().isEmpty()) { + if (trimmedValue.isEmpty()) { return Double.NaN; } + if (dataSource.getResultSetConfiguration().trimValuesForParsing()) { + value = trimmedValue; + } + // parse to double NumberFormat numberFormat = dataSource.getNumberFormat(); if (numberFormat != null) { diff --git a/src/main/java/com/rapidminer/studio/io/data/internal/file/excel/ExcelDataSource.java b/src/main/java/com/rapidminer/studio/io/data/internal/file/excel/ExcelDataSource.java index ef8e184fa..9b585157b 100644 --- a/src/main/java/com/rapidminer/studio/io/data/internal/file/excel/ExcelDataSource.java +++ b/src/main/java/com/rapidminer/studio/io/data/internal/file/excel/ExcelDataSource.java @@ -25,8 +25,10 @@ import com.rapidminer.core.io.data.DataSetMetaData; import com.rapidminer.core.io.data.source.DataSource; import com.rapidminer.core.io.data.source.DataSourceConfiguration; +import com.rapidminer.core.io.data.source.DataSourceFeature; import com.rapidminer.core.io.data.source.FileDataSource; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.nio.ExcelDateTimeTypeGuesser; import com.rapidminer.operator.nio.model.DataResultSet; import com.rapidminer.operator.nio.model.DateFormatProvider; import com.rapidminer.operator.nio.model.ExcelResultSetConfiguration; @@ -236,6 +238,7 @@ public void createMetaData() throws DataSetException { try (DataResultSet resultSet = configuration.makeDataResultSet(null)) { this.metaData = ResultSetAdapterUtils.createMetaData(resultSet, null, getStartRowIndex(), getHeaderRowIndex()); + this.metaData.configure(ExcelDateTimeTypeGuesser.guessDateTimeColumnType(getData(), metaData)); } catch (OperatorException e) { throw new DataSetException(e.getMessage(), e); } @@ -263,4 +266,9 @@ public void close() throws DataSetException { } } + @Override + public boolean supportsFeature(DataSourceFeature feature){ + return feature == DataSourceFeature.DATETIME_METADATA; + } + } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/DataImportWizard.java b/src/main/java/com/rapidminer/studio/io/gui/internal/DataImportWizard.java index c1063a970..2b02e41cd 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/DataImportWizard.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/DataImportWizard.java @@ -23,7 +23,6 @@ import java.awt.GraphicsConfiguration; import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.LinkedList; @@ -32,10 +31,8 @@ import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; -import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JPanel; -import javax.swing.KeyStroke; import javax.swing.event.ChangeListener; import com.rapidminer.core.io.data.DataSetException; @@ -72,7 +69,7 @@ final class DataImportWizard extends ButtonDialog implements ImportWizard { /** * A template for the header which includes a HTML progress bar. */ - private final String INFO_LABEL_TEXT_TEMPLATE = "

    %s

    " + private static final String INFO_LABEL_TEXT_TEMPLATE = "

    %s

    " + "
    " + "
    "; @@ -183,10 +180,6 @@ public void windowClosed(WindowEvent e) { closeDataSource(); } }); - - getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), - "FINISH"); - getRootPane().getActionMap().put("FINISH", finishAction); } /** @@ -227,11 +220,10 @@ void showStep(final String stepId, WizardDirection direction) { } this.currentStepID = stepId; - updateButtons(); - updateTitle(); - updateInfoHeader(); - SwingTools.invokeLater(() -> { + updateButtons(); + updateTitle(); + updateInfoHeader(); // show step cardLayout.show(cardPanel, stepId); }); @@ -292,12 +284,10 @@ private void updateButtons() { } private void disableButtons() { - SwingTools.invokeLater(() -> { - previousButton.setEnabled(false); - nextButton.setEnabled(false); - finishButton.setEnabled(false); - cancelButton.setEnabled(false); - }); + previousButton.setEnabled(false); + nextButton.setEnabled(false); + finishButton.setEnabled(false); + cancelButton.setEnabled(false); } /** @@ -379,8 +369,10 @@ private void removeStep(WizardStep step) { @Override public void previousStep() { - previousButton.setIcon(LOADING_ICON); - disableButtons(); + SwingTools.invokeLater(() -> { + previousButton.setIcon(LOADING_ICON); + disableButtons(); + }); new Thread(() -> { try { getCurrentStep().viewWillBecomeInvisible(WizardDirection.PREVIOUS); @@ -389,29 +381,33 @@ public void previousStep() { String previousStepID = previousStepIDs.remove(previousStepIDs.size() - 1); showStep(previousStepID, WizardDirection.PREVIOUS); } catch (InvalidConfigurationException e) { - updateButtons(); + SwingTools.invokeLater(this::updateButtons); } }).start(); } @Override public void nextStep(final String stepId) { - nextButton.setIcon(LOADING_ICON); - disableButtons(); + SwingTools.invokeLater(() -> { + nextButton.setIcon(LOADING_ICON); + disableButtons(); + }); new Thread(() -> { try { getCurrentStep().viewWillBecomeInvisible(WizardDirection.NEXT); showStep(stepId, WizardDirection.NEXT); } catch (InvalidConfigurationException e) { - updateButtons(); + SwingTools.invokeLater(this::updateButtons); } }).start(); } @Override public void nextStep() { - nextButton.setIcon(LOADING_ICON); - disableButtons(); + SwingTools.invokeLater(() -> { + nextButton.setIcon(LOADING_ICON); + disableButtons(); + }); new Thread(() -> { try { /* @@ -424,7 +420,7 @@ public void nextStep() { String nextStepID = getCurrentStep().getNextStepID(); showStep(nextStepID, WizardDirection.NEXT); } catch (InvalidConfigurationException e) { - updateButtons(); + SwingTools.invokeLater(this::updateButtons); } }).start(); } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/AbstractToRepositoryStep.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/AbstractToRepositoryStep.java index e58e286e0..750e8075b 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/AbstractToRepositoryStep.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/AbstractToRepositoryStep.java @@ -27,17 +27,14 @@ import java.awt.event.WindowEvent; import java.nio.file.Path; import java.util.concurrent.ExecutionException; - import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.WindowConstants; -import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.rapidminer.core.io.data.source.FileDataSource; @@ -48,7 +45,6 @@ import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ProgressThreadDialog; -import com.rapidminer.gui.tools.ProgressThreadListener; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.SwingTools.ResultRunnable; @@ -85,7 +81,7 @@ private class ProgressUpdater extends SwingWorker { private static final int IDLE_TIME_MS = 500; @Override - protected Void doInBackground() throws Exception { + protected Void doInBackground() { while (backgroundJob != null || confirmDialog != null) { try { // we've finished the background job, close the obsolete @@ -107,13 +103,7 @@ protected Void doInBackground() throws Exception { private static final String CARD_ID_PROGRESS = "progress"; /** Change Listener which is registered to the {@link #chooser} */ - private final ChangeListener changeListener = new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent e) { - AbstractToRepositoryStep.this.fireStateChanged(); - } - }; + private final ChangeListener changeListener = e -> AbstractToRepositoryStep.this.fireStateChanged(); /** {@link ResultRunnable} for the {@link #confirmDialog} */ private final ResultRunnable confirmResultRunnable = new ResultRunnable() { @@ -132,11 +122,7 @@ public Integer run() { @Override public void windowClosing(WindowEvent event) { if (backgroundJob != null) { - if (SwingTools.invokeAndWaitWithResult(confirmResultRunnable) != ConfirmDialog.YES_OPTION) { - closeDialog = false; - } else { - closeDialog = true; - } + closeDialog = SwingTools.invokeAndWaitWithResult(confirmResultRunnable) == ConfirmDialog.YES_OPTION; confirmDialog = null; if (closeDialog && backgroundJob != null) { stopButton.doClick(); @@ -258,7 +244,7 @@ public void viewWillBecomeInvisible(WizardDirection direction) throws InvalidCon final RepositoryLocation entryLocation = new RepositoryLocation(chooser.getRepositoryLocation()); final RepositoryLocation folderLocation = entryLocation.parent(); final Entry entry = folderLocation.locateEntry(); - if (entry == null || !(entry instanceof Folder)) { + if (!(entry instanceof Folder)) { fireStateChanged(); throw new InvalidConfigurationException(); } @@ -297,28 +283,17 @@ public void viewWillBecomeInvisible(WizardDirection direction) throws InvalidCon closeDialog = false; isImportCancelled = false; backgroundJob = getImportThread(entryLocation, parent); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - askBeforeClosing(true); - animationLabel.setText(String.format(IMPORTING_TEXT_TEMPLATE, entryLocation)); - stopButton.setEnabled(true); - showCard(CARD_ID_PROGRESS); - // this call ensures that the progress bar runs smoothly - ProgressThreadDialog.getInstance().setVisible(true, false); - } + SwingTools.invokeLater(() -> { + askBeforeClosing(true); + animationLabel.setText(String.format(IMPORTING_TEXT_TEMPLATE, entryLocation)); + stopButton.setEnabled(true); + showCard(CARD_ID_PROGRESS); + // this call ensures that the progress bar runs smoothly + ProgressThreadDialog.getInstance().setVisible(true, false); }); // Import data with background worker. - backgroundJob.addProgressThreadListener(new ProgressThreadListener() { - - @Override - public void threadFinished(ProgressThread thread) { - backgroundJob = null; - - } - }); + backgroundJob.addProgressThreadListener(thread -> backgroundJob = null); SwingWorker progressUpdater = new ProgressUpdater(); progressUpdater.execute(); backgroundJob.start(); @@ -353,19 +328,15 @@ public void threadFinished(ProgressThread thread) { * behavior of the dialog will be used. */ private void askBeforeClosing(final boolean askBeforeClosing) { - SwingTools.invokeLater(new Runnable() { - - @Override - public void run() { - JDialog dialog = wizard.getDialog(); - if (dialog != null) { - if (askBeforeClosing) { - dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - dialog.addWindowListener(closeListener); - } else { - dialog.setDefaultCloseOperation(defaultCloseOperation); - dialog.removeWindowListener(closeListener); - } + SwingTools.invokeLater(() -> { + JDialog dialog = wizard.getDialog(); + if (dialog != null) { + if (askBeforeClosing) { + dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + dialog.addWindowListener(closeListener); + } else { + dialog.setDefaultCloseOperation(defaultCloseOperation); + dialog.removeWindowListener(closeListener); } } }); @@ -427,13 +398,7 @@ protected abstract ProgressThread getImportThread(final RepositoryLocation entry * the id of the card */ private void showCard(final String cardId) { - SwingTools.invokeLater(new Runnable() { - - @Override - public void run() { - ((CardLayout) mainPanel.getLayout()).show(mainPanel, cardId); - } - }); + SwingTools.invokeLater(() -> ((CardLayout) mainPanel.getLayout()).show(mainPanel, cardId)); } /** diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/LocationSelectionStep.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/LocationSelectionStep.java index 2fd1002b8..168b58768 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/LocationSelectionStep.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/LocationSelectionStep.java @@ -97,7 +97,7 @@ public void viewWillBecomeVisible(WizardDirection direction) throws InvalidConfi final DataSource dataSource = wizard.getDataSource(DataSource.class); // update view content - viewWrapper.removeAll(); + SwingTools.invokeAndWait(() -> viewWrapper.removeAll()); if (dataSource != null) { SwingTools.invokeAndWait(() -> { diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/TypeSelectionView.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/TypeSelectionView.java index 46fa9a628..47c5e0007 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/TypeSelectionView.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/TypeSelectionView.java @@ -32,7 +32,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; - import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -42,8 +41,6 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.event.UndoableEditEvent; -import javax.swing.event.UndoableEditListener; import org.jdesktop.swingx.JXTextField; @@ -140,16 +137,12 @@ public TypeSelectionView(final ImportWizard wizard) { { this.searchTextField = new JXTextField(I18N.getGUILabel("io.dataimport.step.type_selection.search_placeholder")); - this.searchTextField.getDocument().addUndoableEditListener(new UndoableEditListener() { - - @Override - public void undoableEditHappened(UndoableEditEvent e) { - String searchTerm = searchTextField.getText(); - if (searchTerm != null && !searchTerm.trim().isEmpty() && searchTerm.trim().length() > 1) { - updateTypeSelectionContentPanel(searchTerm, false); - } else { - updateTypeSelectionContentPanel(null, false); - } + this.searchTextField.getDocument().addUndoableEditListener(e -> { + String searchTerm = searchTextField.getText(); + if (searchTerm != null && !searchTerm.trim().isEmpty() && searchTerm.trim().length() > 1) { + updateTypeSelectionContentPanel(searchTerm, false); + } else { + updateTypeSelectionContentPanel(null, false); } }); @@ -251,9 +244,11 @@ public void actionPerformed(ActionEvent e) { } private void enableDataSourceButtons(boolean enable) { - for (JButton button : dataSourceSelectionButtons) { - button.setEnabled(enable); - } + SwingTools.invokeLater(() -> { + for (JButton button : dataSourceSelectionButtons) { + button.setEnabled(enable); + } + }); } @SuppressWarnings("rawtypes") @@ -262,9 +257,7 @@ private List getFilteredFactories(String searchTerm) { List result = new LinkedList<>(); if (searchTerm == null || searchTerm.trim().isEmpty()) { - for (DataSourceFactory factory : factories) { - result.add(factory); - } + result.addAll(factories); } else { // filter factories according to search term for (DataSourceFactory factory : factories) { @@ -296,154 +289,134 @@ private void updateTypeSelectionContentPanel(final String searchTerm, final bool } // add new action listener - SEARCH_ACTION_LOG_TIMER.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - DataImportWizardUtils.logStats(DataWizardEventType.SEARCH_TYPE, searchTerm); - } - }); + SEARCH_ACTION_LOG_TIMER.addActionListener(e -> DataImportWizardUtils.logStats(DataWizardEventType.SEARCH_TYPE, searchTerm)); // start countdown SEARCH_ACTION_LOG_TIMER.setRepeats(false); SEARCH_ACTION_LOG_TIMER.start(); } - SwingTools.invokeLater(new Runnable() { + SwingTools.invokeLater(() -> { - @Override - @SuppressWarnings("rawtypes") - public void run() { + JButton focusButton = null; - JButton focusButton = null; + boolean resultEmpty; - boolean resultEmpty = false; + // clear panel + mainContentPanel.removeAll(); - // clear panel - mainContentPanel.removeAll(); + // add factory buttons panel + { - // add factory buttons panel - { + JPanel factoryButtonPanel = new JPanel(new GridBagLayout()); + JScrollPane scrollPane = new JScrollPane(factoryButtonPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setMaximumSize(SCROLL_PANE_SIZE); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); - JPanel factoryButtonPanel = new JPanel(new GridBagLayout()); - JScrollPane scrollPane = new JScrollPane(factoryButtonPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setMaximumSize(SCROLL_PANE_SIZE); - scrollPane.setBorder(BorderFactory.createEmptyBorder()); + GridBagConstraints constraint = new GridBagConstraints(); + constraint.gridx = 0; + constraint.gridy = 0; + constraint.insets = new Insets(5, 0, 5, 15); + constraint.fill = GridBagConstraints.NONE; - GridBagConstraints constraint = new GridBagConstraints(); - constraint.gridx = 0; - constraint.gridy = 0; - constraint.insets = new Insets(5, 0, 5, 15); - constraint.fill = GridBagConstraints.NONE; + // retrieve factories + List factoryMatches = getFilteredFactories(searchTerm); - // retrieve factories - List factoryMatches = getFilteredFactories(searchTerm); + // reverse list so first registered factories are displayed at the beginning + Collections.reverse(factoryMatches); - // reverse list so first registered factories are displayed at the beginning - Collections.reverse(factoryMatches); + resultEmpty = factoryMatches.isEmpty(); - resultEmpty = factoryMatches.isEmpty(); + // set preferred size for scroll pane in case of more than 10 factories. + // Otherwise the scrollbar won't show up. + if (factoryMatches.size() > 10) { + scrollPane.setPreferredSize(SCROLL_PANE_SIZE); + } - // set preferred size for scroll pane in case of more than 10 factories. - // Otherwise the scrollbar won't show up. - if (factoryMatches.size() > 10) { - scrollPane.setPreferredSize(SCROLL_PANE_SIZE); - } + dataSourceSelectionButtons.clear(); + // show a type selection button for each data source factory + for (DataSourceFactory factory : factoryMatches) { + JButton typeSelectionButton = createDataSourceSelectionButton(factory); + dataSourceSelectionButtons.add(typeSelectionButton); - dataSourceSelectionButtons.clear(); - // show a type selection button for each data source factory - for (DataSourceFactory factory : factoryMatches) { - JButton typeSelectionButton = createDataSourceSelectionButton(factory); - dataSourceSelectionButtons.add(typeSelectionButton); - - if (focusButton == null) { - focusButton = typeSelectionButton; - } - factoryButtonPanel.add(typeSelectionButton, constraint); - - // update constraints for next button - constraint.gridx += 1; - constraint.insets = new Insets(5, 0, 5, 0); - if (constraint.gridx > 1) { - constraint.gridx = 0; - constraint.gridy += 1; - constraint.insets = new Insets(5, 0, 5, 15); - } + if (focusButton == null) { + focusButton = typeSelectionButton; } + factoryButtonPanel.add(typeSelectionButton, constraint); - // fix for uneven number of data sources - if (factoryMatches.size() % 2 == 1) { + // update constraints for next button + constraint.gridx += 1; + constraint.insets = new Insets(5, 0, 5, 0); + if (constraint.gridx > 1) { constraint.gridx = 0; constraint.gridy += 1; constraint.insets = new Insets(5, 0, 5, 15); } + } - constraint = new GridBagConstraints(); - constraint.fill = GridBagConstraints.NONE; - constraint.gridwidth = GridBagConstraints.REMAINDER; - constraint.weightx = 1; - constraint.weighty = 0; - - mainContentPanel.add(scrollPane, constraint); + // fix for uneven number of data sources + if (factoryMatches.size() % 2 == 1) { + constraint.gridx = 0; + constraint.gridy += 1; + constraint.insets = new Insets(5, 0, 5, 15); } - // add link button below factory buttons - { - JPanel linkButtonPanel = new JPanel(); + constraint = new GridBagConstraints(); + constraint.fill = GridBagConstraints.NONE; + constraint.gridwidth = GridBagConstraints.REMAINDER; + constraint.weightx = 1; + constraint.weighty = 0; - // Add "empty result" text in case the search was empty - if (resultEmpty) { - JPanel noResultsPanel = new JPanel(new BorderLayout()); + mainContentPanel.add(scrollPane, constraint); + } - JLabel noResultsSymbol = new ResourceLabel("io.dataimport.step.type_selection.empty_search_symbol"); - noResultsSymbol.setHorizontalAlignment(SwingConstants.CENTER); - noResultsSymbol.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - noResultsPanel.add(noResultsSymbol, BorderLayout.NORTH); + // add link button below factory buttons + { + JPanel linkButtonPanel = new JPanel(); - JLabel noResultsLabel = new ResourceLabel("io.dataimport.step.type_selection.empty_search", - searchTerm); - noResultsPanel.add(noResultsLabel, BorderLayout.CENTER); + // Add "empty result" text in case the search was empty + if (resultEmpty) { + JPanel noResultsPanel = new JPanel(new BorderLayout()); - JPanel searchInMpPanel = new JPanel(); - LinkRemoteButton searchInMarketplace = new LinkRemoteButton(tryMarketplaceSearchAction); - searchInMarketplace.setAlignmentX(SwingConstants.CENTER); - searchInMpPanel.add(searchInMarketplace); - noResultsPanel.add(searchInMpPanel, BorderLayout.SOUTH); + JLabel noResultsSymbol = new ResourceLabel("io.dataimport.step.type_selection.empty_search_symbol"); + noResultsSymbol.setHorizontalAlignment(SwingConstants.CENTER); + noResultsSymbol.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + noResultsPanel.add(noResultsSymbol, BorderLayout.NORTH); - linkButtonPanel.add(noResultsPanel); - } else { - // add "search marketplace" link button - LinkRemoteButton searchInMarketplace = new LinkRemoteButton(searchInMarketplaceAction); - searchInMarketplace.setAlignmentX(SwingConstants.CENTER); - linkButtonPanel.add(searchInMarketplace); + JLabel noResultsLabel = new ResourceLabel("io.dataimport.step.type_selection.empty_search", + searchTerm); + noResultsPanel.add(noResultsLabel, BorderLayout.CENTER); - } + JPanel searchInMpPanel = new JPanel(); + LinkRemoteButton searchInMarketplace = new LinkRemoteButton(tryMarketplaceSearchAction); + searchInMarketplace.setAlignmentX(SwingConstants.CENTER); + searchInMpPanel.add(searchInMarketplace); + noResultsPanel.add(searchInMpPanel, BorderLayout.SOUTH); - GridBagConstraints constraint = new GridBagConstraints(); - constraint.insets = new Insets(10, 0, 0, 0); - constraint.gridwidth = GridBagConstraints.REMAINDER; - constraint.fill = GridBagConstraints.BOTH; - constraint.weighty = 1; - mainContentPanel.add(linkButtonPanel, constraint); - } + linkButtonPanel.add(noResultsPanel); + } else { + // add "search marketplace" link button + LinkRemoteButton searchInMarketplace = new LinkRemoteButton(searchInMarketplaceAction); + searchInMarketplace.setAlignmentX(SwingConstants.CENTER); + linkButtonPanel.add(searchInMarketplace); - mainContentPanel.revalidate(); - mainContentPanel.repaint(); + } - if (requestFocusForButton && focusButton != null) { - final JButton requestFocusButton = focusButton; - SwingUtilities.invokeLater(new Runnable() { + GridBagConstraints constraint = new GridBagConstraints(); + constraint.insets = new Insets(10, 0, 0, 0); + constraint.gridwidth = GridBagConstraints.REMAINDER; + constraint.fill = GridBagConstraints.BOTH; + constraint.weighty = 1; + mainContentPanel.add(linkButtonPanel, constraint); + } - @Override - public void run() { - requestFocusButton.requestFocusInWindow(); - } + mainContentPanel.revalidate(); + mainContentPanel.repaint(); - }); - } + if (requestFocusForButton && focusButton != null) { + SwingUtilities.invokeLater(focusButton::requestFocusInWindow); } - }); } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataStep.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataStep.java index 8cc96aa07..eab07acf7 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataStep.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataStep.java @@ -18,6 +18,7 @@ */ package com.rapidminer.studio.io.gui.internal.steps.configuration; +import java.text.DateFormat; import java.util.logging.Level; import javax.swing.JComponent; @@ -30,6 +31,7 @@ import com.rapidminer.operator.nio.model.AbstractDataResultSetReader; import com.rapidminer.studio.io.gui.internal.steps.AbstractWizardStep; import com.rapidminer.tools.LogService; +import com.rapidminer.tools.usagestats.ActionStatisticsCollector; /** @@ -100,14 +102,22 @@ public void viewWillBecomeInvisible(WizardDirection direction) throws InvalidCon // update data source meta data with configured view meta data final DataSource dataSource = wizard.getDataSource(DataSource.class); + DateFormat originalFormat; + DateFormat chosenFormat; try { + originalFormat = dataSource.getMetadata().getDateFormat(); dataSource.getMetadata().configure(view.getMetaData()); + chosenFormat = dataSource.getMetadata().getDateFormat(); } catch (DataSetException e) { SwingTools.showSimpleErrorMessage(wizard.getDialog(), "io.dataimport.step.data_column_configuration.error_configuring_metadata", e.getMessage()); throw new InvalidConfigurationException(); } + // Log guessed and chosen format + if (direction.equals(WizardDirection.NEXT) && !originalFormat.equals(chosenFormat)) { + ActionStatisticsCollector.getInstance().logGuessedDateFormat(view.getGuessedDateFormat(), chosenFormat); + } // we are in the last step of configuring an operator if (direction.equals(WizardDirection.NEXT) && reader != null) { diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableHeader.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableHeader.java index 9af4c9ea1..2b26bbda8 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableHeader.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableHeader.java @@ -28,14 +28,12 @@ import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; -import java.util.Set; - +import java.util.Objects; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; @@ -50,6 +48,7 @@ import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; +import com.rapidminer.core.io.data.ColumnMetaData; import com.rapidminer.core.io.data.ColumnMetaData.ColumnType; import com.rapidminer.core.io.data.DataSetException; import com.rapidminer.core.io.data.DataSetMetaData; @@ -63,12 +62,9 @@ import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.components.DropDownPopupButton; import com.rapidminer.gui.tools.components.DropDownPopupButton.DropDownPopupButtonBuilder; -import com.rapidminer.gui.tools.dialogs.InputValidator; import com.rapidminer.studio.io.gui.internal.DataImportWizardUtils; import com.rapidminer.studio.io.gui.internal.DataWizardEventType; import com.rapidminer.tools.I18N; -import com.rapidminer.tools.Observable; -import com.rapidminer.tools.Observer; /** @@ -89,27 +85,25 @@ final class ConfigureDataTableHeader extends JPanel implements TableCellRenderer private static final Color COLOR_COLUMN_DISABLED = new Color(154, 154, 154); - private static final String ERROR_DUPLICATE_ROLE_NAME = I18N - .getGUILabel("io.dataimport.step.data_column_configuration.duplicate_role_name"); - private static final String ERROR_DUPLICATE_COLUMN_NAME = I18N - .getGUILabel("io.dataimport.step.data_column_configuration.duplicate_column_name"); - private static final String ERROR_EMPTY_COLUMN_NAME = I18N - .getGUILabel("io.dataimport.step.data_column_configuration.empty_column_name"); + private static final String BASE_I18N_KEY = "io.dataimport.step.data_column_configuration"; + private static final String ERROR_DUPLICATE_ROLE_NAME = I18N.getGUILabel(BASE_I18N_KEY + ".duplicate_role_name"); + private static final String ERROR_DUPLICATE_COLUMN_NAME = I18N.getGUILabel(BASE_I18N_KEY + ".duplicate_column_name"); + private static final String ERROR_EMPTY_COLUMN_NAME = I18N.getGUILabel(BASE_I18N_KEY + ".empty_column_name"); - private static final String CHANGE_TYPE_LABEL = I18N - .getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.type.label"); - private static final String CHANGE_TYPE_TIP = I18N - .getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.type.tip"); + private static final String GUI_ACTION_PREFIX = "gui.action."; + private static final String CHANGE_TYPE_LABEL = I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".type.label"); + private static final String CHANGE_TYPE_TIP = I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".type.tip"); - private final Action changeRoleAction = new ResourceAction("io.dataimport.step.data_column_configuration.change_role") { + private final Action changeRoleAction = new ResourceAction(BASE_I18N_KEY + ".change_role") { private static final long serialVersionUID = 1L; @Override public void loggedActionPerformed(ActionEvent e) { - String columnName = metaData.getColumnMetaData(columnIndex).getName(); - String type = DataImportWizardUtils.getNameForColumnType(metaData.getColumnMetaData(columnIndex).getType()); - final String currentRoleName = metaData.getColumnMetaData(columnIndex).getRole(); + ColumnMetaData columnMetaData = metaData.getColumnMetaData(columnIndex); + String columnName = columnMetaData.getName(); + String type = DataImportWizardUtils.getNameForColumnType(columnMetaData.getType()); + final String currentRoleName = columnMetaData.getRole(); List roleList = new ArrayList<>(); if (currentRoleName != null) { @@ -122,103 +116,79 @@ public void loggedActionPerformed(ActionEvent e) { roleList.add(attribute); } - Object newRoleName = SwingTools.showInputDialog(ApplicationFrame.getApplicationFrame(), - "io.dataimport.step.data_column_configuration.change_role", true, roleList, currentRoleName, - new InputValidator() { - - @Override - public String validateInput(String input) { - if (input == null) { + String newRoleName = SwingTools.showInputDialog(ApplicationFrame.getApplicationFrame(), + BASE_I18N_KEY + ".change_role", true, roleList, currentRoleName, + input -> { + if (input == null) { + return null; + } + String valueString = input.trim(); + if (!valueString.equals(currentRoleName) && validator.isRoleUsed(valueString)) { + return ERROR_DUPLICATE_ROLE_NAME; + } return null; - } - String valueString = input.trim(); - if (!valueString.equals(currentRoleName) && validator.isRoleUsed(valueString)) { - return ERROR_DUPLICATE_ROLE_NAME; - } - return null; - } - }); + }); if (newRoleName == null) { // user cancelled dialog return; } - String newRoleNameString = String.valueOf(newRoleName).trim(); - if (newRoleNameString.isEmpty()) { - newRoleNameString = null; + newRoleName = newRoleName.trim(); + if (newRoleName.isEmpty()) { + newRoleName = null; } - - if (newRoleNameString == null && currentRoleName == null - || newRoleNameString != null && newRoleNameString.equals(currentRoleName)) { + if (Objects.equals(newRoleName, currentRoleName)) { // user has not changed the role return; } - - metaData.getColumnMetaData(columnIndex).setRole(newRoleNameString); - validator.validate(columnIndex); - ConfigureDataTableHeader.this.setToolTipText(createTooltip(columnName, type, newRoleNameString)); - ConfigureDataTableHeader.this.roleLabel.setText(newRoleNameString != null ? newRoleNameString : " "); - ConfigureDataTableHeader.this.table.getTableHeader().revalidate(); - ConfigureDataTableHeader.this.table.getTableHeader().repaint(); - ConfigureDataTableHeader.this.table.revalidate(); - ConfigureDataTableHeader.this.table.repaint(); + columnMetaData.setRole(newRoleName); + updateMetadataUI(columnName, type, newRoleName); } }; - private final Action renameAction = new ResourceAction("io.dataimport.step.data_column_configuration.rename") { + private final Action renameAction = new ResourceAction(BASE_I18N_KEY + ".rename") { private static final long serialVersionUID = 1L; @Override public void loggedActionPerformed(ActionEvent e) { - final String currentColumnName = metaData.getColumnMetaData(columnIndex).getName(); - String type = DataImportWizardUtils.getNameForColumnType(metaData.getColumnMetaData(columnIndex).getType()); - String roleName = metaData.getColumnMetaData(columnIndex).getRole(); + ColumnMetaData columnMetaData = metaData.getColumnMetaData(columnIndex); + final String currentColumnName = columnMetaData.getName(); + String type = DataImportWizardUtils.getNameForColumnType(columnMetaData.getType()); + String roleName = columnMetaData.getRole(); String newColumnName = SwingTools.showInputDialog(ApplicationFrame.getApplicationFrame(), - "io.dataimport.step.data_column_configuration.rename", currentColumnName, new InputValidator() { - - @Override - public String validateInput(String inputString) { - if (inputString == null || inputString.trim().isEmpty()) { - return ERROR_EMPTY_COLUMN_NAME; - } else if (!inputString.trim().equals(currentColumnName) && validator.isNameUsed(inputString.trim())) { - return ERROR_DUPLICATE_COLUMN_NAME; - } else { + BASE_I18N_KEY + ".rename", currentColumnName, inputString -> { + if (inputString == null || inputString.trim().isEmpty()) { + return ERROR_EMPTY_COLUMN_NAME; + } + if (!inputString.trim().equals(currentColumnName) && validator.isNameUsed(inputString.trim())) { + return ERROR_DUPLICATE_COLUMN_NAME; + } return null; - } - } - }); + }); if (newColumnName == null || newColumnName.trim().equals(currentColumnName)) { // user cancelled dialog or did not change the name return; } - newColumnName = newColumnName.trim(); - metaData.getColumnMetaData(columnIndex).setName(newColumnName); - validator.validate(columnIndex); - ConfigureDataTableHeader.this.setToolTipText(createTooltip(newColumnName, type, roleName)); - ConfigureDataTableHeader.this.nameLabel.setText(newColumnName); - ConfigureDataTableHeader.this.table.getTableHeader().revalidate(); - ConfigureDataTableHeader.this.table.getTableHeader().repaint(); + + columnMetaData.setName(newColumnName); + updateMetadataUI(newColumnName, type, roleName); } }; - private final Action disableEnableAction = new ResourceAction("io.dataimport.step.data_column_configuration.disable") { + private final Action disableEnableAction = new ResourceAction(BASE_I18N_KEY + ".disable") { private static final long serialVersionUID = 1L; @Override public void loggedActionPerformed(ActionEvent e) { - metaData.getColumnMetaData(columnIndex).setRemoved(!metaData.getColumnMetaData(columnIndex).isRemoved()); - if (metaData.getColumnMetaData(columnIndex).isRemoved()) { - nameLabel.setForeground(COLOR_COLUMN_DISABLED); - typeLabel.setForeground(COLOR_COLUMN_DISABLED); - roleLabel.setForeground(COLOR_COLUMN_DISABLED); - } else { - nameLabel.setForeground(Color.BLACK); - typeLabel.setForeground(Color.BLACK); - roleLabel.setForeground(Color.BLACK); - } + boolean wasRemoved = metaData.getColumnMetaData(columnIndex).isRemoved(); + metaData.getColumnMetaData(columnIndex).setRemoved(!wasRemoved); + Color foreGroundColor = wasRemoved ? Color.BLACK : COLOR_COLUMN_DISABLED; + nameLabel.setForeground(foreGroundColor); + typeLabel.setForeground(foreGroundColor); + roleLabel.setForeground(foreGroundColor); validator.validate(columnIndex); updateDisableEnableAction(); ConfigureDataTableHeader.this.table.revalidate(); @@ -237,6 +207,7 @@ public void loggedActionPerformed(ActionEvent e) { private final JLabel roleLabel; private final JLabel typeLabel; private final ConfigureDataView configureDataView; + private final JMenu typeMenu; public ConfigureDataTableHeader(final JTable table, final int columnIndex, final DataSetMetaData metaData, final ConfigureDataValidator validator, final ConfigureDataView configureDataView) { @@ -245,13 +216,9 @@ public ConfigureDataTableHeader(final JTable table, final int columnIndex, final this.validator = validator; this.metaData = metaData; this.configureDataView = configureDataView; - validator.addObserver(new Observer>() { - - @Override - public void update(Observable> observable, Set arg) { - if (arg != null && arg.contains(columnIndex)) { - adjustErrorColors(); - } + validator.addObserver((observable, arg) -> { + if (arg != null && arg.contains(columnIndex)) { + adjustErrorColors(); } }, false); setLayout(new GridBagLayout()); @@ -268,113 +235,101 @@ public void update(Observable> observable, Set arg) { GridBagConstraints gbc = new GridBagConstraints(); // add name label - { - nameLabel = new JLabel(columnName); - nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD, DEFAULT_FONT_SIZE)); + nameLabel = new JLabel(columnName); + nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD, DEFAULT_FONT_SIZE)); - gbc.gridwidth = GridBagConstraints.RELATIVE; - gbc.insets = new Insets(0, 5, 0, 0); - gbc.weightx = 1.0; - gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = GridBagConstraints.RELATIVE; + gbc.insets = new Insets(0, 5, 0, 0); + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; - add(nameLabel, gbc); - } + add(nameLabel, gbc); // add drop down button - { - updateDisableEnableAction(); + updateDisableEnableAction(); + + typeMenu = new JMenu(CHANGE_TYPE_LABEL); + updateTypeMenu(DataImportWizardUtils.getNameForColumnType(metaData.getColumnMetaData(columnIndex).getType())); + typeMenu.setToolTipText(CHANGE_TYPE_TIP); + + configureColumnButton = new DropDownPopupButtonBuilder() + .with(new ResourceActionAdapter(true, BASE_I18N_KEY + ".header_action")) + .add(typeMenu).add(changeRoleAction).add(renameAction).add(disableEnableAction).build(); + configureColumnButton.setIcon(null); + configureColumnButton.setBorder(null); + configureColumnButton.setOpaque(false); + configureColumnButton.setContentAreaFilled(false); + configureColumnButton.setBorderPainted(false); + configureColumnButton.addPopupMenuListener(new PopupMenuListener() { - configureColumnButton = new DropDownPopupButtonBuilder() - .with(new ResourceActionAdapter(true, "io.dataimport.step.data_column_configuration.header_action")) - .add(createTypeMenu()).add(changeRoleAction).add(renameAction).add(disableEnableAction).build(); - configureColumnButton.setIcon(null); - configureColumnButton.setBorder(null); - configureColumnButton.setOpaque(false); - configureColumnButton.setContentAreaFilled(false); - configureColumnButton.setBorderPainted(false); - configureColumnButton.addPopupMenuListener(new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - configureColumnButton.setColor(POPUP_SHOWN_COLOR); - table.getTableHeader().repaint(); - } + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + configureColumnButton.setColor(POPUP_SHOWN_COLOR); + table.getTableHeader().repaint(); + } - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - configureColumnButton.setColor(null); - table.getTableHeader().repaint(); - } + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + configureColumnButton.setColor(null); + table.getTableHeader().repaint(); + } - @Override - public void popupMenuCanceled(PopupMenuEvent e) {} - }); + @Override + public void popupMenuCanceled(PopupMenuEvent e) {} + }); - configureColumnButton.setArrowSize(DEFAULT_FONT_SIZE); - configureColumnButton.setTextSize(DEFAULT_FONT_SIZE); - configureColumnButton.setText(Ionicon.GEAR_B.getHtml()); + configureColumnButton.setArrowSize(DEFAULT_FONT_SIZE); + configureColumnButton.setTextSize(DEFAULT_FONT_SIZE); + configureColumnButton.setText(Ionicon.GEAR_B.getHtml()); - gbc.gridwidth = GridBagConstraints.REMAINDER; - gbc.insets = new Insets(0, 0, 0, 0); - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.insets = new Insets(0, 0, 0, 0); + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; - add(configureColumnButton, gbc); - } + add(configureColumnButton, gbc); // add type label - { - typeLabel = new JLabel(type); - typeLabel.setFont(typeLabel.getFont().deriveFont(Font.ITALIC)); + typeLabel = new JLabel(type); + typeLabel.setFont(typeLabel.getFont().deriveFont(Font.ITALIC)); - gbc.weightx = 1.0; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.insets = new Insets(0, 5, 0, 0); + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = new Insets(0, 5, 0, 0); - add(typeLabel, gbc); - - } + add(typeLabel, gbc); // add role label - { - roleLabel = new JLabel(roleName != null ? roleName : " "); - roleLabel.setFont(roleLabel.getFont().deriveFont(Font.ITALIC)); + roleLabel = new JLabel(roleName != null ? roleName : " "); + roleLabel.setFont(roleLabel.getFont().deriveFont(Font.ITALIC)); - add(roleLabel, gbc); - } + add(roleLabel, gbc); adjustErrorColors(); setupMouseListener(); } - /** - * @return menu that allows to select possible column types + * (Re-)creates the type menu with the selected type + * @param selected the selected column Type */ - private JMenu createTypeMenu() { + private void updateTypeMenu(String selected) { + typeMenu.removeAll(); ButtonGroup typeGroup = new ButtonGroup(); - JMenu typeChangeItem = new JMenu(CHANGE_TYPE_LABEL); - typeChangeItem.setToolTipText(CHANGE_TYPE_TIP); - for (final ColumnType columnType : ColumnType.values()) { - final JCheckBoxMenuItem checkboxItem = new JCheckBoxMenuItem( - DataImportWizardUtils.getNameForColumnType(columnType)); - if (columnType == metaData.getColumnMetaData(columnIndex).getType()) { + for (ColumnType columnType : ColumnType.values()) { + String columnTypeName = DataImportWizardUtils.getNameForColumnType(columnType); + JCheckBoxMenuItem checkboxItem = new JCheckBoxMenuItem(columnTypeName); + if (columnTypeName.equals(selected)) { checkboxItem.setSelected(true); } - checkboxItem.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - changeType(columnType); - } - + checkboxItem.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + changeType(columnType); } }); typeGroup.add(checkboxItem); - typeChangeItem.add(checkboxItem); + typeMenu.add(checkboxItem); } - return typeChangeItem; } /** @@ -449,15 +404,15 @@ private void adjustErrorColors() { private void updateDisableEnableAction() { if (metaData.getColumnMetaData(columnIndex).isRemoved()) { disableEnableAction.putValue(Action.NAME, - I18N.getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.enable.label")); + I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".enable.label")); disableEnableAction.putValue(Action.SHORT_DESCRIPTION, - I18N.getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.enable.tip")); + I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".enable.tip")); } else { disableEnableAction.putValue(Action.NAME, - I18N.getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.disable.label")); + I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".disable.label")); disableEnableAction.putValue(Action.SHORT_DESCRIPTION, - I18N.getGUIMessage("gui.action.io.dataimport.step.data_column_configuration.disable.tip")); + I18N.getGUIMessage(GUI_ACTION_PREFIX + BASE_I18N_KEY + ".disable.tip")); } } @@ -476,17 +431,17 @@ private static String createTooltip(String columnName, String type, String roleN // build header tooltip StringBuilder tipBuilder = new StringBuilder(); tipBuilder.append(""); if (roleName != null) { tipBuilder.append(""); @@ -506,37 +461,22 @@ private void changeType(final ColumnType newType) { metaData.getColumnMetaData(columnIndex).getType() + "->" + newType); metaData.getColumnMetaData(columnIndex).setType(newType); final ConfigureDataTableModel tableModel = (ConfigureDataTableModel) ConfigureDataTableHeader.this.table.getModel(); - ProgressThread columnThread = new ProgressThread("io.dataimport.step.data_column_configuration.update_column") { + ProgressThread columnThread = new ProgressThread(BASE_I18N_KEY + ".update_column") { @Override public void run() { try { tableModel.rereadColumn(columnIndex, getProgressListener()); } catch (final DataSetException e) { - SwingTools.invokeLater(new Runnable() { - - @Override - public void run() { + SwingTools.invokeLater(() -> configureDataView.showErrorNotification( - "io.dataimport.step.data_column_configuration.error_loading_data", e.getMessage()); - } - }); + BASE_I18N_KEY + ".error_loading_data", e.getMessage())); return; } - SwingTools.invokeLater(new Runnable() { - - @Override - public void run() { - validator.setParsingErrors(tableModel.getParsingErrors()); - - ConfigureDataTableHeader.this - .setToolTipText(createTooltip(metaData.getColumnMetaData(columnIndex).getName(), - DataImportWizardUtils.getNameForColumnType(newType), - metaData.getColumnMetaData(columnIndex).getRole())); - ConfigureDataTableHeader.this.typeLabel.setText(DataImportWizardUtils.getNameForColumnType(newType)); - ConfigureDataTableHeader.this.table.repaint(); - ConfigureDataTableHeader.this.table.getTableHeader().repaint(); - } + SwingTools.invokeLater(() -> { + validator.setParsingErrors(tableModel.getParsingErrors()); + ColumnMetaData columnMetaData = metaData.getColumnMetaData(columnIndex); + updateMetadataUI(columnMetaData.getName(), DataImportWizardUtils.getNameForColumnType(newType), columnMetaData.getRole()); }); } @@ -544,4 +484,39 @@ public void run() { columnThread.start(); } + + /** + * Updates this header after the underlying {@link ColumnMetaData} changed. + * + * @since 9.1 + */ + void updateMetadataUI() { + ColumnMetaData columnMetaData = metaData.getColumnMetaData(columnIndex); + updateMetadataUI(columnMetaData.getName(), + DataImportWizardUtils.getNameForColumnType(columnMetaData.getType()), + columnMetaData.getRole()); + } + + /** + * Updates this header with the given column name, type name and role name. + * + * @since 9.1 + */ + private void updateMetadataUI(String columnName, String type, String roleName) { + validator.validate(columnIndex); + SwingTools.invokeAndWait(() -> { + setToolTipText(createTooltip(columnName, type, roleName)); + nameLabel.setText(columnName); + roleLabel.setText(roleName != null ? roleName : " "); + if (!Objects.equals(typeLabel.getText(), type)) { + updateTypeMenu(type); + } + typeLabel.setText(type); + table.getTableHeader().revalidate(); + table.getTableHeader().repaint(); + table.revalidate(); + table.repaint(); + }); + } + } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableModel.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableModel.java index 77c5b1782..bed9f7081 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableModel.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataTableModel.java @@ -21,12 +21,10 @@ import java.text.DateFormat; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; - import javax.swing.table.AbstractTableModel; import com.rapidminer.core.io.data.ColumnMetaData; @@ -113,6 +111,15 @@ void reread(ProgressListener listener) throws DataSetException { } } + /** + * Get the preview data set, e.g. for date format guessing + * + * @since 9.1 + */ + DataSet getDataSet() { + return dataSet; + } + private synchronized void read(DataSet dataPreview, ProgressListener listener) throws DataSetException { if (listener != null) { listener.setTotal(previewSize); @@ -135,13 +142,14 @@ private synchronized void read(DataSet dataPreview, ProgressListener listener) t int numberOfColumns = dataPreview.getNumberOfColumns(); // read in data until preview size is reached - while (dataPreview.hasNext()) { + // somehow the preview gets a maxEndRow of -1 and then this can take loooong + while (dataPreview.hasNext() && dataList.size() < ImportWizardUtils.getPreviewLength()) { DataSetRow dataRow = dataPreview.nextRow(); String[] row = new String[numberOfColumns]; for (int i = 0; i < row.length; i++) { if (dataRow.isMissing(i)) { row[i] = Attribute.MISSING_NOMINAL_VALUE; - } else { + } else if (metaData.getColumnMetaData().size() > i) { final ColumnType columnType = metaData.getColumnMetaData(i).getType(); readNotMissingEntry(dataRow, row, i, dataPreview.getCurrentRowIndex(), columnType, errorCells); } @@ -293,12 +301,7 @@ synchronized void rereadColumn(int columnIndex, ProgressListener listener) throw * the index for which to delete the entries */ private void removeFromErrors(int columnIndex) { - Iterator iterator = parsingErrorList.iterator(); - while (iterator.hasNext()) { - if (iterator.next().getColumn() == columnIndex) { - iterator.remove(); - } - } + parsingErrorList.removeIf(parsingError -> parsingError.getColumn() == columnIndex); } /** @@ -351,10 +354,7 @@ public Object getValueAt(int rowIndex, int columnIndex) { */ boolean hasError(int rowIndex, int columnIndex) { Set errorRows = errorCells.get(columnIndex); - if (errorRows != null && errorRows.contains(rowIndex) && !metaData.getColumnMetaData(columnIndex).isRemoved()) { - return true; - } - return false; + return errorRows != null && errorRows.contains(rowIndex) && !metaData.getColumnMetaData(columnIndex).isRemoved(); } } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataValidator.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataValidator.java index e11f10991..db13a7619 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataValidator.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataValidator.java @@ -125,7 +125,7 @@ private void addColumnToColumnsMaps(int columnIndex, ColumnMetaData column) { // add to name map List listForName = columnNames.get(column.getName()); if (listForName == null) { - List indexList = new ArrayList<>(); + List indexList = Collections.synchronizedList(new ArrayList<>()); indexList.add(columnIndex); columnNames.put(column.getName(), indexList); } else { @@ -136,7 +136,7 @@ private void addColumnToColumnsMaps(int columnIndex, ColumnMetaData column) { if (role != null) { List listForRole = columnRoles.get(role); if (listForRole == null) { - List indexList = new ArrayList<>(); + List indexList = Collections.synchronizedList(new ArrayList<>()); indexList.add(columnIndex); columnRoles.put(role, indexList); } else { diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataView.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataView.java index 719c626b5..7592a9d9a 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataView.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ConfigureDataView.java @@ -1,41 +1,51 @@ /** * Copyright (C) 2001-2018 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.studio.io.gui.internal.steps.configuration; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.Vector; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -57,21 +67,29 @@ import javax.swing.table.TableColumnModel; import com.rapidminer.core.io.data.ColumnMetaData; +import com.rapidminer.core.io.data.ColumnMetaData.ColumnType; import com.rapidminer.core.io.data.DataSetException; import com.rapidminer.core.io.data.DataSetMetaData; import com.rapidminer.core.io.data.source.DataSource; +import com.rapidminer.core.io.data.source.DataSourceFeature; import com.rapidminer.core.io.gui.InvalidConfigurationException; import com.rapidminer.gui.look.Colors; +import com.rapidminer.gui.renderer.MatchingEntry; +import com.rapidminer.gui.renderer.MatchingEntryRenderer; import com.rapidminer.gui.tools.AttributeGuiTools; import com.rapidminer.gui.tools.ColoredTableCellRenderer; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ExtendedJTable; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ProgressThreadStoppedException; +import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceLabel; import com.rapidminer.gui.tools.RowNumberTable; import com.rapidminer.gui.tools.SwingTools; +import com.rapidminer.gui.tools.components.LinkLocalButton; import com.rapidminer.operator.UserError; +import com.rapidminer.operator.nio.DateFormatGuesser; +import com.rapidminer.operator.nio.DateTimeTypeGuesser; import com.rapidminer.parameter.ParameterTypeDateFormat; import com.rapidminer.studio.io.gui.internal.DataImportWizardUtils; import com.rapidminer.studio.io.gui.internal.DataWizardEventType; @@ -90,9 +108,14 @@ final class ConfigureDataView extends JPanel { private static final long serialVersionUID = 1L; - private static final String PROGRESS_THREAD_ID = "io.dataimport.step.data_column_configuration.prepare_data_preview"; + private static final String PREVIEW_PROGRESS_ID = "io.dataimport.step.data_column_configuration.prepare_data_preview"; + private static final String GUESSING_DATE_PROGRESS_ID = "io.dataimport.step.data_column_configuration.guessing_date_format"; - /** Number of ui components to create at once on the edt */ + private static final String ERROR_LOADING_DATA_KEY = "io.dataimport.step.data_column_configuration.error_loading_data"; + + /** + * Number of ui components to create at once on the edt + */ private static final int CHUNK_SIZE = 50; public static final Color BACKGROUND_COLUMN_DISABLED = new Color(232, 232, 232); @@ -100,14 +123,16 @@ final class ConfigureDataView extends JPanel { private static final String ERROR_TOOLTIP_CONTENT = "

    " + I18N.getGUILabel("io.dataimport.step.data_column_configuration.replace_errors_checkbox.tip") + "

    "; - /** cell renderer that displays icons */ + /** + * cell renderer that displays icons + */ private static final DefaultTableCellRenderer ICON_CELL_RENDERER = new DefaultTableCellRenderer() { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { + int row, int column) { JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); label.setText(null); label.setIcon((ImageIcon) value); @@ -125,12 +150,16 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole private static final Border WARNING_BORDER = BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(Color.ORANGE, 2), BorderFactory.createEmptyBorder(0, 8, 0, 3)); - /** Cell renderer that marks error cells with a colored border */ + private static final double DATE_COLUMN_CONFIDENCE = 0.75; + + /** + * Cell renderer that marks error cells with a colored border + */ private final ColoredTableCellRenderer ERROR_MARKING_CELL_RENDERER = new ColoredTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { + int row, int column) { JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (tableModel.hasError(row, column)) { if (errorHandlingCheckBox.isSelected()) { @@ -148,21 +177,34 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole private DataSetMetaData dataSetMetaData; private ConfigureDataTableModel tableModel; + private ConfigureDataTableHeader[] tableHeaders; private JPanel centerPanel; private JPanel upperPanel; private final JCheckBox errorHandlingCheckBox; private final ConfigureDataValidator validator; private final ErrorWarningTableModel errorTableModel; private final CollapsibleErrorTable collapsibleErrorTable; - private final JComboBox dateFormatField; + private final LinkLocalButton ignoreWarning; + private final JLabel dateLabel; + private final JComboBox dateFormatField; private Window owner; private transient ProgressThread currentThread; private boolean fatalError; + private boolean requiresDateFormat = true; private volatile boolean initialized; + private final Vector matchingEntries; + private final MatchingEntry emptyFormatEntry; + private MatchingEntry lastCustomDateFormat; + private MatchingEntry lastSelectedDateFormat; + private DateFormatGuesser dfg; + + private final JLabel matchLabel = new JLabel(); + private String guessedDateFormat; + /** * The constructor that creates a new {@link ConfigureDataView} instance. */ @@ -172,6 +214,15 @@ public ConfigureDataView(JDialog owner) { errorTableModel = new ErrorWarningTableModel(validator); errorTableModel.addTableModelListener(e -> fireStateChanged()); collapsibleErrorTable = new CollapsibleErrorTable(errorTableModel); + ignoreWarning = new LinkLocalButton(new ResourceAction("io.dataimport.step.data_column_configuration.ignore_errors") { + + @Override + public void loggedActionPerformed(final ActionEvent e) { + if(!errorHandlingCheckBox.isSelected()) { + errorHandlingCheckBox.doClick(); + } + }}); + errorTableModel.addTableModelListener(e -> ignoreWarning.setVisible(errorTableModel.getErrorCount() > 0)); setLayout(new BorderLayout()); upperPanel = new JPanel(new GridBagLayout()); @@ -190,34 +241,74 @@ public ConfigureDataView(JDialog owner) { errorHandlingPanel.add(errorHandlingCheckBox, BorderLayout.CENTER); SwingTools.addTooltipHelpIconToLabel(ERROR_TOOLTIP_CONTENT, errorHandlingPanel, owner); - dateFormatField = new JComboBox<>(ParameterTypeDateFormat.PREDEFINED_DATE_FORMATS); - + matchingEntries = MatchingEntry.createVector(ParameterTypeDateFormat.PREDEFINED_DATE_FORMATS); + emptyFormatEntry = matchingEntries.stream().filter(me -> me.getEntryName().isEmpty()).findFirst().orElse(MatchingEntry.create("", Double.NaN)); + dateFormatField = new JComboBox<>(matchingEntries); + dateFormatField.setRenderer(new MatchingEntryRenderer()); dateFormatField.setEditable(true); // do not fire action event when using keyboard to move up and down dateFormatField.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); - dateFormatField.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - // prevent two updates on enter key - if (!"comboBoxChanged".equals(e.getActionCommand())) { - return; + dateFormatField.addActionListener(e -> { + // prevent two updates on enter key + if (!"comboBoxChanged".equals(e.getActionCommand())) { + return; + } + Object selectedItem = dateFormatField.getSelectedItem(); + if (selectedItem == null) { + selectedItem = emptyFormatEntry; + } + String datePattern = selectedItem.toString(); + if (selectedItem instanceof String) { + // find match in existing if possible + selectedItem = getMatchingDateFormat(datePattern); + } + if (selectedItem instanceof MatchingEntry) { + selectMatchingDateFormat((MatchingEntry) selectedItem); + } else { + // recalculate if date format correct + try { + SimpleDateFormat checkedDateFormat = ParameterTypeDateFormat.createCheckedDateFormat(datePattern.trim(), null); + String finalDatePattern = datePattern; + ProgressThread guessingThread = new ProgressThread(GUESSING_DATE_PROGRESS_ID) { + + @Override + public void run() { + guessDateFormatForPreview(finalDatePattern); + MatchingEntry me = getMatchingDateFormat(finalDatePattern); + if (me == null) { + me = MatchingEntry.create(finalDatePattern, 0); + } + selectMatchingDateFormat(me); + } + }; + guessingThread.addDependency(PREVIEW_PROGRESS_ID, GUESSING_DATE_PROGRESS_ID); + guessingThread.start(); + currentThread = guessingThread; + } catch (UserError userError) { + // do nothing and go back to previous selected + selectMatchingDateFormat(MatchingEntry.create(datePattern, 0)); + datePattern = lastSelectedDateFormat.getEntryName(); } - String datePattern = (String) dateFormatField.getSelectedItem(); - if (datePattern != null && !datePattern.isEmpty()) { - try { - updateDateFormat(ParameterTypeDateFormat.createCheckedDateFormat(datePattern, null)); - } catch (UserError userError) { - // reset - dateFormatField.setSelectedItem(""); + } + + try { + SimpleDateFormat checkedDateFormat = ParameterTypeDateFormat.createCheckedDateFormat(datePattern.trim(), null); + if (checkedDateFormat.equals(dataSetMetaData.getDateFormat())) { + if (dfg != null) { + SwingTools.invokeLater(() -> setPredictedDateColumnTypes(dfg, checkedDateFormat.toPattern())); } + return; } + updateDateFormat(checkedDateFormat); + } catch (UserError userError) { + // do nothing and go back to previous selected + // reset + selectMatchingDateFormat(lastSelectedDateFormat); } - }); - JLabel datelabel = new ResourceLabel("date_format"); - datelabel.setLabelFor(dateFormatField); + dateLabel = new ResourceLabel("date_format"); + dateLabel.setLabelFor(dateFormatField); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = GridBagConstraints.RELATIVE; @@ -226,23 +317,35 @@ public void actionPerformed(ActionEvent e) { gbc.weightx = 0.0; gbc.anchor = GridBagConstraints.WEST; - upperPanel.add(datelabel, gbc); + upperPanel.add(dateLabel, gbc); - gbc.insets = new Insets(0, 0, 0, 70); + gbc.insets = new Insets(0, 0, 0, 15); upperPanel.add(dateFormatField, gbc); + gbc.insets = new Insets(0, 0, 0, 70); + matchLabel.setSize(70, 20); + matchLabel.setPreferredSize(new Dimension(70, 20)); + matchLabel.setToolTipText("The preview was tested for different date formats and this is the confidence for the selected date format."); + upperPanel.add(matchLabel, gbc); + gbc.insets = new Insets(0, 0, 0, 0); upperPanel.add(errorHandlingPanel, gbc); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1.0; - upperPanel.add(new JLabel(), gbc); + + upperPanel.add(new JPanel(), gbc); add(upperPanel, BorderLayout.NORTH); centerPanel = new JPanel(new GridBagLayout()); add(centerPanel, BorderLayout.CENTER); - add(collapsibleErrorTable, BorderLayout.SOUTH); + JPanel southPanel = new JPanel(new BorderLayout()); + southPanel.add(collapsibleErrorTable, BorderLayout.NORTH); + southPanel.add(ignoreWarning, BorderLayout.EAST); + add(southPanel, BorderLayout.SOUTH); collapsibleErrorTable.setVisible(false); + ignoreWarning.setVisible(false); + owner.addWindowListener(new WindowAdapter() { @Override @@ -252,20 +355,39 @@ public void windowClosed(WindowEvent e) { }); } + /** + * Returns the initially guessed date format + * + * @return the guessed date format, or the standard date format if nothing was guessed + */ + String getGuessedDateFormat(){ + return guessedDateFormat; + } + /** * Takes the current data source, copies the meta data and configures the view according to the * data and meta data within a progress thread. * * @param dataSource - * the data source to retrieve the meta data and preview data from + * the data source to retrieve the meta data and preview data from * @throws InvalidConfigurationException - * in case the meta data could not be retrieved + * in case the meta data could not be retrieved */ void updatePreviewContent(final DataSource dataSource) throws InvalidConfigurationException { fatalError = false; + requiresDateFormat = !dataSource.supportsFeature(DataSourceFeature.DATETIME_METADATA); + dateFormatField.setVisible(requiresDateFormat); + matchLabel.setVisible(requiresDateFormat); + dateLabel.setText(requiresDateFormat ? dateLabel.getText() : ""); // copy meta data to work on copy instead of real instance try { + // clean up if metaData has changed + if (dataSetMetaData == null || !Objects.equals(dataSource.getMetadata().getDateFormat(), dataSetMetaData.getDateFormat()) || + !Objects.equals(extractColumnNames(dataSource.getMetadata()), extractColumnNames(dataSetMetaData))) { + guessedDateFormat = null; + lastSelectedDateFormat = null; + } dataSetMetaData = dataSource.getMetadata().copy(); } catch (DataSetException e) { SwingTools.showSimpleErrorMessage(owner, @@ -273,20 +395,11 @@ void updatePreviewContent(final DataSource dataSource) throws InvalidConfigurati throw new InvalidConfigurationException(); } - errorHandlingCheckBox.setSelected(dataSetMetaData.isFaultTolerant()); - DateFormat dateFormat = dataSetMetaData.getDateFormat(); - if (dateFormat instanceof SimpleDateFormat) { - // remove action listeners before setting the date format pattern to prevent - // unnecessary update - ActionListener[] listeners = dateFormatField.getActionListeners(); - dateFormatField.removeActionListener(listeners[0]); - dateFormatField.setSelectedItem(((SimpleDateFormat) dateFormat).toPattern()); - dateFormatField.addActionListener(listeners[0]); - } + SwingTools.invokeAndWait(() -> errorHandlingCheckBox.setSelected(dataSetMetaData.isFaultTolerant())); errorTableModel.setColumnMetaData(dataSetMetaData.getColumnMetaData()); validator.init(dataSetMetaData.getColumnMetaData()); - ProgressThread loadDataPG = new ProgressThread(PROGRESS_THREAD_ID) { + ProgressThread loadDataPG = new ProgressThread(PREVIEW_PROGRESS_ID) { @Override public void run() { @@ -302,6 +415,13 @@ public void run() { setDisplayLabel("io.dataimport.step.data_column_configuration.prepare_preview_table"); getProgressListener().setCompleted(0); + // init with the best matching dateformat, or the last selected date format if it exists + if (lastSelectedDateFormat != null && !Objects.equals(lastSelectedDateFormat.getEntryName(), guessedDateFormat)) { + guessDateFormatForPreview(lastSelectedDateFormat.getEntryName()); + } else { + guessDateFormatForPreview(null); + } + // adapt view after table has been loaded final ExtendedJTable previewTable = SwingTools.invokeAndWaitWithResult(this::createPreviewTable); if (previewTable == null) { @@ -313,9 +433,15 @@ public void run() { // Add scroll pane, error table etc. SwingTools.invokeLater(() -> finalizePreviewTable(previewTable)); + DateFormat dateFormat = dataSetMetaData.getDateFormat(); + if (dateFormat instanceof SimpleDateFormat) { + if (lastSelectedDateFormat == null || !Objects.equals(lastSelectedDateFormat.getEntryName(), ((SimpleDateFormat) dateFormat).toPattern())) { + updateDateFormat((SimpleDateFormat) dateFormat); + } + selectMatchingDateFormat(getMatchingDateFormat(((SimpleDateFormat) dateFormat).toPattern())); + } } catch (final DataSetException e) { - SwingTools.invokeLater(() -> showErrorNotification("io.dataimport.step.data_column_configuration.error_loading_data", - e.getMessage())); + SwingTools.invokeLater(() -> showErrorNotification(ERROR_LOADING_DATA_KEY, e.getMessage())); } catch (ProgressThreadStoppedException pts) { // this is logged internally by the progress thread } finally { @@ -347,17 +473,18 @@ private ExtendedJTable createPreviewTable() { @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { Component c = super.prepareRenderer(renderer, row, column); - ColumnMetaData metaData = dataSetMetaData.getColumnMetaData().get(column); + List columnMetaDataList = dataSetMetaData.getColumnMetaData(); + // This was exploding on a switch between a file with less columns then the one before + if (column >= columnMetaDataList.size()) { + return c; + } + ColumnMetaData metaData = columnMetaDataList.get(column); if (metaData.isRemoved()) { c.setBackground(BACKGROUND_COLUMN_DISABLED); c.setForeground(FOREGROUND_COLUMN_DISABLED); } else { String role = metaData.getRole(); - if (role != null) { - c.setBackground(AttributeGuiTools.getColorForAttributeRole(role)); - } else { - c.setBackground(Color.WHITE); - } + c.setBackground(role != null ? AttributeGuiTools.getColorForAttributeRole(role) : Color.WHITE); c.setForeground(Color.BLACK); } return c; @@ -390,6 +517,7 @@ private void createTableHeaders(ExtendedJTable previewTable) { final int columnCount = columnModel.getColumnCount(); // Initialize total size getProgressListener().setTotal((columnCount + CHUNK_SIZE - 1) / CHUNK_SIZE); + tableHeaders = new ConfigureDataTableHeader[columnCount]; for (int columnIndex = 0; columnIndex < columnCount; columnIndex += CHUNK_SIZE) { final int baseIndex = columnIndex; getProgressListener().setCompleted(baseIndex / CHUNK_SIZE); @@ -399,6 +527,7 @@ private void createTableHeaders(ExtendedJTable previewTable) { TableColumn column = columnModel.getColumn(index); ConfigureDataTableHeader headerRenderer = new ConfigureDataTableHeader(previewTable, index, dataSetMetaData, validator, ConfigureDataView.this); + tableHeaders[index] = headerRenderer; column.setHeaderRenderer(headerRenderer); column.setMinWidth(120); } @@ -488,11 +617,130 @@ private void setupErrorTable() { collapsibleErrorTable.setVisible(true); } }; - loadDataPG.addDependency(PROGRESS_THREAD_ID); + loadDataPG.addDependency(PREVIEW_PROGRESS_ID); loadDataPG.start(); currentThread = loadDataPG; } + private void guessDateFormatForPreview(String preferredPattern) { + if (!requiresDateFormat) { + return; + } + + // Keep the currentCustomFormat, lastCustomFormat and the dataSetMetaData format + + List customPatterns = new ArrayList<>(); + Optional.ofNullable(dateFormatField.getSelectedItem()).map(Object::toString).ifPresent(customPatterns::add); + Optional.ofNullable(lastCustomDateFormat).map(MatchingEntry::getEntryName).ifPresent(customPatterns::add); + Stream.of(dataSetMetaData.getDateFormat()).filter(SimpleDateFormat.class::isInstance).map(SimpleDateFormat.class::cast).map(SimpleDateFormat::toPattern).forEach(customPatterns::add); + + DateFormatGuesser dateFormatGuesser = null; + try { + dateFormatGuesser = DateFormatGuesser.guessDateFormat(tableModel.getDataSet(), customPatterns, preferredPattern); + } catch (DataSetException e) { + SwingTools.invokeLater(() -> showErrorNotification(ERROR_LOADING_DATA_KEY, e.getMessage())); + } + if (dateFormatGuesser == null) { + dfg = null; + return; + } + SimpleDateFormat bestDateFormat = dateFormatGuesser.getBestMatch(DATE_COLUMN_CONFIDENCE); + String bestPattern = bestDateFormat != null ? bestDateFormat.toPattern() : null; + MatchingEntry bestMatchingEntry = null; + Map results = dateFormatGuesser.getResults(DATE_COLUMN_CONFIDENCE); + /// update existing entries with new match values + for (MatchingEntry matchingEntry : matchingEntries) { + String entryName = matchingEntry.getEntryName(); + double match = results.getOrDefault(entryName, 0d); + matchingEntry.setMatch(match); + if (entryName.equals(bestPattern)) { + bestMatchingEntry = matchingEntry; + } + } + + // add new entry + if (bestPattern != null && bestMatchingEntry == null) { + bestMatchingEntry = MatchingEntry.create(bestPattern, results.getOrDefault(bestPattern, 0d)); + DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel) dateFormatField.getModel(); + if (lastCustomDateFormat != null) { + comboBoxModel.removeElement(lastCustomDateFormat); + } + comboBoxModel.addElement(bestMatchingEntry); + lastCustomDateFormat = bestMatchingEntry; + } + matchingEntries.sort(MatchingEntry::compareTo); + if (bestDateFormat != null) { + dataSetMetaData.setDateFormat(bestDateFormat); + } + if (guessedDateFormat == null) { + guessedDateFormat = bestPattern != null ? bestPattern : ""; + } + dfg = dateFormatGuesser; + } + + private void setPredictedDateColumnTypes(DateFormatGuesser dateFormatGuesser, String formatPattern) { + if (dateFormatGuesser == null || !requiresDateFormat) { + return; + } + List dateAttributes = dateFormatGuesser.getDateAttributes(formatPattern, DATE_COLUMN_CONFIDENCE); + Set changedAttributes = new HashSet<>(); + // reset current date attributes + int index = 0; + for (ColumnMetaData cmd : dataSetMetaData.getColumnMetaData()) { + switch (cmd.getType()) { + case DATE: + case TIME: + case DATETIME: + cmd.setType(ColumnType.CATEGORICAL); + changedAttributes.add(index); + break; + default: + } + index++; + } + ColumnType dateType = DateTimeTypeGuesser.patternToColumnType(formatPattern); + // set new date attributes + dateAttributes.forEach(dateAttribute -> dataSetMetaData.getColumnMetaData(dateAttribute).setType(dateType)); + changedAttributes.addAll(dateAttributes); + changedAttributes.forEach(i -> { + if (tableHeaders == null || tableHeaders[i] == null) { + return; + } + tableHeaders[i].updateMetadataUI(); + }); + } + + private MatchingEntry getMatchingDateFormat(String pattern) { + for (MatchingEntry me : matchingEntries) { + if (me.getEntryName().equals(pattern)) { + return me; + } + } + if (lastCustomDateFormat != null && lastCustomDateFormat.getEntryName().equals(pattern)) { + return lastCustomDateFormat; + } + return null; + } + + private void selectMatchingDateFormat(MatchingEntry matchingEntry) { + if (matchingEntry == null) { + SwingTools.invokeAndWait(() -> { + dateFormatField.setSelectedIndex(-1); + matchLabel.setText(""); + }); + return; + } + SwingTools.invokeAndWait(() -> { + lastSelectedDateFormat = matchingEntry; + Object selectedItem = dateFormatField.getSelectedItem(); + if (selectedItem != matchingEntry) { + dateFormatField.setSelectedItem(matchingEntry); + } + String matchtext = matchingEntry.getEntryName().isEmpty() ? "" : MatchingEntryRenderer.getMatchtext(matchingEntry.getMatch()); + matchLabel.setText(matchtext); + }); + } + void showErrorNotification(String i18nKey, Object... arguments) { showNotificationLabel(i18nKey, arguments); fatalError = true; @@ -504,9 +752,9 @@ void showErrorNotification(String i18nKey, Object... arguments) { * loading). * * @param i18nKey - * the notification I18N key to lookup the label text and icon + * the notification I18N key to lookup the label text and icon * @param arguments - * the I18N arguments + * the I18N arguments */ private void showNotificationLabel(String i18nKey, Object... arguments) { upperPanel.setVisible(false); @@ -548,8 +796,7 @@ DataSetMetaData getMetaData() { * Checks whether the current view configuration is valid. * * @throws InvalidConfigurationException - * in case the configuration is invalid - * + * in case the configuration is invalid */ public void validateConfiguration() throws InvalidConfigurationException { if (fatalError || tableModel == null || tableModel.getRowCount() == 0 || errorTableModel.getErrorCount() > 0) { @@ -561,7 +808,7 @@ public void validateConfiguration() throws InvalidConfigurationException { * Registers a new change listener. * * @param changeListener - * the listener to register + * the listener to register */ void addChangeListener(ChangeListener changeListener) { this.changeListeners.add(changeListener); @@ -586,7 +833,7 @@ private void fireStateChanged() { * Updates date format for the date and reloads it. * * @param format - * the new date format + * the new date format */ private void updateDateFormat(SimpleDateFormat format) { DataImportWizardUtils.logStats(DataWizardEventType.DATE_FORMAT_CHANGED, format.toPattern()); @@ -595,11 +842,11 @@ private void updateDateFormat(SimpleDateFormat format) { @Override public void run() { + setPredictedDateColumnTypes(dfg, format.toPattern()); try { tableModel.reread(getProgressListener()); } catch (final DataSetException e) { - SwingTools.invokeLater(() -> showErrorNotification("io.dataimport.step.data_column_configuration.error_loading_data", - e.getMessage())); + SwingTools.invokeLater(() -> showErrorNotification(ERROR_LOADING_DATA_KEY, e.getMessage())); return; } SwingTools.invokeLater(() -> { @@ -610,6 +857,7 @@ public void run() { } }; + rereadThread.addDependency(GUESSING_DATE_PROGRESS_ID); rereadThread.start(); currentThread = rereadThread; } @@ -631,4 +879,15 @@ void cancelLoading() { public boolean isInitialized() { return initialized; } + + /** + * Extracts the column names from the DataSetMetaData + * + * @param metaData + * the meta data + * @return the column names + */ + private static List extractColumnNames(DataSetMetaData metaData) { + return metaData.getColumnMetaData().stream().map(ColumnMetaData::getName).collect(Collectors.toList()); + } } diff --git a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ErrorWarningTableModel.java b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ErrorWarningTableModel.java index fab3b1d36..a88c26e0d 100644 --- a/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ErrorWarningTableModel.java +++ b/src/main/java/com/rapidminer/studio/io/gui/internal/steps/configuration/ErrorWarningTableModel.java @@ -151,7 +151,7 @@ public Object getValueAt(int rowIndex, int columnIndex) { * @param errors * the parsing errors to set */ - private void setParsingErrors(Collection errors) { + private synchronized void setParsingErrors(Collection errors) { this.parsingErrors.clear(); this.parsingErrors.addAll(errors); this.parsingErrors.sort((o1, o2) -> { diff --git a/src/main/java/com/rapidminer/test/asserter/AsserterFactoryRapidMiner.java b/src/main/java/com/rapidminer/test/asserter/AsserterFactoryRapidMiner.java index 870901b8c..ef74a77c6 100644 --- a/src/main/java/com/rapidminer/test/asserter/AsserterFactoryRapidMiner.java +++ b/src/main/java/com/rapidminer/test/asserter/AsserterFactoryRapidMiner.java @@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -34,6 +35,9 @@ import com.rapidminer.operator.IOObject; import com.rapidminer.operator.IOObjectCollection; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.clustering.Centroid; +import com.rapidminer.operator.clustering.CentroidClusterModel; +import com.rapidminer.operator.clustering.Cluster; import com.rapidminer.operator.learner.associations.FrequentItemSet; import com.rapidminer.operator.learner.associations.FrequentItemSets; import com.rapidminer.operator.learner.functions.LinearRegressionModel; @@ -681,6 +685,75 @@ public void assertEquals(String message, Object expectedObj, Object actualObj) { }); + // Asserter for Centroid Cluster Model + asserters.add(new Asserter() { + + @Override + public Class getAssertable() { + return CentroidClusterModel.class; + } + + /** + * Tests two Centroid Cluster Model + * + * @param message + * message to display if an error occurs + * @param expectedObj + * expected value + * @param actualObj + * actual value + */ + @Override + public void assertEquals(String message, Object expectedObj, Object actualObj) { + CentroidClusterModel expected = (CentroidClusterModel) expectedObj; + CentroidClusterModel actual = (CentroidClusterModel) actualObj; + + message = message + " - Centroid Cluster Model \"" + actual.getSource() + + "\" does not match the expected result"; + + + // compare training header (basic information) + Assert.assertEquals(message + " : training headers are not equal", expected.getTrainingHeader().toString(), actual.getTrainingHeader().toString()); + + // compare distance measure type + Assert.assertEquals(message + " : distance measure types are not equal", expected.getDistanceMeasure().getClass(), actual.getDistanceMeasure().getClass()); + + // compare attribute names + Assert.assertArrayEquals(message + " : attribute names are not equal", expected.getAttributeNames(), actual.getAttributeNames()); + + // compare number of clusters + Assert.assertEquals(message + " : number of clusters are not equal", expected.getNumberOfClusters(), actual.getNumberOfClusters()); + + // compare centroids + Assert.assertArrayEquals(message + " : centroids are not equal", expected.getCentroids().stream().map(Centroid::getCentroid).toArray(), actual.getCentroids().stream().map(Centroid::getCentroid).toArray()); + + // compare number of examples + Assert.assertArrayEquals(message + " : clusters number of examples are not equal", expected.getClusters().stream().mapToInt(Cluster::getNumberOfExamples).toArray(), actual.getClusters().stream().mapToInt(Cluster::getNumberOfExamples).toArray()); + + // compare cluster ids + Assert.assertArrayEquals(message + " : clusters ids are not equal", expected.getClusters().stream().mapToInt(Cluster::getClusterId).toArray(), actual.getClusters().stream().mapToInt(Cluster::getClusterId).toArray()); + + // compare cluster example ids + Assert.assertArrayEquals(message + " : clusters example ids are not equal", expected.getClusters().stream().map(Cluster::getExampleIds).flatMap(Collection::stream).toArray(Object[]::new), actual.getClusters().stream().map(Cluster::getExampleIds).flatMap(Collection::stream).toArray(Object[]::new)); + + // compare is adding label + Assert.assertEquals(message + " : is adding label is not equal", expected.isAddingLabel(), actual.isAddingLabel()); + + // compare is in target encoding + Assert.assertEquals(message + " : is in target encoding is not equal", expected.isInTargetEncoding(), actual.isInTargetEncoding()); + + // compare is removing + Assert.assertEquals(message + " : is removing unknown assignments is not equal", expected.isRemovingUnknownAssignments(), actual.isRemovingUnknownAssignments()); + + // compare is updatable + Assert.assertEquals(message + " : is updatable is not equal", expected.isUpdatable(), actual.isUpdatable()); + + // check string representation + Assert.assertEquals(message + " : string representations are not equal", expected.toString(), actual.toString()); + } + + }); + return asserters; } diff --git a/src/main/java/com/rapidminer/tools/AbstractObservable.java b/src/main/java/com/rapidminer/tools/AbstractObservable.java index 21c573cb4..2d714a2fb 100644 --- a/src/main/java/com/rapidminer/tools/AbstractObservable.java +++ b/src/main/java/com/rapidminer/tools/AbstractObservable.java @@ -105,13 +105,7 @@ protected void fireUpdate(final A argument) { synchronized (lock) { copyEDT = new LinkedList<>(observersEDT); } - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - fireUpdate(copyEDT, argument); - } - }); + SwingUtilities.invokeLater(() -> fireUpdate(copyEDT, argument)); } } diff --git a/src/main/java/com/rapidminer/tools/ClassNameMapper.java b/src/main/java/com/rapidminer/tools/ClassNameMapper.java index 345d7bf0d..f8d82c19c 100644 --- a/src/main/java/com/rapidminer/tools/ClassNameMapper.java +++ b/src/main/java/com/rapidminer/tools/ClassNameMapper.java @@ -18,11 +18,11 @@ */ package com.rapidminer.tools; -import com.rapidminer.operator.UserError; - -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; + +import com.rapidminer.operator.UserError; /** @@ -33,24 +33,16 @@ */ public class ClassNameMapper { - Map classMap = new LinkedHashMap(); + Map classMap = new LinkedHashMap<>(); public ClassNameMapper(String[] classNames) { - for (int i = 0; i < classNames.length; i++) { - String completeClassName = classNames[i]; - String simpleClassName = completeClassName; - + for (String completeClassName : classNames) { // if possible, strip package information - int index = completeClassName.lastIndexOf('.'); - if (index > -1) { - simpleClassName = completeClassName.substring(index + 1); - } + String simpleClassName = completeClassName.substring(completeClassName.lastIndexOf('.') + 1); // if no class with the same short name is found in the map, add it // else use the complete class name - if (classMap.get(simpleClassName) == null) { - classMap.put(simpleClassName, completeClassName); - } else { + if (classMap.putIfAbsent(simpleClassName, completeClassName) != null) { classMap.put(completeClassName, completeClassName); } } @@ -61,47 +53,25 @@ public String getCompleteClassName(String shortName) { } public Class getClassByShortName(String shortName) throws UserError { - String completeClassName = getCompleteClassName(shortName); - // if the name is not found in the map, try to use the one provided as parameter. - if (completeClassName == null) { - completeClassName = shortName; - } - - if (completeClassName == null) { - throw new UserError(null, 904, shortName, "No such class."); - } - + String completeClassName = classMap.getOrDefault(shortName, shortName); try { + Objects.requireNonNull(completeClassName, "No such class"); return Class.forName(completeClassName); - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException | NullPointerException e) { throw new UserError(null, 904, shortName, e.getMessage()); } } public String[] getShortClassNames() { - String[] result = new String[classMap.size()]; - Iterator it = classMap.keySet().iterator(); - - for (int i = 0; i < classMap.size(); i++) { - result[i] = it.next(); - } - - return result; + return classMap.keySet().toArray(new String[0]); } public Object getInstantiation(String shortName) throws UserError { - Object result = null; try { - result = getClassByShortName(shortName).newInstance(); - if (result == null) { - throw new UserError(null, 904, shortName, "No such class"); - } - } catch (InstantiationException e) { - throw new UserError(null, 904, shortName, e.getMessage()); - } catch (IllegalAccessException e) { + return getClassByShortName(shortName).newInstance(); + } catch (InstantiationException | IllegalAccessException | NullPointerException e) { throw new UserError(null, 904, shortName, e.getMessage()); } - return result; } } diff --git a/src/main/java/com/rapidminer/tools/ExtensibleResourceBundle.java b/src/main/java/com/rapidminer/tools/ExtensibleResourceBundle.java index e5df29297..ebe90cfc1 100644 --- a/src/main/java/com/rapidminer/tools/ExtensibleResourceBundle.java +++ b/src/main/java/com/rapidminer/tools/ExtensibleResourceBundle.java @@ -18,11 +18,29 @@ */ package com.rapidminer.tools; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.security.AccessControlException; +import java.security.AccessController; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.ResourceBundle; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Level; + +import com.rapidminer.RapidMiner; +import com.rapidminer.security.PluginSandboxPolicy; /** @@ -33,11 +51,20 @@ */ public class ExtensibleResourceBundle extends ResourceBundle { - private class KeyEnumeration implements Enumeration { + /** + * Allows to enumerate seamlessly over multiple resource bundles + * + * @author Sebastian Land + */ + private static class KeyEnumeration implements Enumeration { - private Iterator bundleIterator = bundles.iterator(); + private Iterator bundleIterator; private Enumeration keyIterator; + KeyEnumeration(Iterable iterable) { + bundleIterator = iterable.iterator(); + } + @Override public boolean hasMoreElements() { if (keyIterator == null || !keyIterator.hasMoreElements()) { @@ -63,10 +90,46 @@ public String nextElement() { } } + /** + * File that contains the keys that weren't available in the users language + */ + private static final Path TRANSLATION_HELPER_FILE = FileSystemService.getUserRapidMinerDir().toPath().resolve("translation_helper.txt"); + /** + * Log only if the translation helper file exists and the users language is not english + */ + private static final boolean LOG_MISSING_TRANSLATIONS = Files.exists(TRANSLATION_HELPER_FILE) && + !Locale.getDefault().getLanguage().isEmpty() && !Locale.getDefault().getLanguage().equals(Locale.ENGLISH.getLanguage()); + /** + * Set of keys with missing translations + */ + private static final Set MISSING_TRANSLATION_KEYS = Collections.newSetFromMap(new ConcurrentHashMap<>()); + /** + * Used to separate bundle from key + */ + private static final String SEPARATOR = "|"; + /** + * Sorts by "bundle is in selected language" descending + */ + private static final Comparator CURRENT_LANG_DESC = Comparator.comparing(ExtensibleResourceBundle::weightResourceBundle, Integer::compareTo); + + static { + if (LOG_MISSING_TRANSLATIONS) { + RapidMiner.addShutdownHook(() -> { + try { + Files.write(TRANSLATION_HELPER_FILE, MISSING_TRANSLATION_KEYS, StandardCharsets.UTF_8, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); + } catch (IOException e) { + // bad luck + } + }); + } + } + private List bundles = new CopyOnWriteArrayList<>(); + private final List coreBundles; public ExtensibleResourceBundle(ResourceBundle parent) { - bundles.add(parent); + coreBundles = flattenResourceBundle(parent); + bundles.addAll(coreBundles); } /** @@ -74,26 +137,49 @@ public ExtensibleResourceBundle(ResourceBundle parent) { * those properties are already contained, they will be ignored. */ public void addResourceBundle(ResourceBundle bundle) { - bundles.add(bundle); + bundles.addAll(flattenResourceBundle(bundle)); + bundles.sort(CURRENT_LANG_DESC); } /** * This method extends this resource bundle with the properties set by the given bundle. If * those properties were already contained, they are overwritten by the new bundle's settings. + *

    + * Internal API, do not use! + *

    */ public void addResourceBundleAndOverwrite(ResourceBundle bundle) { - bundles.add(0, bundle); + try { + if (System.getSecurityManager() != null) { + AccessController.checkPermission(new RuntimePermission(PluginSandboxPolicy.RAPIDMINER_INTERNAL_PERMISSION)); + } + } catch (AccessControlException ace) { + LogService.getRoot().log(Level.FINEST, "Internal API, cannot be called by unauthorized sources.", ace); + addResourceBundle(bundle); + return; + } + bundles.addAll(0, flattenResourceBundle(bundle)); + bundles.sort(CURRENT_LANG_DESC); } @Override public Enumeration getKeys() { - return new KeyEnumeration(); + return new KeyEnumeration(bundles); } @Override protected Object handleGetObject(String key) { + if (key.endsWith(I18N.ICON_SUFFIX)) { + for (ResourceBundle bundle : coreBundles) { + if (bundle.containsKey(key)) { + return bundle.getObject(key); + } + } + } + for (ResourceBundle bundle : bundles) { if (bundle.containsKey(key)) { + logIfMissing(bundle, key); return bundle.getObject(key); } } @@ -111,6 +197,108 @@ public boolean containsKey(String key) { return true; } } + return false; } + + /** + * Tries to flatten the resource bundle + * + *

    This is needed to support partial translations from multiple extensions.

    + * + * @param bundle + * the bundle hierarchy + * @return a list containing the bundle and it's parents + */ + private static List flattenResourceBundle(ResourceBundle bundle) { + if (bundle instanceof ExtensibleResourceBundle) { + return ((ExtensibleResourceBundle) bundle).bundles; + } + Field parentField; + List resourceBundles = new ArrayList<>(); + try { + parentField = ResourceBundle.class.getDeclaredField("parent"); + parentField.setAccessible(true); + ResourceBundle currentBundle = bundle; + while (currentBundle != null) { + ResourceBundle parentBundle = (ResourceBundle) parentField.get(currentBundle); + parentField.set(currentBundle, null); + resourceBundles.add(currentBundle); + currentBundle = parentBundle; + } + } catch (Exception e) { + LogService.getRoot().log(Level.SEVERE, "Flattening of ResourceBundle failed. I18N might be broken.", e); + return Collections.singletonList(bundle); + } + return resourceBundles; + } + + /** + * Logs the bundle name and key in case of a missing translation + * + * @param bundle the bundle + * @param key the key in the bundle + */ + private static void logIfMissing(ResourceBundle bundle, String key) { + if (LOG_MISSING_TRANSLATIONS && bundle.getLocale().getLanguage().isEmpty() && !key.endsWith(I18N.ICON_SUFFIX)) { + String[] bundlePath = bundle.getBaseBundleName().split("[/.]"); + MISSING_TRANSLATION_KEYS.add(bundlePath[bundlePath.length - 1] + SEPARATOR + key); + } + } + + /** + * Compares the given bundle locale against the default locale. + * + *

    Meaning of the rating

    + *
      + *
    1. Root Bundle
    2. + *
    3. Language equal
    4. + *
    5. Language and Country equal
    6. + *
    7. Language, Country and Variant equal
    8. + *
    + * Negative values are used to sort descending, while keeping the previous order. + * @param bundle the bundle to weight + * @return likeliness to the default locale [-3,0] + */ + private static int weightResourceBundle(ResourceBundle bundle) { + return weightLocale(bundle.getLocale()); + } + + /** + * Compares the given locale against the default locale. + * + *

    Meaning of the rating

    + *
      + *
    1. Root Bundle
    2. + *
    3. Language equal
    4. + *
    5. Language and Country equal
    6. + *
    7. Language, Country and Variant equal
    8. + *
    + * Negative values are used to sort descending, while keeping the previous order. + * @param locale the locale to weight + * @return likeliness to the default locale [-3,0] + */ + private static int weightLocale(Locale locale) { + //between ~50% (non en, no country) and 100% (en) of the loaded bundles are ROOT bundles + if (locale.getLanguage().isEmpty()) { + // root bundle + return 0; + } + // The locale bundle mechanism only loads files with the right language and root bundles + // For de-AT only de_AT, de and ROOT is loaded + + // Check country + if (!Locale.getDefault().getCountry().equalsIgnoreCase(locale.getCountry())) { + // language matched + return -1; + } + // Check variant + if (!Locale.getDefault().getVariant().equalsIgnoreCase(locale.getVariant())) { + // language and country + return -2; + } + // language country and variant matched + return -3; + } + } diff --git a/src/main/java/com/rapidminer/tools/FileSystemService.java b/src/main/java/com/rapidminer/tools/FileSystemService.java index 65c7b44a6..d1654a2a0 100644 --- a/src/main/java/com/rapidminer/tools/FileSystemService.java +++ b/src/main/java/com/rapidminer/tools/FileSystemService.java @@ -45,7 +45,7 @@ public class FileSystemService { /** folder which can be used for internal caching of the Global Search feature */ private static final String RAPIDMINER_INTERNAL_CACHE_SEARCH = "search"; - public static final String RAPIDMINER_INTERNAL_CACHE_SEARCH_FULL = "internal cache/search"; + public static final String RAPIDMINER_INTERNAL_CACHE_SEARCH_FULL = RAPIDMINER_INTERNAL_CACHE + "/" + RAPIDMINER_INTERNAL_CACHE_SEARCH; /** folder which can be used to load additional building blocks */ public static final String RAPIDMINER_BUILDINGBLOCKS = "buildingblocks"; @@ -76,23 +76,30 @@ public static File getUserConfigFile(String name) { } public static File getUserRapidMinerDir() { - File homeDir = new File(System.getProperty("user.home")); - File userHomeDir = new File(homeDir, RAPIDMINER_USER_FOLDER); - File extensionsWorkspaceRootFolder = new File(userHomeDir, RAPIDMINER_EXTENSIONS_FOLDER); + File rapidMinerDir; + String customHome = System.getProperty("rapidminer.user-home"); + if (customHome != null && !customHome.trim().isEmpty()) { + rapidMinerDir = new File(customHome); + } else { + File homeDir = new File(System.getProperty("user.home")); + rapidMinerDir = new File(homeDir, RAPIDMINER_USER_FOLDER); + } + + File extensionsWorkspaceRootFolder = new File(rapidMinerDir, RAPIDMINER_EXTENSIONS_FOLDER); File extensionsWorkspaceFolder = new File(extensionsWorkspaceRootFolder, RAPIDMINER_EXTENSIONS_WORKSPACE_FOLDER); - File sharedDataDir = new File(userHomeDir, RAPIDMINER_SHARED_DATA); - File buildingBlocksFolder = new File(userHomeDir, RAPIDMINER_BUILDINGBLOCKS); - File internalCacheFolder = new File(userHomeDir, RAPIDMINER_INTERNAL_CACHE); + File sharedDataDir = new File(rapidMinerDir, RAPIDMINER_SHARED_DATA); + File buildingBlocksFolder = new File(rapidMinerDir, RAPIDMINER_BUILDINGBLOCKS); + File internalCacheFolder = new File(rapidMinerDir, RAPIDMINER_INTERNAL_CACHE); File internalCacheSearchFolder = new File(internalCacheFolder, RAPIDMINER_INTERNAL_CACHE_SEARCH); - checkAndCreateFolder(userHomeDir); + checkAndCreateFolder(rapidMinerDir); checkAndCreateFolder(extensionsWorkspaceRootFolder); checkAndCreateFolder(internalCacheFolder); checkAndCreateFolder(internalCacheSearchFolder); checkAndCreateFolder(extensionsWorkspaceFolder); checkAndCreateFolder(sharedDataDir); checkAndCreateFolder(buildingBlocksFolder); - return userHomeDir; + return rapidMinerDir; } /** diff --git a/src/main/java/com/rapidminer/tools/FontTools.java b/src/main/java/com/rapidminer/tools/FontTools.java index 3c725dbf8..cd5e98812 100644 --- a/src/main/java/com/rapidminer/tools/FontTools.java +++ b/src/main/java/com/rapidminer/tools/FontTools.java @@ -23,7 +23,7 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Set; - +import java.util.logging.Level; import javax.swing.UIManager; import javax.swing.plaf.FontUIResource; import javax.swing.text.StyleContext; @@ -163,7 +163,13 @@ public static void checkAndSetFallbackUIFont() { * @return array of available font options */ public static String[] getAvailableFonts() { - String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + String[] fonts; + try { + fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + } catch (Exception e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.FontTools.system_font_loading.failed", e); + fonts = new String[0]; + } String[] selectableFonts = new String[fonts.length + 2]; selectableFonts[OPTION_INDEX_STANDARD_FONTS] = OPTION_STANDARD_FONTS; selectableFonts[OPTION_INDEX_SYSTEM_FONTS] = OPTION_SYSTEM_FONTS; diff --git a/src/main/java/com/rapidminer/tools/GlobalAuthenticator.java b/src/main/java/com/rapidminer/tools/GlobalAuthenticator.java index 34430ec32..d09b1dc75 100644 --- a/src/main/java/com/rapidminer/tools/GlobalAuthenticator.java +++ b/src/main/java/com/rapidminer/tools/GlobalAuthenticator.java @@ -46,8 +46,8 @@ */ public class GlobalAuthenticator extends Authenticator { - private final List serverAuthenticators = new LinkedList(); - private final List proxyAuthenticators = new LinkedList(); + private final List serverAuthenticators = new LinkedList<>(); + private final List proxyAuthenticators = new LinkedList<>(); private URLAuthenticator socksProxyAuthenticator = null; private static GlobalAuthenticator THE_INSTANCE = new GlobalAuthenticator(); @@ -61,7 +61,7 @@ public class GlobalAuthenticator extends Authenticator { /** * This method is deprecated use registerServerAuthenticator instead. */ - public synchronized static void register(URLAuthenticator authenticator) { + public static synchronized void register(URLAuthenticator authenticator) { registerServerAuthenticator(authenticator); } @@ -69,7 +69,7 @@ public synchronized static void register(URLAuthenticator authenticator) { * This method adds another Authenticator to the GlobalAuthenticator that will be enqueued in * the list of Authenticators that are tried for URLs that need authentification. */ - public synchronized static void registerServerAuthenticator(URLAuthenticator authenticator) { + public static synchronized void registerServerAuthenticator(URLAuthenticator authenticator) { THE_INSTANCE.serverAuthenticators.add(authenticator); } @@ -77,14 +77,14 @@ public synchronized static void registerServerAuthenticator(URLAuthenticator aut * This method adds another Authenticator to the GlobalAuthenticator that will be enqueued in * the list of Authenticators that are tried for Proxy requests for authentification. */ - public synchronized static void registerProxyAuthenticator(URLAuthenticator authenticator) { + public static synchronized void registerProxyAuthenticator(URLAuthenticator authenticator) { THE_INSTANCE.proxyAuthenticators.add(authenticator); } /** * This method adds the default ProxyAuthenticators to the GlobalAuthenticator. */ - public synchronized static void refreshProxyAuthenticators() { + public static synchronized void refreshProxyAuthenticators() { THE_INSTANCE.proxyAuthenticators.clear(); THE_INSTANCE.socksProxyAuthenticator = new SocksProxyAuthenticator(ProxyAuthenticator.SOCKS); registerProxyAuthenticator(new ProxyAuthenticator(ProxyAuthenticator.HTTP)); @@ -95,36 +95,36 @@ public synchronized static void refreshProxyAuthenticators() { @Override protected synchronized PasswordAuthentication getPasswordAuthentication() { URL url = getRequestingURL(); - try { if (SocksProxyAuthenticator.SOCKS5.equals(this.getRequestingProtocol())) { - PasswordAuthentication auth = socksProxyAuthenticator.getAuthentication(url); - return auth; + return socksProxyAuthenticator.getAuthentication(url); + } + RequestorType requestorType = getRequestorType(); + if (requestorType == null) { + return PasswordDialog.getPasswordAuthentication(url.toString(), false, true); } - switch (getRequestorType()) { + List authenticators; + String logKey = "com.rapidminer.tools.GlobalAuthenticator.authentication_requested"; + switch (requestorType) { case PROXY: - LogService.getRoot().log(Level.FINE, - "com.rapidminer.tools.GlobalAuthenticator.authentication_requested_proxy", - new Object[] { url, proxyAuthenticators }); - for (URLAuthenticator a : proxyAuthenticators) { - PasswordAuthentication auth = a.getAuthentication(url); - if (auth != null) { - return auth; - } - } - // this should not be happen - return PasswordDialog.getPasswordAuthentication(url.toString(), false, false); + logKey += "_proxy"; + authenticators = proxyAuthenticators; + break; case SERVER: - LogService.getRoot().log(Level.FINE, "com.rapidminer.tools.GlobalAuthenticator.authentication_requested", - new Object[] { url, serverAuthenticators }); - for (URLAuthenticator a : serverAuthenticators) { - PasswordAuthentication auth = a.getAuthentication(url); - if (auth != null) { - return auth; - } - } + authenticators = serverAuthenticators; + break; + default: + return null; + } + LogService.getRoot().log(Level.FINE, logKey, new Object[]{url, authenticators}); + for (URLAuthenticator a : authenticators) { + PasswordAuthentication auth = a.getAuthentication(url); + if (auth != null) { + return auth; + } } - return PasswordDialog.getPasswordAuthentication(url.toString(), false, true); + // this should not happen + return PasswordDialog.getPasswordAuthentication(url.toString(), false, requestorType == RequestorType.SERVER); } catch (PasswordInputCanceledException e) { return null; } diff --git a/src/main/java/com/rapidminer/tools/I18N.java b/src/main/java/com/rapidminer/tools/I18N.java index 42ff0d361..c3a1d5420 100644 --- a/src/main/java/com/rapidminer/tools/I18N.java +++ b/src/main/java/com/rapidminer/tools/I18N.java @@ -21,12 +21,16 @@ import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; +import java.util.Objects; import java.util.ResourceBundle; import java.util.logging.Level; - import javax.swing.JComponent; +import org.apache.commons.lang.ArrayUtils; + import com.rapidminer.RapidMiner; +import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.ParameterTypeCategory; /** @@ -39,23 +43,23 @@ public class I18N { private static final ExtensibleResourceBundle GUI_BUNDLE; private static final ExtensibleResourceBundle SETTINGS_BUNDLE; - private static final Locale ORIGINAL_LOCALE; + private static final Locale ORIGINAL_LOCALE = Locale.getDefault(); public static final String SETTINGS_TYPE_TITLE_SUFFIX = ".title"; public static final String SETTINGS_TYPE_DESCRIPTION_SUFFIX = ".description"; + public static final String ICON_SUFFIX = ".icon"; // init I18N static { - ORIGINAL_LOCALE = Locale.getDefault(); ParameterService.init(); String localeLanguage = ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE); - Locale locale = Locale.getDefault(); - if (localeLanguage != null) { - locale = new Locale(localeLanguage); + Locale locale = Locale.forLanguageTag(Objects.toString(localeLanguage,"")); + if (!locale.getLanguage().isEmpty()) { Locale.setDefault(locale); LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.I18N.set_locale_to", locale); } else { + locale = Locale.getDefault(); LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.I18N.using_default_locale", locale); } JComponent.setDefaultLocale(locale); @@ -133,39 +137,54 @@ public static void registerSettingsBundle(ResourceBundle bundle) { registerSettingsBundle(bundle, false); } - /** registers the properties of the given bundle on the global error bundle */ + /** + * Registers the properties of the given bundle on the global error bundle + * @param bundle bundle to register + * @param overwrite always false, internal api + */ public static void registerErrorBundle(ResourceBundle bundle, boolean overwrite) { - if (!overwrite) { - ERROR_BUNDLE.addResourceBundle(bundle); - } else { - ERROR_BUNDLE.addResourceBundleAndOverwrite(bundle); - } + registerBundle(ERROR_BUNDLE, bundle, overwrite); } - /** registers the properties of the given bundle on the global gui bundle */ + /** + * Registers the properties of the given bundle on the global gui bundle + * @param bundle bundle to register + * @param overwrite always false, internal api + */ public static void registerGUIBundle(ResourceBundle bundle, boolean overwrite) { - if (!overwrite) { - GUI_BUNDLE.addResourceBundle(bundle); - } else { - GUI_BUNDLE.addResourceBundleAndOverwrite(bundle); - } + registerBundle(GUI_BUNDLE, bundle, overwrite); } - /** registers the properties of the given bundle on the global userError bundle */ + /** + * Registers the properties of the given bundle on the global userError bundle + * @param bundle bundle to register + * @param overwrite always false, internal api + */ public static void registerUserErrorMessagesBundle(ResourceBundle bundle, boolean overwrite) { - if (!overwrite) { - USER_ERROR_BUNDLE.addResourceBundle(bundle); - } else { - USER_ERROR_BUNDLE.addResourceBundleAndOverwrite(bundle); - } + registerBundle(USER_ERROR_BUNDLE, bundle, overwrite); } - /** registers the properties of the given bundle on the global settings bundle */ + /** + * Registers the properties of the given bundle on the global settings bundle + * @param bundle bundle to register + * @param overwrite always false, internal api + */ public static void registerSettingsBundle(ResourceBundle bundle, boolean overwrite) { - if (!overwrite) { - SETTINGS_BUNDLE.addResourceBundle(bundle); + registerBundle(SETTINGS_BUNDLE, bundle, overwrite); + } + + /** + * Registers the given bundle in the targetBundle + * + * @param targetBundle the target bundle + * @param bundle bundle to register + * @param overwrite always false, internal api + */ + private static void registerBundle(ExtensibleResourceBundle targetBundle, ResourceBundle bundle, boolean overwrite) { + if (overwrite) { + targetBundle.addResourceBundleAndOverwrite(bundle); } else { - SETTINGS_BUNDLE.addResourceBundleAndOverwrite(bundle); + targetBundle.addResourceBundle(bundle); } } @@ -175,21 +194,14 @@ public static void registerSettingsBundle(ResourceBundle bundle, boolean overwri * will be replaced by the first argument, '{1}' with the second and so on. * * Catches the exception thrown by ResourceBundle in the latter case. + * @param bundle the bundle that contains the key + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle **/ public static String getMessage(ResourceBundle bundle, String key, Object... arguments) { try { - - if (arguments == null || arguments.length == 0) { - return bundle.getString(key); - } else { - String message = bundle.getString(key); - if (message != null) { - return MessageFormat.format(message, arguments); - } else { - return key; - } - } - + return getMessageOptimistic(bundle, key, arguments); } catch (MissingResourceException e) { LogService.getRoot().log(Level.FINEST, "com.rapidminer.tools.I18N.missing_key", key); return key; @@ -199,6 +211,10 @@ public static String getMessage(ResourceBundle bundle, String key, Object... arg /** * Convenience method to call {@link #getMessage(ResourceBundle, String, Object...)} with return * value from {@link #getGUIBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle */ public static String getGUIMessage(String key, Object... arguments) { return getMessage(getGUIBundle(), key, arguments); @@ -207,6 +223,10 @@ public static String getGUIMessage(String key, Object... arguments) { /** * Convenience method to call {@link #getMessageOrNull(ResourceBundle, String, Object...)} with * return value from {@link #getGUIBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or null if the key does not exists in the bundle */ public static String getGUIMessageOrNull(String key, Object... arguments) { return getMessageOrNull(getGUIBundle(), key, arguments); @@ -215,6 +235,10 @@ public static String getGUIMessageOrNull(String key, Object... arguments) { /** * Convenience method to call {@link #getMessage(ResourceBundle, String, Object...)} with return * value from {@link #getErrorBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle */ public static String getErrorMessage(String key, Object... arguments) { return getMessage(getErrorBundle(), key, arguments); @@ -223,6 +247,10 @@ public static String getErrorMessage(String key, Object... arguments) { /** * Convenience method to call {@link #getMessageOrNull(ResourceBundle, String, Object...)} with * return value from {@link #getErrorBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or null if the key does not exists in the bundle */ public static String getErrorMessageOrNull(String key, Object... arguments) { return getMessageOrNull(getErrorBundle(), key, arguments); @@ -231,6 +259,10 @@ public static String getErrorMessageOrNull(String key, Object... arguments) { /** * Convenience method to call {@link #getMessage(ResourceBundle, String, Object...)} with return * value from {@link #getUserErrorMessagesBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle */ public static String getUserErrorMessage(String key, Object... arguments) { return getMessage(getUserErrorMessagesBundle(), key, arguments); @@ -239,6 +271,10 @@ public static String getUserErrorMessage(String key, Object... arguments) { /** * Convenience method to call {@link #getMessageOrNull(ResourceBundle, String, Object...)} with * return value from {@link #getUserErrorMessagesBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or null if the key does not exists in the bundle */ public static String getUserErrorMessageOrNull(String key, Object... arguments) { return getMessageOrNull(getUserErrorMessagesBundle(), key, arguments); @@ -247,6 +283,10 @@ public static String getUserErrorMessageOrNull(String key, Object... arguments) /** * Convenience method to call {@link #getMessage(ResourceBundle, String, Object...)} with return * value from {@link #getSettingsBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle */ public static String getSettingsMessage(String key, SettingsType type, Object... arguments) { return getMessage(getSettingsBundle(), key + type, arguments); @@ -255,6 +295,10 @@ public static String getSettingsMessage(String key, SettingsType type, Object... /** * Convenience method to call {@link #getMessageOrNull(ResourceBundle, String, Object...)} with * return value from {@link #getSettingsBundle()} as {@link ResourceBundle}. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or null if the key does not exists in the bundle */ public static String getSettingsMessageOrNull(String key, SettingsType type, Object... arguments) { return getMessageOrNull(getSettingsBundle(), key + type, arguments); @@ -266,29 +310,29 @@ public static String getSettingsMessageOrNull(String key, SettingsType type, Obj * Arguments can be specified which will be used to format the String. In the * {@link ResourceBundle} the String '{0}' (without ') will be replaced by the first argument, * '{1}' with the second and so on. - * + * @param bundle the bundle that contains the key + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or null if key not exists in the bundle */ public static String getMessageOrNull(ResourceBundle bundle, String key, Object... arguments) { - - if (bundle.containsKey(key)) { - return getMessage(bundle, key, arguments); - } else { + try { + return getMessageOptimistic(bundle, key, arguments); + } catch (MissingResourceException e) { return null; } - } /** * This will return the value of the property gui.label.-key- of the GUI bundle or the key * itself if unknown. + * + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key, or the key if it does not exists in the bundle */ public static String getGUILabel(String key, Object... arguments) { - String completeKey = "gui.label." + key; - if (GUI_BUNDLE.containsKey(completeKey)) { - return getMessage(GUI_BUNDLE, completeKey, arguments); - } else { - return completeKey; - } + return getMessage(GUI_BUNDLE, "gui.label." + key, arguments); } /** @@ -301,4 +345,77 @@ public static String getGUILabel(String key, Object... arguments) { public static Locale getOriginalLocale() { return ORIGINAL_LOCALE; } + + /** + * Returns a message if found or the key if not found. Arguments can be specified which + * will be used to format the String. In the {@link ResourceBundle} the String '{0}' (without ') + * will be replaced by the first argument, '{1}' with the second and so on. + * + * @param bundle the bundle that contains the key + * @param key key – the key for the desired string + * @param arguments optional arguments for message formatter + * @return the formatted string for the given key + * @throws java.util.MissingResourceException – if no object for the given key can be found + */ + private static String getMessageOptimistic(ResourceBundle bundle, String key, Object... arguments) throws MissingResourceException { + String message = bundle.getString(key); + if (arguments == null || arguments.length == 0) { + return message; + } + return MessageFormat.format(message, arguments); + } + + /** + *

    + * Registers a new language tag to be shown in the RapidMiner Settings + *

    + * + *

    + * Important: Use underscore for the .properties files, but hyphen for the language tag!
    + * Examples: + *

    "); - tipBuilder.append(I18N.getGUILabel("io.dataimport.step.data_column_configuration.tooltip_name")); + tipBuilder.append(I18N.getGUILabel(BASE_I18N_KEY + ".tooltip_name")); tipBuilder.append(""); tipBuilder.append(columnName); tipBuilder.append("
    "); - tipBuilder.append(I18N.getGUILabel("io.dataimport.step.data_column_configuration.tooltip_type")); + tipBuilder.append(I18N.getGUILabel(BASE_I18N_KEY + ".tooltip_type")); tipBuilder.append(""); tipBuilder.append(type); tipBuilder.append("
    "); - tipBuilder.append(I18N.getGUILabel("io.dataimport.step.data_column_configuration.tooltip_role")); + tipBuilder.append(I18N.getGUILabel(BASE_I18N_KEY + ".tooltip_role")); tipBuilder.append(""); tipBuilder.append(roleName); tipBuilder.append("
    + * + * + * + * + * + * + * + * + * + * + * + * + *
    Language TagFilename
    English Fallback MyExtGUI.properties
    "de" MyExtGUI_de.properties
    "de-AT" MyExtGUI_de_AT.properties
    + * If de-AT is the selected language, first de-AT files are checked, second de, finally {@link Locale#ROOT} + * + * @param languageTag + * An IETF BCP 47 language tag, i.e. "fr", "zh", "de" or "en-GB" + * @throws IllegalArgumentException + * if the given {@code languageTag} is not valid + * @throws NullPointerException + * if {@code languageTag} is {@code null} + * @since 9.1.0 + */ + public static void registerLanguage(String languageTag) { + // Check if language key is valid + if (Locale.forLanguageTag(languageTag).getLanguage().isEmpty()) { + LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.I18N.add_language_wrong_format", String.valueOf(languageTag)); + throw new IllegalArgumentException(languageTag + " is not a valid IETF BCP 47 language tag."); + } + + ParameterType type = ParameterService.getParameterType(RapidMiner.PROPERTY_RAPIDMINER_GENERAL_LOCALE_LANGUAGE); + if (!(type instanceof ParameterTypeCategory)) { + LogService.getRoot().log(Level.SEVERE, "com.rapidminer.tools.I18N.add_language_failed", languageTag); + return; + } + ParameterTypeCategory lng = ((ParameterTypeCategory) type); + if (ArrayUtils.contains(lng.getValues(), languageTag)) { + //already registered + return; + } + // Add language key to the end, not sorted + String[] languages = (String[]) ArrayUtils.add(lng.getValues(), languageTag); + ParameterService.registerParameter(new ParameterTypeCategory(lng.getKey(), lng.getDescription(), languages, lng.getDefault(), lng.isExpert())); + } } diff --git a/src/main/java/com/rapidminer/tools/LineParser.java b/src/main/java/com/rapidminer/tools/LineParser.java index 47b096ebc..f99be789e 100644 --- a/src/main/java/com/rapidminer/tools/LineParser.java +++ b/src/main/java/com/rapidminer/tools/LineParser.java @@ -224,9 +224,9 @@ public static String[] fastSplit(String line, char splitChar, boolean trimLine, // Character nextChar = null; /** error message to display */ String errorMessage = ""; - /** column index where the error occured */ + /** column index where the error occurred */ int errorColumnIndex = 0; - /** string with the last 10 characters read before the error occured */ + /** string with the last 10 characters read before the error occurred */ String errorLastFewReadChars = ""; /** current state of the SplitMachine */ SplitMachineState machineState = SplitMachineState.NEW_SPLIT; @@ -235,7 +235,7 @@ public static String[] fastSplit(String line, char splitChar, boolean trimLine, line = trimLine ? line.trim() : line; // go through the line for (int i = 0; i < line.length(); i++) { - // read current character and next character (if applicaple) + // read current character and next character (if applicable) char currentChar = line.charAt(i); char nextChar; if (i + 1 < line.length()) { diff --git a/src/main/java/com/rapidminer/tools/RMUrlHandler.java b/src/main/java/com/rapidminer/tools/RMUrlHandler.java index 8ff4b9c51..563ed5517 100644 --- a/src/main/java/com/rapidminer/tools/RMUrlHandler.java +++ b/src/main/java/com/rapidminer/tools/RMUrlHandler.java @@ -35,13 +35,14 @@ import com.rapidminer.RapidMiner; import com.rapidminer.RepositoryProcessLocation; import com.rapidminer.gui.MainFrame; +import com.rapidminer.gui.OperatorDocumentationBrowser; import com.rapidminer.gui.Perspective; import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.actions.OpenAction; import com.rapidminer.gui.dialog.BrowserUnavailableDialogFactory; import com.rapidminer.gui.security.PasswordManager; +import com.rapidminer.gui.tools.DockingTools; import com.rapidminer.gui.tools.dialogs.ButtonDialog; -import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorCreationException; import com.rapidminer.repository.Entry; import com.rapidminer.repository.IOObjectEntry; @@ -112,6 +113,7 @@ public class RMUrlHandler { private static final String SCHEMA_RAPIDMINER = "rapidminer"; private static final String RAPIDMINER_SCHEMA_EXTENSION = "extension"; private static final String RAPIDMINER_SCHEMA_REPOSITORY = "repository"; + private static final String RAPIDMINER_SCHEMA_OPERATOR_TUTORIAL_PROCESS = "operator_tutorial_process"; private static final String INTERNAL_SCHEMA_OPDOC = "opdoc/"; private static final String INTERNAL_SCHEMA_OPERATOR = "operator/"; private static final String SCHEMA_HTTP = "http://"; @@ -329,10 +331,9 @@ private static void handleRMUrl(String url) { if (suffix.startsWith(INTERNAL_SCHEMA_OPDOC)) { // operator doc display change String opName = suffix.substring(INTERNAL_SCHEMA_OPDOC.length()); - Operator op; try { - op = OperatorService.createOperator(opName); - RapidMinerGUI.getMainFrame().getOperatorDocViewer().setDisplayedOperator(op); + RapidMinerGUI.getMainFrame().getOperatorDocViewer().setDisplayedOperator(OperatorService.createOperator(opName)); + DockingTools.openDockable(OperatorDocumentationBrowser.OPERATOR_HELP_DOCK_KEY); } catch (OperatorCreationException e) { LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), "com.rapidminer.tools.RMUrlHandler.creating_operator_error", opName), e); @@ -429,6 +430,17 @@ private static void handleRapidMinerURL(String urlStr) { new Object[] { locString }); } break; + case RAPIDMINER_SCHEMA_OPERATOR_TUTORIAL_PROCESS: + try { + int lastColumnPos = components[1].lastIndexOf(':'); + String operatorKey = components[1].substring(0, lastColumnPos); + int tutorialPos = Integer.parseInt(components[1].substring(lastColumnPos + 1)); + OperatorDocumentationBrowser.openTutorialProcess(operatorKey, tutorialPos); + } catch (Exception e) { + LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unknown_rapidminer_url", + new Object[]{urlStr}); + } + break; default: LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unknown_rapidminer_url", new Object[] { urlStr }); diff --git a/src/main/java/com/rapidminer/tools/StrictDecimalFormat.java b/src/main/java/com/rapidminer/tools/StrictDecimalFormat.java index aaaed2e0a..d67a539e4 100644 --- a/src/main/java/com/rapidminer/tools/StrictDecimalFormat.java +++ b/src/main/java/com/rapidminer/tools/StrictDecimalFormat.java @@ -1,190 +1,199 @@ -/** - * Copyright (C) 2001-2018 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.tools; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.ParseException; -import java.text.ParsePosition; -import java.util.LinkedList; -import java.util.List; - -import com.rapidminer.parameter.ParameterHandler; -import com.rapidminer.parameter.ParameterType; -import com.rapidminer.parameter.ParameterTypeBoolean; -import com.rapidminer.parameter.ParameterTypeChar; -import com.rapidminer.parameter.ParameterTypeString; -import com.rapidminer.parameter.UndefinedParameterError; -import com.rapidminer.parameter.conditions.BooleanParameterCondition; - - -/** - * @author Tobias Malbrecht - */ -public class StrictDecimalFormat extends DecimalFormat { - - private static final long serialVersionUID = -1597219600920760784L; - - public static final String PARAMETER_PARSE_NUMBERS = "parse_numbers"; - - public static final String PARAMETER_DECIMAL_CHARACTER = "decimal_character"; - - public static final String PARAMETER_GROUPED_DIGITS = "grouped_digits"; - - public static final String PARAMETER_GROUPING_CHARACTER = "grouping_character"; - - /** @since 8.2.1 */ - public static final String PARAMETER_INFINITY_STRING = "infinity_representation"; - - { - setParseIntegerOnly(false); - setGroupingSize(3); - } - - public static final char DEFAULT_DECIMAL_CHARACTER = '.'; - - public static final char DEFAULT_GROUPING_CHARACTER = ','; - - /** @since 8.2.1 */ - public static final String DEFAULT_INFINITY_STRING = ""; - - public StrictDecimalFormat() { - super(); - } - - public StrictDecimalFormat(char decimalSeparator) { - this(); - DecimalFormatSymbols symbols = getDecimalFormatSymbols(); - symbols.setDecimalSeparator(decimalSeparator); - setDecimalFormatSymbols(symbols); - setGroupingUsed(false); - } - - public StrictDecimalFormat(char decimalSeparator, char groupingSeparator) { - this(); - DecimalFormatSymbols symbols = getDecimalFormatSymbols(); - symbols.setDecimalSeparator(decimalSeparator); - symbols.setGroupingSeparator(groupingSeparator); - setDecimalFormatSymbols(symbols); - setGroupingUsed(true); - } - - @Override - public Number parse(String source) throws ParseException { - ParsePosition parsePosition = new ParsePosition(0); - Number result = parse(source, parsePosition); - - /** - * throw an error if a parse error has occurred somewhere in the source string, not only at - * the beginning as in {@link NumberFormat} - */ - if (result == null || parsePosition.getIndex() < source.length()) { - // try also with lowercase "e" as the exponent symbol (generally, lowercase version of - // the exponent separator) - String exponentSeparator = getDecimalFormatSymbols().getExponentSeparator(); - if (source.contains(exponentSeparator.toLowerCase())) { - parsePosition.setIndex(0); - result = parse(source.replace(exponentSeparator.toLowerCase(), exponentSeparator), parsePosition); - if (parsePosition.getIndex() < source.length()) { - throw new ParseException("Unparseable number: \"" + source + "\"", parsePosition.getIndex()); - } - } else { - throw new ParseException("Unparseable number: \"" + source + "\"", parsePosition.getIndex()); - } - } - return result; - } - - public void setDecimalSeparator(char decimalSeparator) { - DecimalFormatSymbols symbols = getDecimalFormatSymbols(); - symbols.setDecimalSeparator(decimalSeparator); - setDecimalFormatSymbols(symbols); - } - - public void setGroupingSeparator(char groupingSeparator) { - DecimalFormatSymbols symbols = getDecimalFormatSymbols(); - symbols.setGroupingSeparator(groupingSeparator); - setDecimalFormatSymbols(symbols); - } - - /** - * Sets the infinity symbol string of this number format. - * - * @param infinityString - * the infinity string representation - * @since 8.2.1 - */ - public void setInfinityString(String infinityString) { - DecimalFormatSymbols symbols = getDecimalFormatSymbols(); - symbols.setInfinity(infinityString); - setDecimalFormatSymbols(symbols); - } - - public static StrictDecimalFormat getInstance(ParameterHandler handler) throws UndefinedParameterError { - return getInstance(handler, false); - } - - public static StrictDecimalFormat getInstance(ParameterHandler handler, boolean optional) throws UndefinedParameterError { - if (optional && !handler.getParameterAsBoolean(PARAMETER_PARSE_NUMBERS)) { - return null; - } - char decimalCharacter = handler.getParameterAsChar(PARAMETER_DECIMAL_CHARACTER); - char groupingCharacter = handler.getParameterAsChar(PARAMETER_GROUPING_CHARACTER); - StrictDecimalFormat instance; - if (handler.getParameterAsBoolean(PARAMETER_GROUPED_DIGITS)) { - instance = new StrictDecimalFormat(decimalCharacter, groupingCharacter); - } else { - instance = new StrictDecimalFormat(decimalCharacter); - } - String infinityString = handler.getParameterAsString(PARAMETER_INFINITY_STRING); - if (infinityString != null && !infinityString.trim().isEmpty()) { - instance.setInfinityString(infinityString.trim()); - } - return instance; - } - - public static List getParameterTypes(ParameterHandler handler) { - return getParameterTypes(handler, false); - } - - public static List getParameterTypes(ParameterHandler handler, boolean optional) { - List types = new LinkedList<>(); - ParameterType type; - type = new ParameterTypeChar(PARAMETER_DECIMAL_CHARACTER, "The decimal character.", DEFAULT_DECIMAL_CHARACTER, false); - types.add(type); - type = new ParameterTypeBoolean(PARAMETER_GROUPED_DIGITS, "Parse grouped digits.", false, false); - types.add(type); - type = new ParameterTypeChar(PARAMETER_GROUPING_CHARACTER, "The grouping character.", DEFAULT_GROUPING_CHARACTER, - false); - type.registerDependencyCondition(new BooleanParameterCondition(handler, PARAMETER_GROUPED_DIGITS, false, true)); - types.add(type); - type = new ParameterTypeString(StrictDecimalFormat.PARAMETER_INFINITY_STRING, - "The infinity representation that should be recognized during parsing.", true, true); - type.setDefaultValue(DEFAULT_INFINITY_STRING); - types.add(type); - if (optional) { - type = new ParameterTypeBoolean(PARAMETER_PARSE_NUMBERS, "Specifies whether numbers are parsed.", true, false); - BooleanParameterCondition parseNumbersCondition = new BooleanParameterCondition( - handler, PARAMETER_PARSE_NUMBERS, false, true); - types.forEach(t -> t.registerDependencyCondition(parseNumbersCondition)); - types.add(0, type); - } - return types; - } -} +/** + * Copyright (C) 2001-2018 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.tools; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.ParseException; +import java.text.ParsePosition; +import java.util.LinkedList; +import java.util.List; + +import com.rapidminer.parameter.ParameterHandler; +import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.ParameterTypeBoolean; +import com.rapidminer.parameter.ParameterTypeChar; +import com.rapidminer.parameter.ParameterTypeString; +import com.rapidminer.parameter.UndefinedParameterError; +import com.rapidminer.parameter.conditions.BooleanParameterCondition; + + +/** + * @author Tobias Malbrecht + */ +public class StrictDecimalFormat extends DecimalFormat { + + private static final long serialVersionUID = -1597219600920760784L; + + public static final String PARAMETER_PARSE_NUMBERS = "parse_numbers"; + + public static final String PARAMETER_DECIMAL_CHARACTER = "decimal_character"; + + public static final String PARAMETER_GROUPED_DIGITS = "grouped_digits"; + + public static final String PARAMETER_GROUPING_CHARACTER = "grouping_character"; + + /** @since 8.2.1 */ + public static final String PARAMETER_INFINITY_STRING = "infinity_representation"; + + private static final String PLUS_SYMBOL = "+"; + + { + setParseIntegerOnly(false); + setGroupingSize(3); + } + + public static final char DEFAULT_DECIMAL_CHARACTER = '.'; + + public static final char DEFAULT_GROUPING_CHARACTER = ','; + + /** @since 8.2.1 */ + public static final String DEFAULT_INFINITY_STRING = ""; + + public StrictDecimalFormat() { + super(); + } + + public StrictDecimalFormat(char decimalSeparator) { + this(); + DecimalFormatSymbols symbols = getDecimalFormatSymbols(); + symbols.setDecimalSeparator(decimalSeparator); + setDecimalFormatSymbols(symbols); + setGroupingUsed(false); + } + + public StrictDecimalFormat(char decimalSeparator, char groupingSeparator) { + this(); + DecimalFormatSymbols symbols = getDecimalFormatSymbols(); + symbols.setDecimalSeparator(decimalSeparator); + symbols.setGroupingSeparator(groupingSeparator); + setDecimalFormatSymbols(symbols); + setGroupingUsed(true); + } + + @Override + public Number parse(String source) throws ParseException { + ParsePosition parsePosition = new ParsePosition(0); + Number result = parse(source, parsePosition); + + /** + * throw an error if a parse error has occurred somewhere in the source string, not only at + * the beginning as in {@link NumberFormat} + */ + if (result == null || parsePosition.getIndex() < source.length()) { + // find the "e" as the exponent symbol, searching for lowercase version of the exponent separator in lowercase source string + // if "e" is followed by a "+" the "+" will be removed to get a parseable number + String exponentSeparator = getDecimalFormatSymbols().getExponentSeparator(); + final String lowercaseSource = source.toLowerCase(); + int indexOfExp = lowercaseSource.indexOf(exponentSeparator.toLowerCase()); + if (indexOfExp > 0) { + parsePosition.setIndex(0); + String replacee = exponentSeparator.toLowerCase(); + if (source.length() > indexOfExp && source.substring(indexOfExp + 1).startsWith(PLUS_SYMBOL)) { + replacee = replacee + PLUS_SYMBOL; + } + final String sourceExpModified = lowercaseSource.replace(replacee, exponentSeparator); + result = parse(sourceExpModified, parsePosition); + if (parsePosition.getIndex() < sourceExpModified.length()) { + throw new ParseException("Unparseable number: \"" + source + "\"", parsePosition.getIndex()); + } + } else { + throw new ParseException("Unparseable number: \"" + source + "\"", parsePosition.getIndex()); + } + } + return result; + } + + public void setDecimalSeparator(char decimalSeparator) { + DecimalFormatSymbols symbols = getDecimalFormatSymbols(); + symbols.setDecimalSeparator(decimalSeparator); + setDecimalFormatSymbols(symbols); + } + + public void setGroupingSeparator(char groupingSeparator) { + DecimalFormatSymbols symbols = getDecimalFormatSymbols(); + symbols.setGroupingSeparator(groupingSeparator); + setDecimalFormatSymbols(symbols); + } + + /** + * Sets the infinity symbol string of this number format. + * + * @param infinityString + * the infinity string representation + * @since 8.2.1 + */ + public void setInfinityString(String infinityString) { + DecimalFormatSymbols symbols = getDecimalFormatSymbols(); + symbols.setInfinity(infinityString); + setDecimalFormatSymbols(symbols); + } + + public static StrictDecimalFormat getInstance(ParameterHandler handler) throws UndefinedParameterError { + return getInstance(handler, false); + } + + public static StrictDecimalFormat getInstance(ParameterHandler handler, boolean optional) throws UndefinedParameterError { + if (optional && !handler.getParameterAsBoolean(PARAMETER_PARSE_NUMBERS)) { + return null; + } + char decimalCharacter = handler.getParameterAsChar(PARAMETER_DECIMAL_CHARACTER); + char groupingCharacter = handler.getParameterAsChar(PARAMETER_GROUPING_CHARACTER); + StrictDecimalFormat instance; + if (handler.getParameterAsBoolean(PARAMETER_GROUPED_DIGITS)) { + instance = new StrictDecimalFormat(decimalCharacter, groupingCharacter); + } else { + instance = new StrictDecimalFormat(decimalCharacter); + } + String infinityString = handler.getParameterAsString(PARAMETER_INFINITY_STRING); + if (infinityString != null && !infinityString.trim().isEmpty()) { + instance.setInfinityString(infinityString.trim()); + } + return instance; + } + + public static List getParameterTypes(ParameterHandler handler) { + return getParameterTypes(handler, false); + } + + public static List getParameterTypes(ParameterHandler handler, boolean optional) { + List types = new LinkedList<>(); + ParameterType type; + type = new ParameterTypeChar(PARAMETER_DECIMAL_CHARACTER, "The decimal character.", DEFAULT_DECIMAL_CHARACTER, false); + types.add(type); + type = new ParameterTypeBoolean(PARAMETER_GROUPED_DIGITS, "Parse grouped digits.", false, false); + types.add(type); + type = new ParameterTypeChar(PARAMETER_GROUPING_CHARACTER, "The grouping character.", DEFAULT_GROUPING_CHARACTER, + false); + type.registerDependencyCondition(new BooleanParameterCondition(handler, PARAMETER_GROUPED_DIGITS, false, true)); + types.add(type); + type = new ParameterTypeString(StrictDecimalFormat.PARAMETER_INFINITY_STRING, + "The infinity representation that should be recognized during parsing.", true, true); + type.setDefaultValue(DEFAULT_INFINITY_STRING); + types.add(type); + if (optional) { + type = new ParameterTypeBoolean(PARAMETER_PARSE_NUMBERS, "Specifies whether numbers are parsed.", true, false); + BooleanParameterCondition parseNumbersCondition = new BooleanParameterCondition( + handler, PARAMETER_PARSE_NUMBERS, false, true); + types.forEach(t -> t.registerDependencyCondition(parseNumbersCondition)); + types.add(0, type); + } + return types; + } +} diff --git a/src/main/java/com/rapidminer/tools/Tools.java b/src/main/java/com/rapidminer/tools/Tools.java index ed060035c..3dc909462 100644 --- a/src/main/java/com/rapidminer/tools/Tools.java +++ b/src/main/java/com/rapidminer/tools/Tools.java @@ -121,42 +121,30 @@ public class Tools { // ThreadLocal because DateFormat is NOT threadsafe and creating a new DateFormat is // EXTREMELY expensive /** Used for formatting values in the {@link #formatTime(Date)} method. */ - private static final ThreadLocal TIME_FORMAT = new ThreadLocal() { - - @Override - protected DateFormat initialValue() { - // clone because getDateInstance uses an internal pool which can return the same - // instance for multiple threads - return (DateFormat) DateFormat.getTimeInstance(DateFormat.LONG, Locale.getDefault()).clone(); - } - }; + private static final ThreadLocal TIME_FORMAT = ThreadLocal.withInitial(() -> { + // clone because getDateInstance uses an internal pool which can return the same + // instance for multiple threads + return (DateFormat) DateFormat.getTimeInstance(DateFormat.LONG, Locale.getDefault()).clone(); + }); // ThreadLocal because DateFormat is NOT threadsafe and creating a new DateFormat is // EXTREMELY expensive /** Used for formatting values in the {@link #formatDate(Date)} method. */ - private static final ThreadLocal DATE_FORMAT = new ThreadLocal() { - - @Override - protected DateFormat initialValue() { - // clone because getDateInstance uses an internal pool which can return the same - // instance for multiple threads - return (DateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).clone(); - } - }; + private static final ThreadLocal DATE_FORMAT = ThreadLocal.withInitial(() -> { + // clone because getDateInstance uses an internal pool which can return the same + // instance for multiple threads + return (DateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).clone(); + }); // ThreadLocal because DateFormat is NOT threadsafe and creating a new DateFormat is // EXTREMELY expensive /** Used for formatting values in the {@link #formatDateTime(Date)} method. */ - public static final ThreadLocal DATE_TIME_FORMAT = new ThreadLocal() { - - @Override - protected DateFormat initialValue() { - // clone because getDateInstance uses an internal pool which can return the same - // instance for multiple threads - return (DateFormat) DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG, Locale.getDefault()) - .clone(); - } - }; + public static final ThreadLocal DATE_TIME_FORMAT = ThreadLocal.withInitial(() -> { + // clone because getDateInstance uses an internal pool which can return the same + // instance for multiple threads + return (DateFormat) DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG, Locale.getDefault()) + .clone(); + }); private static Locale FORMAT_LOCALE = Locale.US; diff --git a/src/main/java/com/rapidminer/tools/cipher/FileCipherKeyProvider.java b/src/main/java/com/rapidminer/tools/cipher/FileCipherKeyProvider.java index f2cd32d09..e250eb6e6 100644 --- a/src/main/java/com/rapidminer/tools/cipher/FileCipherKeyProvider.java +++ b/src/main/java/com/rapidminer/tools/cipher/FileCipherKeyProvider.java @@ -31,6 +31,7 @@ import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import com.rapidminer.RapidMiner; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.LogService; @@ -61,7 +62,8 @@ public SecretKey loadKey() throws KeyLoadingException { return KeyGeneratorTool.makeKey(rawKey); } catch (IOException e) { // catch to log the problem, then throw again to indicate error - LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.cipher.KeyGeneratorTool.read_key_error", + Level logLevel = RapidMiner.getExecutionMode().canAccessFilesystem() ? Level.WARNING : Level.CONFIG; + LogService.getRoot().log(logLevel, "com.rapidminer.tools.cipher.KeyGeneratorTool.read_key_error", e.getMessage()); throw new KeyLoadingException("Cannot retrieve key: " + e.getMessage()); } diff --git a/src/main/java/com/rapidminer/tools/config/AbstractConfigurator.java b/src/main/java/com/rapidminer/tools/config/AbstractConfigurator.java index d135a66df..a04e5a568 100644 --- a/src/main/java/com/rapidminer/tools/config/AbstractConfigurator.java +++ b/src/main/java/com/rapidminer/tools/config/AbstractConfigurator.java @@ -24,6 +24,7 @@ import com.rapidminer.parameter.ParameterHandler; import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; import com.rapidminer.parameter.conditions.ParameterCondition; import com.rapidminer.tools.I18N; @@ -117,7 +118,7 @@ public final ParameterHandler getParameterHandler(Configurable configurable) { String configurableName = configurable.getName(); if (!parameterHandlers.containsKey(configurableName)) { - parameterHandlers.put(configurableName, new ConfiguratorParameterHandler() { + parameterHandlers.put(configurableName, new SimpleListBasedParameterHandler() { @Override public List getParameterTypes() { diff --git a/src/main/java/com/rapidminer/tools/config/ClientConfigurationManager.java b/src/main/java/com/rapidminer/tools/config/ClientConfigurationManager.java index b9707efa1..34a3f1d34 100644 --- a/src/main/java/com/rapidminer/tools/config/ClientConfigurationManager.java +++ b/src/main/java/com/rapidminer/tools/config/ClientConfigurationManager.java @@ -1,30 +1,32 @@ /** * Copyright (C) 2001-2018 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.tools.config; import java.io.File; +import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.logging.Level; import org.w3c.dom.Document; +import com.rapidminer.RapidMiner; import com.rapidminer.io.process.XMLTools; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.I18N; @@ -36,13 +38,13 @@ * Stores configurations in files (one file per {@link Configurator}. * * @author Simon Fischer - * */ public class ClientConfigurationManager extends ConfigurationManager { @Override protected Map, Map> loadAllParameters( AbstractConfigurator configurator) throws ConfigurationException { + final File file = getConfigFile(configurator); if (!file.exists()) { LogService.getRoot().log(Level.INFO, @@ -58,9 +60,33 @@ protected Map, Map> loadAllParameters( } } - /** Returns the config file in which this data will be saved. */ - private File getConfigFile(AbstractConfigurator configurator) { - return FileSystemService.getUserConfigFile("configurable-" + configurator.getTypeId() + ".xml"); + /** + * Returns the config file in which is source or destination for the data. + * + * @since 9.0.3 + */ + private static File getConfigFile(AbstractConfigurator configurator) { + if (RapidMiner.ExecutionMode.TEST == RapidMiner.getExecutionMode()) { + try { + final File rapidMinerHome = FileSystemService.getRapidMinerHome(); + return new File(rapidMinerHome, getFileName(configurator)); + } catch (IOException e) { + LogService.getRoot().warning(e.getMessage()); + } + } + return FileSystemService.getUserConfigFile(getFileName(configurator)); + } + + /** + * Set up the file name for a configurable configuration file + * + * @param configurator + * may not be null, its type Id is used for the file name + * @return a file name like "configurable-twitter.xml" + * @since 9.0.3 + */ + private static String getFileName(AbstractConfigurator configurator) { + return "configurable-" + configurator.getTypeId() + ".xml"; } @Override diff --git a/src/main/java/com/rapidminer/tools/config/ConfigurationManager.java b/src/main/java/com/rapidminer/tools/config/ConfigurationManager.java index f14d4a162..f6ce58b1a 100644 --- a/src/main/java/com/rapidminer/tools/config/ConfigurationManager.java +++ b/src/main/java/com/rapidminer/tools/config/ConfigurationManager.java @@ -1,18 +1,18 @@ /** * Copyright (C) 2001-2018 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/. */ @@ -43,6 +43,7 @@ import com.rapidminer.io.process.XMLTools; import com.rapidminer.parameter.ParameterHandler; import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; import com.rapidminer.repository.ConnectionListener; import com.rapidminer.repository.ConnectionRepository; import com.rapidminer.repository.Folder; @@ -118,7 +119,7 @@ public boolean test(Configurable configurable) { return false; } }; - + /** * Compares {@link Configurable}s. */ @@ -151,7 +152,7 @@ public int compare(Configurable o1, Configurable o2) { * {@link ConfigurationManager#createAndRegisterConfigurables(AbstractConfigurator, java.util.Map, java.util.Map, com.rapidminer.repository.internal.remote.RemoteRepository)} * for mocking a {@link ParameterHandler} when retrieving the list of parameters. */ - private static final ParameterHandler EMPTY_PARAMETER_HANDLER = new ConfiguratorParameterHandler() { + private static final ParameterHandler EMPTY_PARAMETER_HANDLER = new SimpleListBasedParameterHandler() { @Override public List getParameterTypes() { @@ -322,10 +323,10 @@ public synchronized void register(AbstractConfigurator c throw new RuntimeException("typeID must not be null for " + configurator.getClass() + "!"); } configurators.put(typeId, configurator); - configurables.put(typeId, new TreeMap, Configurable>()); + configurables.put(typeId, new TreeMap<>()); if (permittedGroups.get(typeId) == null) { - permittedGroups.put(typeId, new TreeMap, Set>()); + permittedGroups.put(typeId, new TreeMap<>()); } } @@ -458,7 +459,7 @@ public Configurable lookup(String typeId, String name, RepositoryAccessor access .map(nameAndSourceToConfigurable::get).orElse(null); if (result == null) { AbstractConfigurator configurator = configurators.get(typeId); - throw new ConfigurationException("No such configured object of name " + name + " of " + configurator.getName()); + throw new ConfigurationException("No such configured object of name " + name + " of " + (configurator != null ? configurator.getName() : "typeId: " + typeId)); } return result; } diff --git a/src/main/java/com/rapidminer/tools/config/Configurator.java b/src/main/java/com/rapidminer/tools/config/Configurator.java index 74b6d2952..08f2ea409 100644 --- a/src/main/java/com/rapidminer/tools/config/Configurator.java +++ b/src/main/java/com/rapidminer/tools/config/Configurator.java @@ -22,6 +22,7 @@ import com.rapidminer.parameter.ParameterHandler; import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; /** @@ -52,7 +53,7 @@ public abstract class Configurator extends AbstractConfi * * This class can be used to convert and check parameters. */ - private class DefaultParameterHandler extends ConfiguratorParameterHandler { + private class DefaultParameterHandler extends SimpleListBasedParameterHandler { @Override public List getParameterTypes() { diff --git a/src/main/java/com/rapidminer/tools/config/ConfiguratorParameterHandler.java b/src/main/java/com/rapidminer/tools/config/ConfiguratorParameterHandler.java index 7eb98d2a7..2129b9fa3 100644 --- a/src/main/java/com/rapidminer/tools/config/ConfiguratorParameterHandler.java +++ b/src/main/java/com/rapidminer/tools/config/ConfiguratorParameterHandler.java @@ -18,28 +18,9 @@ */ package com.rapidminer.tools.config; -import java.awt.Color; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; - -import com.rapidminer.operator.OperatorException; import com.rapidminer.parameter.ParameterHandler; import com.rapidminer.parameter.ParameterType; -import com.rapidminer.parameter.ParameterTypeCategory; -import com.rapidminer.parameter.ParameterTypeColor; -import com.rapidminer.parameter.ParameterTypeList; -import com.rapidminer.parameter.ParameterTypeTupel; -import com.rapidminer.parameter.Parameters; -import com.rapidminer.parameter.UndefinedParameterError; -import com.rapidminer.tools.WebServiceTools; -import com.rapidminer.tools.math.StringToMatrixConverter; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; /** @@ -51,195 +32,7 @@ * @since 6.1.1 Extracted to public class * * @author Simon Fischer, Dominik Halfkann, Marco Boeck, Adrian Wilke + * @deprecated since 9.1; use {@link SimpleListBasedParameterHandler} instead */ -public abstract class ConfiguratorParameterHandler implements ParameterHandler { - - private Parameters parameters; - - @Override - public String getParameter(String key) throws UndefinedParameterError { - return this.parameters.getParameter(key); - } - - @Override - public boolean getParameterAsBoolean(String key) { - try { - return Boolean.valueOf(getParameter(key)); - } catch (UndefinedParameterError e) { - return false; - } - } - - @Override - public char getParameterAsChar(String key) throws UndefinedParameterError { - String parameterValue = getParameter(key); - if (parameterValue != null && parameterValue.length() > 0) { - return parameterValue.charAt(0); - } - return 0; - } - - @Override - public Color getParameterAsColor(String key) throws UndefinedParameterError { - String parameterValue = getParameter(key); - if (parameterValue == null) { - return Color.BLACK; - } - return ParameterTypeColor.string2Color(parameterValue); - } - - @Override - public double getParameterAsDouble(String key) throws UndefinedParameterError { - String value = getParameter(key); - if (value == null) { - throw new UndefinedParameterError(key); - } - try { - return Double.valueOf(value); - } catch (NumberFormatException e) { - throw new UndefinedParameterError(key, "Expected real number but found '" + value + "'."); - } - } - - @Override - public InputStream getParameterAsInputStream(String key) throws UndefinedParameterError, IOException { - String urlString = getParameter(key); - if (urlString == null) { - return null; - } - - try { - URL url = new URL(urlString); - InputStream stream = WebServiceTools.openStreamFromURL(url); - return stream; - } catch (MalformedURLException e) { - // URL did not work? Try as file... - File file = getParameterAsFile(key); - if (file != null) { - return new FileInputStream(file); - } else { - return null; - } - } - } - - @Override - public File getParameterAsFile(String key) throws UndefinedParameterError { - return getParameterAsFile(key, false); - } - - @Override - public File getParameterAsFile(String key, boolean createMissingDirectories) throws UndefinedParameterError { - String filename = getParameter(key); - if (filename == null) { - return null; - } - if (!Files.exists(Paths.get(filename))) { - return null; - } - return new File(filename); - } - - @Override - public int getParameterAsInt(String key) throws UndefinedParameterError { - ParameterType type = this.parameters.getParameterType(key); - String value = getParameter(key); - if (type != null) { - if (type instanceof ParameterTypeCategory) { - try { - return Integer.valueOf(value); - } catch (NumberFormatException e) { - ParameterTypeCategory categoryType = (ParameterTypeCategory) type; - return categoryType.getIndex(value); - } - } - } - try { - return Integer.valueOf(value); - } catch (NumberFormatException e) { - throw new UndefinedParameterError(key, "Expected integer but found '" + value + "'."); - } - } - - @Override - public long getParameterAsLong(String key) throws UndefinedParameterError { - ParameterType type = this.parameters.getParameterType(key); - String value = getParameter(key); - if (type != null) { - if (type instanceof ParameterTypeCategory) { - try { - return Long.valueOf(value); - } catch (NumberFormatException e) { - ParameterTypeCategory categoryType = (ParameterTypeCategory) type; - return categoryType.getIndex(value); - } - } - } - try { - return Long.valueOf(value); - } catch (NumberFormatException e) { - throw new UndefinedParameterError(key, "Expected long but found '" + value + "'."); - } - } - - @Override - public double[][] getParameterAsMatrix(String key) throws UndefinedParameterError { - String matrixLine = getParameter(key); - try { - return StringToMatrixConverter.parseMatlabString(matrixLine); - } catch (OperatorException e) { - throw new UndefinedParameterError(e.getMessage()); - } - } - - @Override - public String getParameterAsString(String key) throws UndefinedParameterError { - return getParameter(key); - } - - @Override - public List getParameterList(String key) throws UndefinedParameterError { - String value = getParameter(key); - if (value == null) { - throw new UndefinedParameterError(key); - } - return ParameterTypeList.transformString2List(value); - } - - @Override - public String[] getParameterTupel(String key) throws UndefinedParameterError { - String value = getParameter(key); - if (value == null) { - throw new UndefinedParameterError(key); - } - return ParameterTypeTupel.transformString2Tupel(value); - } - - @Override - public boolean isParameterSet(String key) throws UndefinedParameterError { - return getParameter(key) != null; - } - - @Override - public void setListParameter(String key, List list) { - this.parameters.setParameter(key, ParameterTypeList.transformList2String(list)); - } - - @Override - public void setParameter(String key, String value) { - this.parameters.setParameter(key, value); - } - - @Override - public void setParameters(Parameters parameters) { - this.parameters = parameters; - } - - @Override - public Parameters getParameters() { - if (this.parameters == null) { - this.parameters = new Parameters(getParameterTypes()); - } - return this.parameters; - } -} +@Deprecated +public abstract class ConfiguratorParameterHandler extends SimpleListBasedParameterHandler {} diff --git a/src/main/java/com/rapidminer/tools/math/ROCDataGenerator.java b/src/main/java/com/rapidminer/tools/math/ROCDataGenerator.java index 03bd09c76..4625aa0b0 100644 --- a/src/main/java/com/rapidminer/tools/math/ROCDataGenerator.java +++ b/src/main/java/com/rapidminer/tools/math/ROCDataGenerator.java @@ -31,6 +31,7 @@ import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.Statistics; +import com.rapidminer.gui.ApplicationFrame; import com.rapidminer.gui.plotter.ScatterPlotter; import com.rapidminer.gui.plotter.SimplePlotterDialog; import com.rapidminer.gui.viewer.ROCChartPlotter; @@ -278,7 +279,7 @@ public void createROCPlotDialog(ROCData data) { dialog.setTitle("ROC Plot"); dialog.add(plotter); dialog.setSize(500, 500); - dialog.setLocationRelativeTo(null); + dialog.setLocationRelativeTo(ApplicationFrame.getApplicationFrame()); dialog.setVisible(true); } diff --git a/src/main/java/com/rapidminer/tools/math/similarity/numerical/MaxProductSimilarity.java b/src/main/java/com/rapidminer/tools/math/similarity/numerical/MaxProductSimilarity.java index 85eb543f7..cf9a7d165 100644 --- a/src/main/java/com/rapidminer/tools/math/similarity/numerical/MaxProductSimilarity.java +++ b/src/main/java/com/rapidminer/tools/math/similarity/numerical/MaxProductSimilarity.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.tools.math.similarity.numerical; import com.rapidminer.example.ExampleSet; @@ -28,7 +28,7 @@ * Specialized similarity that takes the maximum product of two feature values. If this value is * zero, the similarity is undefined. This similarity measure is used mainly with features extracted * from cluster models. - * + * * @author Michael Wurst */ public class MaxProductSimilarity extends SimilarityMeasure { @@ -39,11 +39,12 @@ public class MaxProductSimilarity extends SimilarityMeasure { public double calculateSimilarity(double[] value1, double[] value2) { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < value1.length; i++) { - if ((!Double.isNaN(value1[i])) && (!Double.isNaN(value2[i]))) { - double v = value2[i] * value1[i]; - if (v > max) { - max = v; - } + if (Double.isNaN(value1[i]) || Double.isNaN(value2[i])) { + continue; + } + double v = value2[i] * value1[i]; + if (v > max) { + max = v; } } if (max > 0.0) { diff --git a/src/main/java/com/rapidminer/tools/net/UserProvidedTLSCertificateLoader.java b/src/main/java/com/rapidminer/tools/net/UserProvidedTLSCertificateLoader.java new file mode 100644 index 000000000..c38af7ef6 --- /dev/null +++ b/src/main/java/com/rapidminer/tools/net/UserProvidedTLSCertificateLoader.java @@ -0,0 +1,221 @@ +/** + * Copyright (C) 2001-2018 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.tools.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.FileVisitOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Stream; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.rapidminer.RapidMiner; +import com.rapidminer.tools.FileSystemService; +import com.rapidminer.tools.LogService; +import com.rapidminer.tools.PlatformUtilities; + + +/** + * Loads additional X.509 certificates from .RapidMiner/cacerts + *

    + * The certificates are loaded from both the jre cacerts file as well as from the .RapidMiner/cacerts folder. Loading is + * only done once on startup. + * + * @author Jonas Wilms-Pfau + * @since 9.1 + */ +public enum UserProvidedTLSCertificateLoader { + INSTANCE; + + private static final String CERTS_FOLDER = "cacerts"; + private static final String X509 = "X.509"; + private static final String USER_CERT_PREFIX = "user_cert_"; + private static final String JRE_CERT_PREFIX = "jre_cert_"; + private static final char SEPARATOR = '_'; + private static final String TMP_PREFIX = "cacerts-rm"; + private static final String TMP_SUFFIX = "jks"; + + /** + * We can only access the LogService if + *

      + *
    1. PlatformUtilities are initialized
    2. + *
    3. We have Filesystem access
    4. + *
    + */ + private final Logger logger; + + UserProvidedTLSCertificateLoader() { + if (RapidMiner.getExecutionMode().canAccessFilesystem()) { + PlatformUtilities.initialize(); + logger = LogService.getRoot(); + } else { + logger = Logger.getLogger(UserProvidedTLSCertificateLoader.class.getName()); + } + reloadCertificates(); + } + + /** + * Initializes the TrustManager + * + * @see #reloadCertificates() + */ + public void init() { + // init happens in the constructor + } + + /** + * Reloads the certificates from the .RapidMiner/cacerts folder and merges them with the provided jvm certificates + */ + private void reloadCertificates() { + try { + Path certsPath = FileSystemService.getUserRapidMinerDir().toPath().resolve(CERTS_FOLDER); + Map userCertificates = readCertificates(certsPath); + if (userCertificates.isEmpty()) { + // No need to do anything here + return; + } + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + // init with default keystore (or "javax.net.ssl.trustStore" if configured) + factory.init((KeyStore) null); + // Extract the default certificates + userCertificates.putAll(extractCertificates(factory.getTrustManagers())); + // Create new keystore, containing all certificates + KeyStore keystore = createKeyStore(userCertificates); + String password = UUID.randomUUID().toString(); + Path keystoreFile = Files.createTempFile(TMP_PREFIX, TMP_SUFFIX); + keystoreFile.toFile().deleteOnExit(); + try (OutputStream out = Files.newOutputStream(keystoreFile)) { + keystore.store(out, password.toCharArray()); + } + // Set the new trustStore and trustStorePassword + System.setProperty("javax.net.ssl.trustStore", keystoreFile.toAbsolutePath().toString()); + System.setProperty("javax.net.ssl.trustStorePassword", password); + } catch (Throwable e) { + logger.log(Level.SEVERE, "Loading of user provided certificates failed.", e); + } + } + + /** + * Creates a new java keystore, containing the given certificates + * + * @param certificates + * the certificates that the keystore should contain + * @return a new in-memory {@link KeyStore} containing the certificates + * @throws KeyStoreException + * if no Provider supports a KeyStoreSpi implementation for the default type, if the keystore has not been + * initialized, or the given alias already exists and does not identify an entry containing a trusted certificate, + * or this operation fails for some other reason. + * @throws CertificateException + * if any of the certificates in the keystore could not be loaded + * @throws NoSuchAlgorithmException + * if the algorithm used to check the integrity of the keystore cannot be found + * @throws IOException + * if there is an I/O or format problem with the keystore data. If the error is due to an incorrect + * ProtectionParameter (e.g. wrong password) the cause of the IOException should be an UnrecoverableKeyException + */ + private KeyStore createKeyStore(Map certificates) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); + keystore.load(null); + for (Map.Entry certificate : certificates.entrySet()) { + keystore.setCertificateEntry(certificate.getKey(), certificate.getValue()); + } + return keystore; + } + + /** + * Extracts the X509Certificate from the given TrustManagers + * + * @param trustManagers + * trust managers to extract the certificates from + * @return Map containing the certificates + */ + private Map extractCertificates(TrustManager... trustManagers) { + Map certificates = new HashMap<>(); + int certCount = 0; + for (TrustManager manager : trustManagers) { + if (manager instanceof X509TrustManager) { + for (X509Certificate x509Certificate : ((X509TrustManager) manager).getAcceptedIssuers()) { + String name = JRE_CERT_PREFIX + certCount++; + certificates.put(name, x509Certificate); + } + } + } + return certificates; + } + + /** + * Reads the certificates from the given path + * + * @param certFolder + * the folder containing the certificates + * @return a map containing all names and certificates + */ + private Map readCertificates(Path certFolder) throws IOException, CertificateException { + if (!certFolder.toFile().exists()) { + return Collections.emptyMap(); + } + + Map result = new ConcurrentHashMap<>(); + CertificateFactory factory = CertificateFactory.getInstance(X509); + Predicate isDirectory = Files::isDirectory; + try (Stream files = Files.walk(certFolder, FileVisitOption.FOLLOW_LINKS)) { + AtomicInteger globalCount = new AtomicInteger(0); + files.filter(isDirectory.negate()).forEach(path -> { + String filename = path.getFileName().toString(); + // Filenames might occur multiple times in the file tree + int fileNumber = globalCount.getAndIncrement(); + try (InputStream fileInputStream = Files.newInputStream(path)) { + Collection certificates = factory.generateCertificates(fileInputStream); + int certCount = 0; + for (Certificate certificate : certificates) { + String name = USER_CERT_PREFIX + fileNumber + SEPARATOR + certCount++ + SEPARATOR + filename; + result.put(name, certificate); + } + logger.info("Loaded " + certCount + " certificate" + (certCount != 1 ? "s" : "") + " from " + filename); + } catch (IOException | CertificateException e) { + logger.log(Level.WARNING, "Could not load certificates from " + filename, e); + } + }); + } + + return result; + } + +} diff --git a/src/main/java/com/rapidminer/tools/parameter/admin/WindowsRegistryParameterProvider.java b/src/main/java/com/rapidminer/tools/parameter/admin/WindowsRegistryParameterProvider.java index eba1dfde9..29f7e3421 100644 --- a/src/main/java/com/rapidminer/tools/parameter/admin/WindowsRegistryParameterProvider.java +++ b/src/main/java/com/rapidminer/tools/parameter/admin/WindowsRegistryParameterProvider.java @@ -70,7 +70,7 @@ public Map readProperties() { ); LogService.getRoot().fine(() -> String.format("Successfully enforced %d settings from the Windows registry.", values.size())); return values; - } catch (Exception e) { + } catch (Throwable e) { LogService.getRoot().log(Level.WARNING, "Failed to access the Windows registry.", e); return null; } diff --git a/src/main/java/com/rapidminer/tools/plugin/Plugin.java b/src/main/java/com/rapidminer/tools/plugin/Plugin.java index 7f3ee9a73..586362e0b 100644 --- a/src/main/java/com/rapidminer/tools/plugin/Plugin.java +++ b/src/main/java/com/rapidminer/tools/plugin/Plugin.java @@ -145,7 +145,7 @@ public class Plugin { /** @since 9.0.0 */ public static final String WHITELIST_SHIPPED = "shipped"; /** @since 9.0.0 */ - private static final String PACKAGED_IDS = "advanced_file_connectors,concurrency,jdbc_connectors,legacy,productivity,professional,remote_repository"; + private static final String PACKAGED_IDS = "advanced_file_connectors,concurrency,jdbc_connectors,legacy,productivity,professional,remote_repository,blending"; /** @since 9.0.0 */ private static final Set PACKAGED_EXTENSIONS; /** @since 9.0.0 */ diff --git a/src/main/java/com/rapidminer/tools/update/internal/MigrationManager.java b/src/main/java/com/rapidminer/tools/update/internal/MigrationManager.java new file mode 100644 index 000000000..acd7c62db --- /dev/null +++ b/src/main/java/com/rapidminer/tools/update/internal/MigrationManager.java @@ -0,0 +1,242 @@ +/** + * Copyright (C) 2001-2018 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.tools.update.internal; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Properties; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import com.rapidminer.RapidMiner; +import com.rapidminer.gui.RapidMinerGUI; +import com.rapidminer.gui.tools.VersionNumber; +import com.rapidminer.tools.FileSystemService; +import com.rapidminer.tools.I18N; +import com.rapidminer.tools.LogService; +import com.rapidminer.tools.ParameterService; + + +/** + * Updates of RM Studio sometimes require specific changes to parts of the installation. With this class it is possible + * to execute these changes only if the specific version update happened. + * + * @author Andreas Timm + * @since 9.1.0 + */ +public final class MigrationManager { + + /** + * The {@link MigrationStep} gets all the information which is required to check if the update is necessary and + * run the update itself. + */ + static class MigrationStep { + + /** + * Name of the step for information through logs + */ + private String name; + + /** + * Minimal version from which the changes are possible + */ + private VersionNumber fromVersion; + + /** + * The target version of this migration must be at most the Studio version. + */ + private VersionNumber toVersion; + + /** + * The code that will be executed + */ + private Runnable runnable; + + /** + * {@link MigrationStep} holds all the information for migration + * + * @param name + * of the step, will be shown in the logs + * @param fromVersion + * minimal version for the migration to make sense and be executed, may be null for any + * @param toVersion + * only run the migration if at least the target version is reached + * @param runnable + * the actual migration + */ + public MigrationStep(String name, VersionNumber fromVersion, VersionNumber toVersion, Runnable runnable) { + this.name = Objects.requireNonNull(name); + this.fromVersion = fromVersion; + this.toVersion = Objects.requireNonNull(toVersion); + this.runnable = Objects.requireNonNull(runnable); + } + + /** + * Minimal version for the migration + * + * @return a {@link VersionNumber} or null + */ + private VersionNumber getFromVersion() { + return fromVersion; + } + + /** + * Minimal Studio version for the migration + * + * @return a {@link VersionNumber} + */ + private VersionNumber getToVersion() { + return toVersion; + } + + /** + * Execute the step safely, will catch any error and just log it. + */ + private void runSafe() { + try { + LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.update.internal.MigrationManager.starting", name); + runnable.run(); + LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.update.internal.MigrationManager.success", name); + + } catch (Exception e) { + LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(), "com.rapidminer.tools.update.internal.MigrationManager.failure", name), e); + } + } + + + } + + /** + * List of all possible migration steps. + */ + private static List steps = new ArrayList<>(); + + /** + * Migration of the parameter "disconnect_on_disable" is done here + * + * @since 9.1.0 + */ + private static final MigrationStep REMOVE_DISCONNECT_ON_DISABLE_SETTING = new MigrationStep("Migrate disconnect on disable setting", null, + new VersionNumber(9, 1, 0), () -> { + if (RapidMiner.getExecutionMode().canAccessFilesystem() && !RapidMiner.getExecutionMode().isHeadless()) { + File userConfigFile = FileSystemService.getUserConfigFile(ParameterService.RAPIDMINER_CONFIG_FILE_NAME); + if (userConfigFile != null) { + Properties properties = new Properties(); + // read the user config for RM Studio + try (InputStream in = new FileInputStream(userConfigFile)) { + properties.load(in); + final String disconnectOnDisableKey = "rapidminer.gui.disconnect_on_disable"; + String disconnectOnDisableValue = properties.getProperty(disconnectOnDisableKey); + if (disconnectOnDisableValue != null) { + // Migration strategy: + // if disconnect_on_disable was set to true, set the new parameters disable_op_conn_behavior and delete_op_conn_behavior to drop + // else set disable_op_conn_behavior to keep and delete_op_conn_behavior to bridge + if (Boolean.parseBoolean(disconnectOnDisableValue)) { + if (!properties.containsKey(RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR)) { + properties.setProperty(RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR, RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_VALUES[0]); + } + if (!properties.containsKey(RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR)) { + properties.setProperty(RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR, RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_VALUES[0]); + } + } else { + if (!properties.containsKey(RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR)) { + properties.setProperty(RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR, RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_VALUES[RapidMinerGUI.PROPERTY_DISABLE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE]); + } + if (!properties.containsKey(RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR)) { + properties.setProperty(RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR, RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_VALUES[RapidMinerGUI.PROPERTY_DELETE_OPERATOR_CONNECTION_BEHAVIOR_DEFAULT_VALUE]); + } + } + properties.remove(disconnectOnDisableKey); + } + storeProperties(userConfigFile, properties); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + }); + + static { + steps.add(REMOVE_DISCONNECT_ON_DISABLE_SETTING); + } + + /** + * Util class, not to be instantiated. + */ + private MigrationManager() { + throw new UnsupportedOperationException("Util class, not to be instantiated!"); + } + + /** + * Calculate the necessary migration and execute it. Will be executed in the order of appearance in the list steps. + * + * @param fromVersion + * the version that was last in use before the update + * @param toVersion + * the current version + */ + public static void doMigrate(VersionNumber fromVersion, VersionNumber toVersion) { + if (fromVersion == null || toVersion == null) { + return; + } + + getNecessaryMigrationSteps(fromVersion, toVersion).forEach(MigrationStep::runSafe); + } + + /** + * Find the necessary migration steps. + * + * @param fromVersion + * version that was in use previously + * @param toVersion + * current version + * @return Stream of the steps that need to be run now + */ + static List getNecessaryMigrationSteps(VersionNumber fromVersion, VersionNumber toVersion) { + if (fromVersion == null || toVersion == null) { + return Collections.emptyList(); + } + return steps.stream().filter(migrationStep -> (migrationStep.getFromVersion() == null || fromVersion.isAtLeast(migrationStep.getFromVersion())) + && migrationStep.getToVersion().isAtMost(toVersion) && migrationStep.getToVersion().isAbove(fromVersion)).collect(Collectors.toList()); + } + + /** + * Store properties in this file + * + * @param outfile + * where to store the properties + * @param properties + * the properties to be stored + */ + private static void storeProperties(File outfile, Properties properties) { + try (FileOutputStream fos = new FileOutputStream(outfile); BufferedOutputStream out = new BufferedOutputStream(fos)) { + properties.store(out, ""); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/src/main/java/com/rapidminer/tools/usagestats/ActionStatisticsCollector.java b/src/main/java/com/rapidminer/tools/usagestats/ActionStatisticsCollector.java index 807601197..58e48b92e 100644 --- a/src/main/java/com/rapidminer/tools/usagestats/ActionStatisticsCollector.java +++ b/src/main/java/com/rapidminer/tools/usagestats/ActionStatisticsCollector.java @@ -24,6 +24,8 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.EnumSet; @@ -256,6 +258,15 @@ public static interface UsageObject { /** remote_repository | status | uuid (since 8.2.1) */ public static final String TYPE_REMOTE_REPOSITORY = "remote_repository"; + /** new_import | guessed_date_wrong | guessed|choosen (since 9.1) */ + public static final String VALUE_GUESSED_DATE_FORMAT_RIGHT = "guessed_date_format_right"; + public static final String VALUE_GUESSED_DATE_FORMAT_WRONG = "guessed_date_format_wrong"; + public static final String ARG_GUESSED_DATE_SEPARATOR = "|"; + + /** es_view_filter | filter_selected | condition (since 9.1) */ + public static final String TYPE_EXAMPLESET_VIEW_FILTER = "es_view_filter"; + public static final String VALUE_FILTER_SELECTED = "filter_selected"; + public static final String VALUE_CREATED = "created"; public static final String VALUE_CONNECTED = "connected"; public static final String VALUE_CONNECTION_ERROR = "connection_error"; @@ -339,6 +350,21 @@ public void logGlobalSearchAction(String searchTerm, String categoryId, String c log(TYPE_GLOBAL_SEARCH, VALUE_ACTION, arg.toString()); } + /** + * Logs the guessed and chosen format + * + * @param guessed The guessed date format pattern + * @param chosenFormat The chosen date format + * @since 9.1 + */ + public void logGuessedDateFormat(String guessed, DateFormat chosenFormat) { + guessed = guessed != null ? guessed : ""; + String chosen = (chosenFormat instanceof SimpleDateFormat) ? ((SimpleDateFormat) chosenFormat).toPattern() : ""; + String value = guessed.equals(chosen) ? VALUE_GUESSED_DATE_FORMAT_RIGHT : VALUE_GUESSED_DATE_FORMAT_WRONG; + String argument = guessed.equals(chosen) ? chosen : guessed + ARG_GUESSED_DATE_SEPARATOR + chosen; + log(TYPE_NEW_IMPORT, value, argument); + } + /** * A Key defines an identifier that is used to store some collected usage data associated with it. It has 3 levels, * TYPE, VALUE and ARG, where ARG may be null. diff --git a/src/main/java/com/rapidminer/tools/usagestats/RuleService.java b/src/main/java/com/rapidminer/tools/usagestats/RuleService.java index 804678cae..4d346655f 100644 --- a/src/main/java/com/rapidminer/tools/usagestats/RuleService.java +++ b/src/main/java/com/rapidminer/tools/usagestats/RuleService.java @@ -24,9 +24,10 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -51,39 +52,42 @@ enum RuleService { INSTANCE; - private final Set PROHIBITED_KEYWORDS = new HashSet<>(); + private final Pattern prohibitedKeywords; private final Set rules = new HashSet<>(); private RuleService() { - PROHIBITED_KEYWORDS.add("JOIN"); - PROHIBITED_KEYWORDS.add("CREATE"); - PROHIBITED_KEYWORDS.add("INSERT"); - PROHIBITED_KEYWORDS.add("UPDATE"); - PROHIBITED_KEYWORDS.add("DELETE"); - PROHIBITED_KEYWORDS.add("DROP"); - PROHIBITED_KEYWORDS.add("ALTER"); - PROHIBITED_KEYWORDS.add("MERGE"); - PROHIBITED_KEYWORDS.add("TRUNCATE"); - PROHIBITED_KEYWORDS.add("SET"); - PROHIBITED_KEYWORDS.add("SHUTDOWN"); - PROHIBITED_KEYWORDS.add("COMMIT"); - PROHIBITED_KEYWORDS.add("GRANT"); - PROHIBITED_KEYWORDS.add("CHECKPOINT"); - PROHIBITED_KEYWORDS.add("SAVEPOINT"); - PROHIBITED_KEYWORDS.add("PREPARE"); - PROHIBITED_KEYWORDS.add("REVOKE"); - PROHIBITED_KEYWORDS.add("ROLLBACK"); - PROHIBITED_KEYWORDS.add("CONSTRAINT"); - PROHIBITED_KEYWORDS.add("RUNSCRIPT"); - PROHIBITED_KEYWORDS.add("BACKUP"); - PROHIBITED_KEYWORDS.add("CALL"); - PROHIBITED_KEYWORDS.add("SCRIPT"); - PROHIBITED_KEYWORDS.add("ANALYZE"); - PROHIBITED_KEYWORDS.add("COMMENT"); - PROHIBITED_KEYWORDS.add("EXPLAIN"); - PROHIBITED_KEYWORDS.add("SHOW"); - + List prohibitedKeywords = new ArrayList<>(); + prohibitedKeywords.add("JOIN"); + prohibitedKeywords.add("CREATE"); + prohibitedKeywords.add("INSERT"); + prohibitedKeywords.add("UPDATE"); + prohibitedKeywords.add("DELETE"); + prohibitedKeywords.add("DROP"); + prohibitedKeywords.add("ALTER"); + prohibitedKeywords.add("MERGE"); + prohibitedKeywords.add("TRUNCATE"); + prohibitedKeywords.add("SET"); + prohibitedKeywords.add("SHUTDOWN"); + prohibitedKeywords.add("COMMIT"); + prohibitedKeywords.add("GRANT"); + prohibitedKeywords.add("CHECKPOINT"); + prohibitedKeywords.add("SAVEPOINT"); + prohibitedKeywords.add("PREPARE"); + prohibitedKeywords.add("REVOKE"); + prohibitedKeywords.add("ROLLBACK"); + prohibitedKeywords.add("CONSTRAINT"); + prohibitedKeywords.add("RUNSCRIPT"); + prohibitedKeywords.add("BACKUP"); + prohibitedKeywords.add("CALL"); + prohibitedKeywords.add("SCRIPT"); + prohibitedKeywords.add("ANALYZE"); + prohibitedKeywords.add("COMMENT"); + prohibitedKeywords.add("EXPLAIN"); + prohibitedKeywords.add("SHOW"); + + // Create a "\b(JOIN|CREATE|...)\b" regex, where \b matches word boundaries + this.prohibitedKeywords = Pattern.compile("\\b(" + String.join("|", prohibitedKeywords) + ")\\b", Pattern.CASE_INSENSITIVE); reloadRules(); } @@ -165,7 +169,7 @@ public void reloadRules() { /** * Converts JSON rules list to a {@link VerifiableRule} list. Also checks that rules do not - * violate the {@link #PROHIBITED_KEYWORDS} SQL blacklist. If any rules does, it is skipped. + * violate the {@link #prohibitedKeywords} SQL blacklist. If any rules does, it is skipped. * * @param jsonRules * the input rule list @@ -173,19 +177,16 @@ public void reloadRules() { */ private List checkAndConvertRules(List jsonRules) { List newRules = new ArrayList<>(jsonRules.size()); - ruleLoop: for (Rule rule : jsonRules) { - for (String sql : rule.getQueries()) { - for (String prohibited : PROHIBITED_KEYWORDS) { - if (sql.toUpperCase(Locale.ENGLISH).contains(prohibited)) { - // prohibited keyword found, skip this rule - LogService.getRoot().log(Level.WARNING, - "com.rapidminer.tools.usagestats.RuleService.load_invalid_sql", - new Object[] { rule.getId(), prohibited }); - continue ruleLoop; - } - } + for (Rule rule : jsonRules) { + Matcher matcher = prohibitedKeywords.matcher(String.join(" ", rule.getQueries())); + if (matcher.find()) { + // prohibited keyword found, skip this rule + LogService.getRoot().log(Level.WARNING, + "com.rapidminer.tools.usagestats.RuleService.load_invalid_sql", + new Object[]{rule.getId(), matcher.group()}); + } else { + newRules.add(new VerifiableRule(rule)); } - newRules.add(new VerifiableRule(rule)); } return newRules; diff --git a/src/main/java/com/rapidminer/tutorial/gui/TutorialSelector.java b/src/main/java/com/rapidminer/tutorial/gui/TutorialSelector.java index 7a379fffe..94b360918 100644 --- a/src/main/java/com/rapidminer/tutorial/gui/TutorialSelector.java +++ b/src/main/java/com/rapidminer/tutorial/gui/TutorialSelector.java @@ -168,14 +168,8 @@ public void perspectiveChangedTo(Perspective perspective) { if (getSelectedTutorial() != null) { // the user has opened a tutorial, ensure that the tutorial browser is // displayed - SwingTools.invokeLater(new Runnable() { - - @Override - public void run() { - DockingTools.openDockable(TutorialBrowser.TUTORIAL_BROWSER_DOCK_KEY, null, - TutorialBrowser.POSITION); - } - }); + SwingTools.invokeLater(() -> DockingTools.openDockable(TutorialBrowser.TUTORIAL_BROWSER_DOCK_KEY, null, + TutorialBrowser.POSITION)); } else { // no tutorial selected, ensure that no tutorial browser is displayed closeAllTutorialBrowsers(); @@ -250,10 +244,12 @@ public void setSelectedTutorial(Tutorial selectedTutorial) { */ private void closeAllTutorialBrowsers() { DockableState state = DockingTools.getDockableState(TutorialBrowser.TUTORIAL_BROWSER_DOCK_KEY); - if (state != null) { - Dockable browser = state.getDockable(); - mainFrame.getDockingDesktop().close(browser); - mainFrame.getPerspectiveController().removeFromInvisiblePerspectives(browser); + if (state != null && !state.isClosed()) { + SwingTools.invokeLater(() -> { + Dockable browser = state.getDockable(); + mainFrame.getDockingDesktop().close(browser); + mainFrame.getPerspectiveController().removeFromInvisiblePerspectives(browser); + }); } } } diff --git a/src/main/java/de/dfki/madm/operator/KMeanspp.java b/src/main/java/de/dfki/madm/operator/KMeanspp.java index 514eef0fc..bdca4d123 100644 --- a/src/main/java/de/dfki/madm/operator/KMeanspp.java +++ b/src/main/java/de/dfki/madm/operator/KMeanspp.java @@ -20,8 +20,10 @@ import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; +import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorVersion; import com.rapidminer.operator.ProcessStoppedException; import com.rapidminer.operator.clustering.ClusterModel; import com.rapidminer.operator.clustering.clusterer.RMAbstractClusterer; @@ -30,44 +32,82 @@ /** - * This algorithm is the first part of K-Means++ descried in the paper "k-means++: The Advantages of - * Careful Seeding" by David Arther and Sergei Vassilvitskii + * This algorithm is the first part of K-Means++ described in the paper "k-means++: The Advantages of + * Careful Seeding" by David Arthur and Sergei Vassilvitskii * * @author Patrick Kalka - * */ public class KMeanspp extends RMAbstractClusterer { - /** Short description for GUI */ + /** + * Short description for GUI + */ public static final String SHORT_DESCRIPTION = "Determine the first k centroids using the K-Means++ heuristic described in \"k-means++: The Advantages of Careful Seeding\" by David Arthur and Sergei Vassilvitskii 2007"; - /** Label for button */ + /** + * Label for button + */ public static final String PARAMETER_USE_KPP = "determine_good_start_values"; - /** ExampleSet to work on */ + /** + * KMeans++ (Use good start values) was not working before 9.0.2 + */ + public static final OperatorVersion VERSION_KPP_NOT_WORKING = new OperatorVersion(9, 0, 1); + + /** + * the calling operator + */ + private Operator caller = this; + + /** + * ExampleSet to work on + */ private ExampleSet exampleSet = null; - /** DistanceMeasure to use */ + /** + * DistanceMeasure to use + */ private DistanceMeasure measure = null; private RandomGenerator generator = null; private int examplesize = -1; private int minK = 0; + /** + * Initialization of K-Means++ + * + * @param parent + * The calling operator + * @param anz + * Initial Cluster count + * @param es + * ExampleSet to work on + * @param measure + * DistanceMeasure to use + * @throws OperatorException + */ + public KMeanspp(Operator parent, int anz, ExampleSet es, DistanceMeasure measure, + RandomGenerator generator) throws OperatorException { + this(parent.getOperatorDescription(), anz, es, measure, generator); + caller = parent; + } + /** * Initialization of K-Means++ * * @param description * @param anz - * initial Cluster count + * initial Cluster count * @param es - * ExampleSet to work on + * ExampleSet to work on * @param measure - * DistanceMeasure to use + * DistanceMeasure to use * @throws OperatorException + * @deprecated use {@link KMeanspp(Operator,int,ExampleSet,DistanceMeasure,RandomGenerator) instead */ + @Deprecated public KMeanspp(OperatorDescription description, int anz, ExampleSet es, DistanceMeasure measure, - RandomGenerator generator) throws OperatorException { + RandomGenerator generator) throws OperatorException { super(description); this.minK = anz; @@ -84,6 +124,7 @@ public KMeanspp(OperatorDescription description, int anz, ExampleSet es, Distanc * @throws ProcessStoppedException */ public int[] getStart() throws ProcessStoppedException { + boolean additionalCheckForPossibleInfiniteLoop = caller.getCompatibilityLevel().isAbove(VERSION_KPP_NOT_WORKING); int[] ret = new int[minK]; int i = 0; int anz = 0; @@ -96,23 +137,22 @@ public int[] getStart() throws ProcessStoppedException { } while (anz < minK) { - boolean again = false; - checkForStop(); + caller.checkForStop(); do { - checkForStop(); - again = false; + caller.checkForStop(); double[] shortest = new double[examplesize]; - double maxProb = 0; - int maxPorbId = -1; + double maxProb = -1; + int maxProbId = -1; double distSum = 0; - // sum of shortest path between chosen centroids an all Points + // sum of shortest path between chosen centroids and all Points for (int j = 0; j < examplesize; j++) { double minDist = -1; Example ex = exampleSet.getExample(j); for (Integer id : ret) { double dist = measure.calculateDistance(ex, exampleSet.getExample(id)); - if (minDist == -1 || minDist > dist) { + // if the distance can not be calculated it returns NaN + if (!Double.isNaN(dist) && (minDist < 0 || minDist > dist)) { minDist = dist; } } @@ -123,19 +163,17 @@ public int[] getStart() throws ProcessStoppedException { // get maximal Probability for (int j = 0; j < examplesize; j++) { double prob = Math.pow(shortest[j], 2) / Math.pow(distSum, 2); - if (prob > maxProb) { - maxPorbId = j; - maxProb = prob; + // 0/0 = Double.NaN + if (Double.isNaN(prob)) { + prob = 0; } - } - - i = maxPorbId; - for (Integer id : ret) { - if (id == i) { - again = true; + if (prob > maxProb && (!additionalCheckForPossibleInfiniteLoop || !contains(ret, j, anz))) { + maxProbId = j; + maxProb = prob; } } - } while (again); + i = maxProbId; + } while (contains(ret, i, anz)); ret[anz] = i; anz++; } @@ -143,6 +181,26 @@ public int[] getStart() throws ProcessStoppedException { return ret; } + /** + * Check if the parameter searchValue is an element of the ins array. Only check the first elements up to maxIndex - 1 + * + * @param ints + * array of int elements to be checked for containment of the searchValue parameter + * @param searchValue + * check if this element exists in the ints array + * @param maxIndex + * check only the elements 0..maxIndex of the ints array + * @return true if searchValue was found, false if searchValue was not found in the ints array + */ + private static boolean contains(int[] ints, int searchValue, int maxIndex) { + for (int i = 0; i < Math.min(maxIndex, ints.length); i++) { + if (ints[i] == searchValue) { + return true; + } + } + return false; + } + @Override protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throws OperatorException { return null; diff --git a/src/main/java/de/dfki/madm/operator/clustering/XMeansCore.java b/src/main/java/de/dfki/madm/operator/clustering/XMeansCore.java index 08f77194b..51ea2ce9a 100644 --- a/src/main/java/de/dfki/madm/operator/clustering/XMeansCore.java +++ b/src/main/java/de/dfki/madm/operator/clustering/XMeansCore.java @@ -1,439 +1,452 @@ -/** - * Copyright (C) 2001-2018 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 de.dfki.madm.operator.clustering; - -import java.util.ArrayList; - -import com.rapidminer.example.Attribute; -import com.rapidminer.example.Attributes; -import com.rapidminer.example.Example; -import com.rapidminer.example.ExampleSet; -import com.rapidminer.example.Tools; -import com.rapidminer.example.set.SplittedExampleSet; -import com.rapidminer.operator.Operator; -import com.rapidminer.operator.OperatorDescription; -import com.rapidminer.operator.OperatorException; -import com.rapidminer.operator.OperatorProgress; -import com.rapidminer.operator.ProcessStoppedException; -import com.rapidminer.operator.UserError; -import com.rapidminer.operator.clustering.Centroid; -import com.rapidminer.operator.clustering.CentroidClusterModel; -import com.rapidminer.operator.clustering.Cluster; -import com.rapidminer.operator.clustering.ClusterModel; -import com.rapidminer.operator.clustering.clusterer.FastKMeans; -import com.rapidminer.operator.clustering.clusterer.KMeans; -import com.rapidminer.operator.clustering.clusterer.RMAbstractClusterer; -import com.rapidminer.tools.RandomGenerator; -import com.rapidminer.tools.math.similarity.DistanceMeasure; - -import de.dfki.madm.operator.KMeanspp; - - -public class XMeansCore extends RMAbstractClusterer { - - private static final int INTERMEDIATE_PROGRESS = 20; - - private ExampleSet exampleSet = null; - private int examplesize = -1; - private DistanceMeasure measure = null; - private int k_min = -1; - private int k_max = -1; - private boolean kpp = false; - private int maxOptimizationSteps = -1; - private int maxRuns = -1; - private OperatorDescription description = null; - private Attributes attributes = null; - private int dimension = -1; - private int[] centroidAssignments = null; - private String ClusteringAlgorithm = ""; - private Operator executingOperator = null; - - /** - * Initialization of X-Mean - * - * @param eSet - * ExamleSet to cluster - * @param k_min - * minimal number of cluster - * @param k_max - * maximal number of cluster - * @param kpp - * using K++-Algorithem to determin the first centroids - * @param maxOptimizationSteps - * maximal optimationsteps of k-Means - * @param maxRuns - * The maximal number of runs of k-Means with random initialization that are - * performed. - * @param description - * @param measure - * MeasureType to use - * @param cluster_alg - * Clustering Algorithm to use - */ - public XMeansCore(ExampleSet eSet, int k_min, int k_max, boolean kpp, int maxOptimizationSteps, int maxRuns, - OperatorDescription description, DistanceMeasure measure, String cluster_alg) { - super(description); - - this.exampleSet = eSet; - this.measure = measure; - this.k_max = k_max; - this.k_min = k_min; - this.kpp = kpp; - this.maxOptimizationSteps = maxOptimizationSteps; - this.maxRuns = maxRuns; - this.description = description; - this.centroidAssignments = new int[exampleSet.size()]; - this.ClusteringAlgorithm = cluster_alg; - } - - /** - * Running X-Means Algorithm - * - * @return Clustered Model - * @throws OperatorException - */ - public ClusterModel doXMean() throws OperatorException { - - examplesize = exampleSet.size(); - - measure.init(exampleSet); - - // checking and creating ids if necessary - Tools.checkAndCreateIds(exampleSet); - - // additional checks - Tools.onlyNonMissingValues(exampleSet, getOperatorClassName(), this, new String[0]); - if (exampleSet.size() < k_min) { - throw new UserError(this, 142, k_min); - } - - // extracting attribute names - attributes = exampleSet.getAttributes(); - ArrayList attributeNames = new ArrayList(attributes.size()); - for (Attribute attribute : attributes) { - attributeNames.add(attribute.getName()); - } - - CentroidClusterModel bestModel = null; - - RMAbstractClusterer KMean = null; - - // get the Clustering Algorithm - if (this.ClusteringAlgorithm.equals("FastKMeans")) { - KMean = new FastKMeans(description); - ((FastKMeans) KMean).setPresetMeasure(measure); - } else if (this.ClusteringAlgorithm.equals("KMeans")) { - KMean = new KMeans(description); - ((KMeans) KMean).setPresetMeasure(measure); - } else { - throw new OperatorException("Unknown kmeans algorithm: " + ClusteringAlgorithm); - } - - // Set Parameters for Clustering Algorithm - KMean.setParameter("k", k_min + ""); - KMean.setParameter("max_runs", maxRuns + ""); - KMean.setParameter("max_optimization_steps", maxOptimizationSteps + ""); - KMean.setParameter(KMeanspp.PARAMETER_USE_KPP, kpp + ""); - if (executingOperator != null - && executingOperator.getParameterAsBoolean(RandomGenerator.PARAMETER_USE_LOCAL_RANDOM_SEED)) { - KMean.setParameter(RandomGenerator.PARAMETER_USE_LOCAL_RANDOM_SEED, Boolean.toString(true)); - KMean.setParameter(RandomGenerator.PARAMETER_LOCAL_RANDOM_SEED, - executingOperator.getParameter(RandomGenerator.PARAMETER_LOCAL_RANDOM_SEED)); - } - - // initialize progress - OperatorProgress operatorProgress = null; - if (executingOperator != null && executingOperator.getProgress() != null) { - operatorProgress = executingOperator.getProgress(); - operatorProgress.setTotal(100); - } - - // get the first run - bestModel = (CentroidClusterModel) KMean.generateClusterModel(exampleSet); - if (operatorProgress != null) { - operatorProgress.setCompleted(INTERMEDIATE_PROGRESS); - } - - // save Dimension of data - dimension = bestModel.getCentroid(0).getCentroid().length; - - // calculate first BIC - double current_m_BIC = this.calcBIC(bestModel); - - boolean change = true; - - boolean addAsLabel = addsLabelAttribute(); - boolean removeUnlabeled = getParameterAsBoolean(RMAbstractClusterer.PARAMETER_REMOVE_UNLABELED); - - while (bestModel.getCentroids().size() < k_max && change) { - change = false; - int array_size = bestModel.getClusters().size(); - - CentroidClusterModel[] Children = new CentroidClusterModel[array_size]; - CentroidClusterModel[] Parent = new CentroidClusterModel[array_size]; - SplittedExampleSet splittedSet = SplittedExampleSet.splitByAttribute(exampleSet, - exampleSet.getAttributes().get("cluster")); - - if (splittedSet.getNumberOfSubsets() < array_size) { - break; - } - int anz = 0; - - // get all Child-cluster - for (@SuppressWarnings("unused") - Cluster cl : bestModel.getClusters()) { - splittedSet.selectSingleSubset(anz); - - KMean.setParameter("k", 2 + ""); - Children[anz] = (CentroidClusterModel) KMean.generateClusterModel(splittedSet); - KMean.setParameter("k", 1 + ""); - Parent[anz] = (CentroidClusterModel) KMean.generateClusterModel(splittedSet); - anz++; - } - - Double[] SaveDiffBic = new Double[array_size]; - boolean[] takeChange = new boolean[array_size]; - int change_anz = 0; - // check which Children to take - for (int i = 0; i < Parent.length; i++) { - double BICc = calcBIC(Children[i]); - double BICp = calcBIC(Parent[i]); - if (BICc > BICp) { - // take Children - takeChange[i] = true; - SaveDiffBic[i] = BICc - BICp; - change_anz++; - } else { - takeChange[i] = false; - } - } - - CentroidClusterModel model = null; - if (change_anz + array_size < k_max) { - // all children are in the limit - model = new CentroidClusterModel(exampleSet, change_anz + array_size, attributeNames, measure, addAsLabel, - removeUnlabeled); - - int id = 0; - for (int i = 0; i < array_size; i++) { - if (takeChange[i]) { - for (Centroid z : Children[i].getCentroids()) { - model.assignExample(id, z.getCentroid()); - id++; - } - } else { - model.assignExample(id, Parent[i].getCentroid(0).getCentroid()); - id++; - } - } - } else { - // pick the best children - model = new CentroidClusterModel(exampleSet, k_max, attributeNames, measure, addAsLabel, removeUnlabeled); - double hilf = 0; - CentroidClusterModel hilf2 = null; - // sort - for (int i = 0; i < takeChange.length - 1; i++) { - for (int j = i + 1; j < takeChange.length; j++) { - if (SaveDiffBic[j] > SaveDiffBic[i]) { - hilf = SaveDiffBic[j]; - SaveDiffBic[j] = SaveDiffBic[i]; - SaveDiffBic[i] = hilf; - - hilf2 = Children[j]; - Children[j] = Children[i]; - Children[i] = hilf2; - - hilf2 = Parent[j]; - Parent[j] = Parent[i]; - Parent[i] = hilf2; - } - } - } - - int id = 0; - int anz1 = 0; - for (int i = 0; i < array_size; i++) { - if (takeChange[i]) { - for (Centroid z : Children[i].getCentroids()) { - model.assignExample(id, z.getCentroid()); - id++; - anz1++; - } - } else { - model.assignExample(id, Parent[i].getCentroid(0).getCentroid()); - id++; - anz1++; - } - if (anz1 >= k_max) { - break; - } - } - } - - model.finishAssign(); - - model = this.assinePoints(model); - - double new_m_BIC = calcBIC(model); - - // check if the new BIC is better than the old - if (new_m_BIC > current_m_BIC) { - change = true; - bestModel = model; - current_m_BIC = new_m_BIC; - } else { - model = null; - } - - if (operatorProgress != null) { - if (bestModel.getCentroids().size() > k_max) { - operatorProgress.complete(); - } else { - operatorProgress.setCompleted((int) (INTERMEDIATE_PROGRESS - + (100.0 - INTERMEDIATE_PROGRESS) * bestModel.getCentroids().size() / k_max)); - } - } - } - - if (addsClusterAttribute()) { - addClusterAssignments(exampleSet, centroidAssignments); - } - - if (operatorProgress != null) { - operatorProgress.complete(); - } - - return bestModel; - } - - /** - * assign the Points to cluster - * - * @param model - * @return - */ - private CentroidClusterModel assinePoints(CentroidClusterModel model) { - double[] values = new double[attributes.size()]; - int i = 0; - for (Example example : exampleSet) { - double[] exampleValues = getAsDoubleArray(example, attributes, values); - double nearestDistance = measure.calculateDistance(model.getCentroidCoordinates(0), exampleValues); - int nearestIndex = 0; - int id = 0; - for (Centroid cr : model.getCentroids()) { - double distance = measure.calculateDistance(cr.getCentroid(), exampleValues); - if (distance < nearestDistance) { - nearestDistance = distance; - nearestIndex = id; - } - id++; - } - centroidAssignments[i] = nearestIndex; - i++; - } - - model.setClusterAssignments(centroidAssignments, exampleSet); - return model; - } - - /** - * Calculate the BIC like in the paper by Dan Pelleg and Andrew Moore - * - * @param bestModel - * @return BIC of the given modell - * @throws ProcessStoppedException - */ - private double calcBIC(CentroidClusterModel bestModel) throws ProcessStoppedException { - double loglike = 0; - int numCenters = bestModel.getNumberOfClusters(); - int numDimensions = bestModel.getCentroidCoordinates(0).length; - - int numParameters = numCenters - 1 + // probabilities - numCenters * numDimensions + // means - numCenters; // variance params - - for (Cluster c : bestModel.getClusters()) { - int current_id = c.getClusterId(); - loglike += logLikelihoodEstimate(c, bestModel.getCentroidCoordinates(current_id), numCenters); - } - - loglike -= numParameters / 2.0 * Math.log(examplesize); - return loglike; - } - - private double[] getAsDoubleArray(Example example, Attributes attributes, double[] values) { - int i = 0; - for (Attribute attribute : attributes) { - values[i] = example.getValue(attribute); - i++; - } - return values; - } - - private double logLikelihoodEstimate(Cluster c, double[] centroid, int K) { - double l = 0; - double R = examplesize; - double Rn = c.getNumberOfExamples(); - double M = dimension; - double d = 0; - double[] values = new double[attributes.size()]; - - if (Rn > 1) { - double sum = 0; - - final Attribute idAttribute = exampleSet.getAttributes().getId(); - boolean idIsNominal = idAttribute.isNominal(); - exampleSet.remapIds(); - for (Object ob : c.getExampleIds()) { - Example example; - if (idIsNominal) { - example = exampleSet.getExampleFromId(idAttribute.getMapping().mapString((String) ob)); - } else { - example = exampleSet.getExampleFromId(((Double) ob).intValue()); - } - if (example == null) { - throw new RuntimeException("Unknown id: " + ob); - } - sum += Math.pow(measure.calculateDistance(centroid, getAsDoubleArray(example, attributes, values)), 2); - } - - d = 1.0 / (Rn - K) * sum; - - l = -(Rn / 2.0) * Math.log(2.0 * Math.PI) - Rn * M / 2.0 * Math.log(d) - (Rn - K) / 2.0 + Rn * Math.log(Rn) - - Rn * Math.log(R); - } - return l; - } - - @Override - protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throws OperatorException { - return null; - } - - /** - * The operator in which XMeans is done. Used to display the progress. - * - * @param executingOperator - * The executing XMeans operator - */ - public void setExecutingOperator(Operator executingOperator) { - this.executingOperator = executingOperator; - } - -} +/** + * Copyright (C) 2001-2018 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 de.dfki.madm.operator.clustering; + +import java.util.ArrayList; + +import com.rapidminer.example.Attribute; +import com.rapidminer.example.Attributes; +import com.rapidminer.example.Example; +import com.rapidminer.example.ExampleSet; +import com.rapidminer.example.Tools; +import com.rapidminer.example.set.SplittedExampleSet; +import com.rapidminer.operator.Operator; +import com.rapidminer.operator.OperatorDescription; +import com.rapidminer.operator.OperatorException; +import com.rapidminer.operator.OperatorProgress; +import com.rapidminer.operator.ProcessStoppedException; +import com.rapidminer.operator.UserError; +import com.rapidminer.operator.clustering.Centroid; +import com.rapidminer.operator.clustering.CentroidClusterModel; +import com.rapidminer.operator.clustering.Cluster; +import com.rapidminer.operator.clustering.ClusterModel; +import com.rapidminer.operator.clustering.clusterer.FastKMeans; +import com.rapidminer.operator.clustering.clusterer.KMeans; +import com.rapidminer.operator.clustering.clusterer.RMAbstractClusterer; +import com.rapidminer.operator.clustering.clusterer.XMeans; +import com.rapidminer.tools.RandomGenerator; +import com.rapidminer.tools.math.similarity.DistanceMeasure; + +import de.dfki.madm.operator.KMeanspp; + + +public class XMeansCore extends RMAbstractClusterer { + + private static final int INTERMEDIATE_PROGRESS = 20; + + private ExampleSet exampleSet = null; + private int examplesize = -1; + private DistanceMeasure measure = null; + private int k_min = -1; + private int k_max = -1; + private boolean kpp = false; + private int maxOptimizationSteps = -1; + private int maxRuns = -1; + private OperatorDescription description = null; + private Attributes attributes = null; + private int dimension = -1; + private int[] centroidAssignments = null; + private String ClusteringAlgorithm = ""; + private Operator executingOperator = null; + + /** + * Initialization of X-Mean + * + * @param eSet + * ExamleSet to cluster + * @param k_min + * minimal number of cluster + * @param k_max + * maximal number of cluster + * @param kpp + * using K++-Algorithem to determin the first centroids + * @param maxOptimizationSteps + * maximal optimationsteps of k-Means + * @param maxRuns + * The maximal number of runs of k-Means with random initialization that are + * performed. + * @param description + * @param measure + * MeasureType to use + * @param cluster_alg + * Clustering Algorithm to use + */ + public XMeansCore(ExampleSet eSet, int k_min, int k_max, boolean kpp, int maxOptimizationSteps, int maxRuns, + OperatorDescription description, DistanceMeasure measure, String cluster_alg) { + super(description); + + this.exampleSet = eSet; + this.measure = measure; + this.k_max = k_max; + this.k_min = k_min; + this.kpp = kpp; + this.maxOptimizationSteps = maxOptimizationSteps; + this.maxRuns = maxRuns; + this.description = description; + this.centroidAssignments = new int[exampleSet.size()]; + this.ClusteringAlgorithm = cluster_alg; + } + + /** + * Running X-Means Algorithm + * + * @return Clustered Model + * @throws OperatorException + */ + public ClusterModel doXMean() throws OperatorException { + + examplesize = exampleSet.size(); + + measure.init(exampleSet); + + // checking and creating ids if necessary + Tools.checkAndCreateIds(exampleSet); + + // additional checks + Tools.onlyNonMissingValues(exampleSet, getOperatorClassName(), this, new String[0]); + if (exampleSet.size() < k_min) { + throw new UserError(this, 142, k_min); + } + + // extracting attribute names + attributes = exampleSet.getAttributes(); + ArrayList attributeNames = new ArrayList(attributes.size()); + for (Attribute attribute : attributes) { + attributeNames.add(attribute.getName()); + } + + CentroidClusterModel bestModel = null; + + RMAbstractClusterer kmean = null; + + // get the Clustering Algorithm + if (this.ClusteringAlgorithm.equals("FastKMeans")) { + kmean = new FastKMeans(description); + ((FastKMeans) kmean).setPresetMeasure(measure); + } else if (this.ClusteringAlgorithm.equals("KMeans")) { + kmean = new KMeans(description); + ((KMeans) kmean).setPresetMeasure(measure); + } else { + throw new OperatorException("Unknown kmeans algorithm: " + ClusteringAlgorithm); + } + + // Set Parameters for Clustering Algorithm + kmean.setParameter("k", k_min + ""); + kmean.setParameter("max_runs", maxRuns + ""); + kmean.setParameter("max_optimization_steps", maxOptimizationSteps + ""); + kmean.setParameter(KMeanspp.PARAMETER_USE_KPP, kpp + ""); + if (executingOperator != null + && executingOperator.getParameterAsBoolean(RandomGenerator.PARAMETER_USE_LOCAL_RANDOM_SEED)) { + kmean.setParameter(RandomGenerator.PARAMETER_USE_LOCAL_RANDOM_SEED, Boolean.toString(true)); + kmean.setParameter(RandomGenerator.PARAMETER_LOCAL_RANDOM_SEED, + executingOperator.getParameter(RandomGenerator.PARAMETER_LOCAL_RANDOM_SEED)); + } + + if (this.getCompatibilityLevel().isAbove(XMeans.VERSION_9_0_0_LABEL_ROLE_BUG)) { + kmean.setParameter(RMAbstractClusterer.PARAMETER_ADD_CLUSTER_ATTRIBUTE, "false"); + } + kmean.setCompatibilityLevel(getCompatibilityLevel()); + + // initialize progress + OperatorProgress operatorProgress = null; + if (executingOperator != null && executingOperator.getProgress() != null) { + operatorProgress = executingOperator.getProgress(); + operatorProgress.setTotal(100); + } + + // get the first run + bestModel = (CentroidClusterModel) kmean.generateClusterModel(exampleSet); + if (operatorProgress != null) { + operatorProgress.setCompleted(INTERMEDIATE_PROGRESS); + } + + // save Dimension of data + dimension = bestModel.getCentroid(0).getCentroid().length; + + // calculate first BIC + double current_m_BIC = this.calcBIC(bestModel); + + boolean change = true; + + boolean addAsLabel = addsLabelAttribute(); + boolean removeUnlabeled = getParameterAsBoolean(RMAbstractClusterer.PARAMETER_REMOVE_UNLABELED); + + while (bestModel.getCentroids().size() < k_max && change) { + change = false; + int array_size = bestModel.getClusters().size(); + + CentroidClusterModel[] Children = new CentroidClusterModel[array_size]; + CentroidClusterModel[] Parent = new CentroidClusterModel[array_size]; + SplittedExampleSet splittedSet = SplittedExampleSet.splitByAttribute(exampleSet, + exampleSet.getAttributes().get("cluster")); + + if (splittedSet.getNumberOfSubsets() < array_size) { + break; + } + int anz = 0; + + // get all Child-cluster + for (@SuppressWarnings("unused") + Cluster cl : bestModel.getClusters()) { + splittedSet.selectSingleSubset(anz); + + kmean.setParameter("k", 2 + ""); + Children[anz] = (CentroidClusterModel) kmean.generateClusterModel(splittedSet); + kmean.setParameter("k", 1 + ""); + Parent[anz] = (CentroidClusterModel) kmean.generateClusterModel(splittedSet); + anz++; + } + + Double[] SaveDiffBic = new Double[array_size]; + boolean[] takeChange = new boolean[array_size]; + int change_anz = 0; + // check which Children to take + for (int i = 0; i < Parent.length; i++) { + double BICc = calcBIC(Children[i]); + double BICp = calcBIC(Parent[i]); + if (BICc > BICp) { + // take Children + takeChange[i] = true; + SaveDiffBic[i] = BICc - BICp; + change_anz++; + } else { + takeChange[i] = false; + } + } + + CentroidClusterModel model = null; + if (change_anz + array_size < k_max) { + // all children are in the limit + model = new CentroidClusterModel(exampleSet, change_anz + array_size, attributeNames, measure, addAsLabel, + removeUnlabeled); + + int id = 0; + for (int i = 0; i < array_size; i++) { + if (takeChange[i]) { + for (Centroid z : Children[i].getCentroids()) { + model.assignExample(id, z.getCentroid()); + id++; + } + } else { + model.assignExample(id, Parent[i].getCentroid(0).getCentroid()); + id++; + } + } + } else { + // pick the best children + model = new CentroidClusterModel(exampleSet, k_max, attributeNames, measure, addAsLabel, removeUnlabeled); + double hilf = 0; + CentroidClusterModel hilf2 = null; + // sort + for (int i = 0; i < takeChange.length - 1; i++) { + for (int j = i + 1; j < takeChange.length; j++) { + if (SaveDiffBic[j] > SaveDiffBic[i]) { + hilf = SaveDiffBic[j]; + SaveDiffBic[j] = SaveDiffBic[i]; + SaveDiffBic[i] = hilf; + + hilf2 = Children[j]; + Children[j] = Children[i]; + Children[i] = hilf2; + + hilf2 = Parent[j]; + Parent[j] = Parent[i]; + Parent[i] = hilf2; + } + } + } + + int id = 0; + int anz1 = 0; + for (int i = 0; i < array_size; i++) { + if (takeChange[i]) { + for (Centroid z : Children[i].getCentroids()) { + model.assignExample(id, z.getCentroid()); + id++; + anz1++; + } + } else { + model.assignExample(id, Parent[i].getCentroid(0).getCentroid()); + id++; + anz1++; + } + if (anz1 >= k_max) { + break; + } + } + } + + model.finishAssign(); + + model = this.assinePoints(model); + + double new_m_BIC = calcBIC(model); + + // check if the new BIC is better than the old + if (new_m_BIC > current_m_BIC) { + change = true; + bestModel = model; + current_m_BIC = new_m_BIC; + } else { + model = null; + } + + if (operatorProgress != null) { + if (bestModel.getCentroids().size() > k_max) { + operatorProgress.complete(); + } else { + operatorProgress.setCompleted((int) (INTERMEDIATE_PROGRESS + + (100.0 - INTERMEDIATE_PROGRESS) * bestModel.getCentroids().size() / k_max)); + } + } + } + + if (getCompatibilityLevel().isAbove(XMeans.VERSION_9_0_0_LABEL_ROLE_BUG) && getCompatibilityLevel().isAtMost(XMeans.VERSION_9_1_0_POINTS_COUNTED_TWICE_BUG)) { + bestModel = assinePoints(bestModel); + } + + if (addsClusterAttribute()) { + if (getCompatibilityLevel().isAbove(XMeans.VERSION_9_1_0_POINTS_COUNTED_TWICE_BUG)) { + centroidAssignments = bestModel.getClusterAssignments(exampleSet); + } + addClusterAssignments(exampleSet, centroidAssignments); + } + + if (operatorProgress != null) { + operatorProgress.complete(); + } + + return bestModel; + } + + /** + * assign the Points to cluster + * + * @param model + * @return + */ + private CentroidClusterModel assinePoints(CentroidClusterModel model) { + double[] values = new double[attributes.size()]; + int i = 0; + for (Example example : exampleSet) { + double[] exampleValues = getAsDoubleArray(example, attributes, values); + double nearestDistance = measure.calculateDistance(model.getCentroidCoordinates(0), exampleValues); + int nearestIndex = 0; + int id = 0; + for (Centroid cr : model.getCentroids()) { + double distance = measure.calculateDistance(cr.getCentroid(), exampleValues); + if (distance < nearestDistance) { + nearestDistance = distance; + nearestIndex = id; + } + id++; + } + centroidAssignments[i] = nearestIndex; + i++; + } + + model.setClusterAssignments(centroidAssignments, exampleSet); + return model; + } + + /** + * Calculate the BIC like in the paper by Dan Pelleg and Andrew Moore + * + * @param bestModel + * @return BIC of the given modell + * @throws ProcessStoppedException + */ + private double calcBIC(CentroidClusterModel bestModel) throws ProcessStoppedException { + double loglike = 0; + int numCenters = bestModel.getNumberOfClusters(); + int numDimensions = bestModel.getCentroidCoordinates(0).length; + + int numParameters = numCenters - 1 + // probabilities + numCenters * numDimensions + // means + numCenters; // variance params + + for (Cluster c : bestModel.getClusters()) { + int current_id = c.getClusterId(); + loglike += logLikelihoodEstimate(c, bestModel.getCentroidCoordinates(current_id), numCenters); + } + + loglike -= numParameters / 2.0 * Math.log(examplesize); + return loglike; + } + + private double[] getAsDoubleArray(Example example, Attributes attributes, double[] values) { + int i = 0; + for (Attribute attribute : attributes) { + values[i] = example.getValue(attribute); + i++; + } + return values; + } + + private double logLikelihoodEstimate(Cluster c, double[] centroid, int K) { + double l = 0; + double R = examplesize; + double Rn = c.getNumberOfExamples(); + double M = dimension; + double d = 0; + double[] values = new double[attributes.size()]; + + if (Rn > 1) { + double sum = 0; + + final Attribute idAttribute = exampleSet.getAttributes().getId(); + boolean idIsNominal = idAttribute.isNominal(); + exampleSet.remapIds(); + for (Object ob : c.getExampleIds()) { + Example example; + if (idIsNominal) { + example = exampleSet.getExampleFromId(idAttribute.getMapping().mapString((String) ob)); + } else { + example = exampleSet.getExampleFromId(((Double) ob).intValue()); + } + if (example == null) { + throw new RuntimeException("Unknown id: " + ob); + } + sum += Math.pow(measure.calculateDistance(centroid, getAsDoubleArray(example, attributes, values)), 2); + } + + d = 1.0 / (Rn - K) * sum; + + l = -(Rn / 2.0) * Math.log(2.0 * Math.PI) - Rn * M / 2.0 * Math.log(d) - (Rn - K) / 2.0 + Rn * Math.log(Rn) + - Rn * Math.log(R); + } + return l; + } + + @Override + protected ClusterModel generateInternalClusterModel(ExampleSet exampleSet) throws OperatorException { + return null; + } + + /** + * The operator in which XMeans is done. Used to display the progress. + * + * @param executingOperator + * The executing XMeans operator + */ + public void setExecutingOperator(Operator executingOperator) { + this.executingOperator = executingOperator; + } + +} diff --git a/src/main/resources/com/rapidminer/resources/OperatorsCore.xml b/src/main/resources/com/rapidminer/resources/OperatorsCore.xml index 68e8a5625..20993d6c2 100644 --- a/src/main/resources/com/rapidminer/resources/OperatorsCore.xml +++ b/src/main/resources/com/rapidminer/resources/OperatorsCore.xml @@ -151,6 +151,13 @@ com.rapidminer.operator.features.transformation.FourierTransform FourierTransform + + 9.1 + pivot + com.rapidminer.operator.preprocessing.transformation.Example2AttributePivoting + + Example2AttributePivoting + @@ -616,12 +623,6 @@ table_refresh.png - - pivot - com.rapidminer.operator.preprocessing.transformation.Example2AttributePivoting - - Example2AttributePivoting - de_pivot com.rapidminer.operator.preprocessing.transformation.Attribute2ExamplePivoting diff --git a/src/main/resources/com/rapidminer/resources/i18n/Errors.properties b/src/main/resources/com/rapidminer/resources/i18n/Errors.properties index d6c0cf7e7..cc951705a 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/Errors.properties +++ b/src/main/resources/com/rapidminer/resources/i18n/Errors.properties @@ -212,6 +212,7 @@ repository.error.check_connection.no_password = Password is empty repository.error.check_connection.unknown_host = Unknown host ''{0}'' repository.error.check_connection.connect_error = Could not connect to ''{0}'' +check_connection.certificate_error = {0}

    Learn how to trust a self-signed SSL certificate in RapidMiner Studio. import.excel.excel_file_broken = The Excel file is broken and could not be read. export.excel.excel_xls_file_exceeds_column_limit = Excel .xls files only support up to 256 attributes diff --git a/src/main/resources/com/rapidminer/resources/i18n/Errors_de.properties b/src/main/resources/com/rapidminer/resources/i18n/Errors_de.properties deleted file mode 100644 index a83a653cb..000000000 --- a/src/main/resources/com/rapidminer/resources/i18n/Errors_de.properties +++ /dev/null @@ -1,8 +0,0 @@ -metadata.quickfix.connect_to = Mit {0} verbinden. -metadata.quickfix.add_compatible = Operator einfügen, der {0} erzeugt... -metadata.quickfix.disconnect = Trenne {0} von {1} - -metadata.error.input_missing = Benötigte Eingabe am Port {0} fehlt. -metadata.error.expected = Erwarte {0}, aber erhalte {1}. - - \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/i18n/GUI.properties b/src/main/resources/com/rapidminer/resources/i18n/GUI.properties index 9020ce78b..ced8c0e0c 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/GUI.properties +++ b/src/main/resources/com/rapidminer/resources/i18n/GUI.properties @@ -26,7 +26,7 @@ gui.dockkey.overview.tip = Overview: Overview of the process view.< gui.dockkey.repository_browser.name = Repository gui.dockkey.repository_browser.short = Manage your data and processes. gui.dockkey.repository_browser.icon = data.png -gui.dockkey.repository_browser.tip = Repository: The place where your data and processes are stored, either locally or remotely. Best practice suggests reading your data from a repository instead of reading directly from a file or database.
    Also known as: folder, workspace, project +gui.dockkey.repository_browser.tip = Repository: The place where your data, processes, and results are stored, either locally or remotely. Also known as: folder, workspace, project gui.dockkey.operator_tree.name = Tree gui.dockkey.operator_tree.short = A tree representation of your process. @@ -147,6 +147,8 @@ gui.action.workspace_user.tip = Switch to view {0}. gui.label.workspace_views.label = Views: gui.label.workspace_more = More +gui.label.dockable.unclosable.tip = That panel is the entire reason the current View exists. Closing it here is not possible. + gui.dialog.confirm.delete_perspective.title = Delete View gui.dialog.confirm.delete_perspective.message = Are you sure you want to delete the view {0}? @@ -1408,6 +1410,9 @@ gui.label.preferences.setting_enforced.label = gui.label.preferences.setting_enforced.tip = This setting has been enforced by your system administrator. gui.label.preferences.setting_enforced.icon = 16/lock.png +gui.label.datatable.too_many_rows.label = There are more rows in the ExampleSet than displayed here. +gui.label.datatable.too_many_rows.icon = sign_warning.png + ###### VIEW ################ gui.action.menu.view.label = View @@ -1633,6 +1638,8 @@ gui.label.compatibility_level.label = Compatibility level gui.label.compatibility_level.mne = L gui.label.compatibility_level.tip = The compatibility level specifies the behaviour of which RapidMiner Studio or extension version should be emulated. If the behaviour of operators changes over time, you can always go back to older versions. Saved with the process. gui.label.operator_pararameters.help_icon = information_faint.png +gui.label.propertyPanel.no_parameters.label = No parameters to display. +gui.label.propertyPanel.no_parameters.icon = information.png # XMLEditor gui.action.xml_editor.apply_changes.label = Apply @@ -2679,6 +2686,8 @@ gui.dialog.error.update_md5_error.message = The downloaded package {0} was corru gui.dialog.error.no_update_md5.message = Error while comparing check sums please try to download the updates again. gui.dialog.error.updatemanager.updates_installed_partially.title=Update complete gui.dialog.error.updatemanager.updates_installed_partially.message={0} of {1} updates were installed. +gui.dialog.error.updatemanager.update_failed.title = Update failed +gui.dialog.error.updatemanager.update_failed.message = None of the {1} updates were installed. gui.dialog.error.updatemanager.unknown_package_type.title = Unknown package type gui.dialog.error.updatemanager.unknown_package_type.message = The selected package {0} is of an unknown type ({1}) and will be skipped. @@ -4183,7 +4192,16 @@ gui.label.meta_data_stats.headers.missing.label = Missing gui.label.meta_data_stats.headers.missing.tip = Click to sort via the number of missing values. gui.label.meta_data_stats.headers.stats.label = Statistics +gui.label.data_view.open_in.label = Open in gui.label.data_view.filter.label = Filter ({0} / {1} examples): +gui.label.data_view.filter.tip = These filters can be used to skip examples in the view fulfilling the filter condition. +gui.label.data_view.filter_result_begin.label = ExampleSet ( +gui.label.data_view.filter_result_example.label = {0} example, +gui.label.data_view.filter_result_examples.label = {0} examples, +gui.label.data_view.filter_result_special.label = {0} special attribute, +gui.label.data_view.filter_result_specials.label = {0} special attributes, +gui.label.data_view.filter_result_regular.label = {0} regular attribute) +gui.label.data_view.filter_result_regulars.label = {0} regular attributes) gui.label.data_view.example_index.tooltip = The position of the example in the (filtered) view on the example table. gui.label.data_view.calc_stats.tooltip = Creating tooltip... @@ -4308,6 +4326,7 @@ gui.progress.repository_delete_entry.label=Deleting data gui.progress.open_file.label=Opening File gui.progress.open_process.label=Opening Process gui.progress.add_repository.label=Adding Repository +gui.progress.configure_repository.label=Configuring Repository {0} gui.progress.creating_display.label=Creating Display gui.progress.create_folder.label=Creating Folder gui.progress.refreshing.label=Refreshing @@ -4333,6 +4352,7 @@ gui.progress.log_in_to_updateserver.label = Logging in to Update Server gui.progress.log_out_frm_updateserver.label = Logging out from Update Server gui.progress.test.rapidanaltics.configuration.label = Trying to connect to RapidMiner Server with new configuration gui.progress.check_connection_settings.label = Trying to connect to RapidMiner Server +gui.progress.wait_for_connection_check.label = Waiting for connection check gui.progress.update_result_statistics.label = Updating Statistics gui.progress.open_remote_file_chooser.label = Opening File Chooser gui.progress.download_licenses.label=Downloading Licenses @@ -4375,6 +4395,8 @@ gui.splash.plugin_gui = Initializing Plugin GUI gui.splash.show_frame = Showing Frame gui.splash.checks = Initializing Checks gui.splash.ready = Ready. +gui.splash.cacerts = Initialize Certificate Trust Store + ######################################## # RapidDocBotImporter @@ -5830,6 +5852,7 @@ gui.progress.io.dataimport.step.data_column_configuration.prepare_data_preview.l gui.progress.io.dataimport.step.data_column_configuration.prepare_preview_table.label = Creating preview table gui.progress.io.dataimport.step.data_column_configuration.update_column.label = Updating column gui.progress.io.dataimport.step.data_column_configuration.update_date_format.label = Updating date format +gui.progress.io.dataimport.step.data_column_configuration.guessing_date_format.label = Guessing date format gui.label.io.dataimport.step.data_column_configuration.loading_preview.label = Loading data preview gui.label.io.dataimport.step.data_column_configuration.loading_preview.icon = 48/hourglass.png @@ -5913,6 +5936,9 @@ gui.label.io.dataimport.step.excel.sheet_selection.use_header_row = Define heade gui.action.io.dataimport.step.excel.sheet_selection.apply_cell_selection.label = Apply gui.action.io.dataimport.step.excel.sheet_selection.select_all.label = Select All +gui.action.io.dataimport.step.data_column_configuration.ignore_errors.label = Ignore errors +gui.action.io.dataimport.step.data_column_configuration.ignore_errors.tip = Replace errors with missing values + gui.bubble.io.dataimport.step.excel.sheet_selection.wrong_cell_format.title = Invalid cell reference gui.bubble.io.dataimport.step.excel.sheet_selection.wrong_cell_format.body = The cell reference ''{0}'' is invalid. Please specify a valid cell reference (e.g. A1:B12 or A:F). diff --git a/src/main/resources/com/rapidminer/resources/i18n/GUI_de.properties b/src/main/resources/com/rapidminer/resources/i18n/GUI_de.properties deleted file mode 100644 index 117c8031f..000000000 --- a/src/main/resources/com/rapidminer/resources/i18n/GUI_de.properties +++ /dev/null @@ -1,3464 +0,0 @@ -############### -## Dockables -############### - -gui.dockkey.remote_process_viewer.name = RapidMiner Server Prozesse -#gui.dockkey.remote_process_viewer.icon = server2_play.png -gui.dockkey.remote_process_viewer.tip = RapidMiner Server Prozesse betrachten und verwalten. - -gui.dockkey.welcome.name = Willkommen -#gui.dockkey.welcome.icon = about.png -gui.dockkey.welcome.tip = Willkommen bei RapidMiner. - -gui.dockkey.overview.name = Übersicht -#gui.dockkey.overview.icon = magnifying_glass.png -gui.dockkey.overview.tip = Übersicht der Prozessansicht. - -gui.dockkey.repository_browser.name = Repository -#gui.dockkey.repository_browser.icon = data.png -gui.dockkey.repository_browser.tip = Die Daten- und Ergebnisrepositories durchsuchen. - -gui.dockkey.operator_tree.name = Baum -#gui.dockkey.operator_tree.icon = text_tree.png -gui.dockkey.operator_tree.tip = Der Operatorenbaum des aktuellen Prozesses. - -gui.dockkey.error_table.name = Probleme -#gui.dockkey.error_table.icon = sign_warning.png -gui.dockkey.error_table.tip = Probleme (Fehler und Warnungen) des aktuellen Prozessaufbaus. - -gui.dockkey.log_viewer.name = Log -#gui.dockkey.log_viewer.icon = document_empty_time.png -gui.dockkey.log_viewer.tip = Konsole mit Logeinträgen. - -gui.dockkey.process_panel.name = Prozess -#gui.dockkey.process_panel.icon = vector_curve_cubic.png -gui.dockkey.process_panel.tip = Bearbeitung des Prozesses in Form eines Graphen. - -gui.dockkey.xml_editor.name = XML -#gui.dockkey.xml_editor.icon = code.png -gui.dockkey.xml_editor.tip = Zeigt den aktuellen Prozessaufbau als XML-code an. - -gui.dockkey.comment_editor.name = Kommentar -#gui.dockkey.comment_editor.icon = document_text.png -gui.dockkey.comment_editor.tip = Zeigt einen Editor zum Kommentieren des ausgewählten Operators an. - -gui.dockkey.property_editor.name = Parameter -#gui.dockkey.property_editor.icon = form_edit.png -gui.dockkey.property_editor.tip = Zeigt die Parameter des ausgewählten Operators an. - - -gui.dockkey.result.name = Ergebnisübersicht -#gui.dockkey.result.icon = presentation_chart.png -gui.dockkey.result.tip = Stellt die aktuellen Ergebnisse des Prozesses dar. - -gui.dockkey.new_operator.name = Operatoren -#gui.dockkey.new_operator.icon = element_new.png -gui.dockkey.new_operator.tip = Zeigt alle Operatoren, die in den Prozess eingefügt werden können. - - -gui.dockkey.operator_help.name = Hilfe -#gui.dockkey.operator_help.icon = lightbulb_on.png -#gui.dockkey.operator_help.icon = question.png -gui.dockkey.operator_help.tip = Stellt einen Hilfetext zum ausgewählten Operator zur Verfügung. - -gui.dockkey.operator_documentation_browser.name = Hilfe -#gui.dockkey.operator_documentation_browser.icon = question.png -gui.dockkey.operator_documentation_browser.tip = Stellt einen Hilfetext zum ausgewählten Operator zur Verfügung. - -gui.dockkey.system_monitor.name = System Monitor -#gui.dockkey.system_monitor.icon = window_oscillograph.png -gui.dockkey.system_monitor.tip = Informiert über den aktuellen Speicherverbrauch. - -gui.dockkey.process_context.name = Kontext -#gui.dockkey.process_context.icon = environment.png -gui.dockkey.process_context.tip = Die Kontexteinstellungen des Prozesses editieren. - -# Toolbars -gui.toolbar.file.tip = Datei -gui.toolbar.edit.tip = Bearbeiten -gui.toolbar.run.tip = Ausführen -gui.toolbar.perspectives.tip = Ansicht - -# Workspace actions -gui.action.workspace_design.label = Erstellung -gui.action.workspace_design.tip = Zur Erstellungsansicht wechseln. -#gui.action.workspace_design.icon = edit.png -#gui.action.workspace_design.acc = F8 -gui.action.workspace_result.label = Ergebnisse -#gui.action.workspace_result.icon = presentation_chart.png -gui.action.workspace_result.tip = Zur Ergebnisansicht wechseln. -#gui.action.workspace_result.acc = F9 -gui.action.workspace_welcome.label = Willkommen -gui.action.workspace_welcome.tip = Zur Willkommensansicht wechseln. -#gui.action.workspace_welcome.icon = about.png -#gui.action.workspace_user.icon = window.png -gui.action.workspace_user.tip = Zur {0}ansicht wechseln. - - -############################################################ -## Actions -############################################################ - -############################ -# WELCOME SCREEN -############################ -gui.action.welcome.new.label = Neuer Prozess -gui.action.welcome.new.tip = Einen neuen Prozess erstellen -#gui.action.welcome.new.icon = document_empty_new.png - -gui.action.welcome.open_recent.label = Öffne zuletzt verwendetden Prozess -gui.action.welcome.open_recent.tip = Öffnet einen der zuletzt verwendeten Prozesse -#gui.action.welcome.open_recent.icon = folder_open_time.png - -gui.action.welcome.open.label = Öffne Prozess -gui.action.welcome.open.tip = Öffnet einen existierenden Prozess -#gui.action.welcome.open.icon = folder_open.png - -gui.action.welcome.wizard.label = Öffne Vorlage -gui.action.welcome.wizard.tip = Öffnet einen Prozess basierend auf einer Vorlage -#gui.action.welcome.wizard.icon = package_new.png - -gui.action.welcome.tutorial.label = Online Tutorial -gui.action.welcome.tutorial.tip = Startet das RapidMiner Online Tutorial -#gui.action.welcome.tutorial.icon = book.png -gui.action.welcome.tour.label = RapidMiner Tour -gui.action.welcome.tour.tip = Startet die Interaktive RapidMiner Tour -#gui.action.welcome.tour.icon = signpost.png - -############################ -# GENERAL PURPOSE -############################ -gui.action.simple_link_action.label = {0} -gui.action.simple_link_action.tip = Öffnet {0} in einem Internetbrowser. - -gui.action.cancel.label = Löschen -gui.action.cancel.tip = Beim Schlieߟen des Fensters werden keine Änderungen gespeichert. -#gui.action.cancel.acc = ESCAPE -gui.action.cancel.mne = C -#gui.action.cancel.icon = delete.png - -gui.action.ok.label = Ok -gui.action.ok.tip = Beim Schlieߟen dieses Fensters werden alle Änderungen gespeichert. -#gui.action.ok.icon = check.png -#gui.action.ok.acc = ENTER # no accelerator, make this the default button - -gui.action.close.label = Abbrechen -gui.action.close.mne = A -gui.action.close.tip = Schlieߟt dieses Fenster. -#gui.action.close.icon = delete.png - -gui.action.previous.label = Zurück -gui.action.previous.mne = Z -gui.action.previous.tip = Zur vorherigen Seite zurückkehren -#gui.action.previous.icon = arrow_left.png - -gui.action.next.label = Weiter -gui.action.next.mne = W -gui.action.next.tip = Zur nächsten Seite gehen. -#gui.action.next.icon = arrow_right.png - -gui.action.finish.label = Beenden -gui.action.finish.mne = B -gui.action.finish.tip = Beendet -#gui.action.finish.icon = signal_flag_checkered.png - -gui.action.dont_ask_again.label = Nicht noch einmal fragen. -gui.action.dont_ask_again.tip = Diese Frage beim nächsten Mal nicht erneut stellen. -gui.action.dont_ask_again.mne = F - -############################ -# FILE CHOOSER -############################ - -gui.dialog.file_chooser.open.title = Öffne Datei -gui.dialog.file_chooser.open.message = Bitte eine Datei zum Öffnen wählen. -#gui.dialog.file_chooser.open.icon = folder_open.png - -gui.dialog.file_chooser.open_directory.title = Verzeichnis wählen -gui.dialog.file_chooser.open_directory.message = Bitte ein Verzeichnis wählen. -#gui.dialog.file_chooser.open_directory.icon = folder_open.png - -gui.dialog.file_chooser.save.title = Speichern -gui.dialog.file_chooser.save.message = Bitte einen Ort und Namen zum Speichern der Datei angeben. -#gui.dialog.file_chooser.save.icon = floppy_disk.png - -gui.dialog.file_chooser.export_pdf.title = Exportieren -gui.dialog.file_chooser.export_pdf.message = Bitte einen Ort und Namen zum Speichern der PDF-Datei angeben. -#gui.dialog.file_chooser.export_pdf.icon = document_empty_out.png - -gui.action.file_chooser.new_folder.label = Neuer Ordner -#gui.action.file_chooser.new_folder.icon = folder_open_new.png -gui.action.file_chooser.new_folder.mne = N -gui.action.file_chooser.new_folder.tip = Einen neuen Ordner erstellen. - -gui.label.file_chooser.bookmarks.label = Lesezeichen - -gui.action.file_chooser.add_to_bookmarks.label = Zu Lesezeichen hinzufügen. -#gui.action.file_chooser.add_to_bookmarks.icon = star_add.png -gui.action.file_chooser.add_to_bookmarks.mne = L -gui.action.file_chooser.add_to_bookmarks.tip = Ordner zu Lesezeichen hinzufügen. - -gui.action.file_chooser.rename_bookmark.label = Lesezeichen umbenennen -#gui.action.file_chooser.rename_bookmark.icon = star_edit.png -gui.action.file_chooser.rename_bookmark.tip = Ausgewähltes Lesezeichen umbenennen. - -gui.action.file_chooser.delete_bookmark.label = Lesezeichen löschen -#gui.action.file_chooser.delete_bookmark.icon = star_delete.png -gui.action.file_chooser.delete_bookmark.tip = Ausgewähltes Lesezeichen löschen. - -gui.action.file_chooser.show_hidden.label = Zeige versteckte Dateien -#gui.action.file_chooser.show_hidden.icon = folder_open_view.png -gui.action.file_chooser.show_hidden.mne = V -gui.action.file_chooser.show_hidden.tip = Zeigt versteckte Dateien an. -#gui.action.file_chooser.show_hidden.acc = - -gui.action.file_chooser.refresh.label = Neu laden -#gui.action.file_chooser.refresh.icon = folder_open_refresh.png -gui.action.file_chooser.refresh.mne = l -gui.action.file_chooser.refresh.tip = Ansicht neu laden. -#gui.action.file_chooser.refresh.acc = F5 - -gui.action.file_chooser.select_all.label = Alles markieren -#gui.action.file_chooser.select_all.icon = folder_open_checkbox_checked.png -gui.action.file_chooser.select_all.mne = m -#gui.action.file_chooser.select_all.acc = control A -gui.action.file_chooser.select_all.tip = Alle Elemente auswählen. - -gui.action.file_chooser.sort_by.label = Sortieren nach -#gui.action.file_chooser.sort_by.icon = sort_up_down_question.png -gui.action.file_chooser.sort_by.mne = S -gui.action.file_chooser.sort_by.tip = Eine Sortierung für die Elemente wählen. - -gui.menu.file_chooser.sort_by.file_name = Datei Name -gui.menu.file_chooser.sort_by.file_type = Datei Format -gui.menu.file_chooser.sort_by.file_size = Datei Gröߟe -gui.menu.file_chooser.sort_by.last_modified = Zuletzt geändert - -gui.action.file_chooser.view.label = Ansicht -#gui.action.file_chooser.view.icon = window_view.png -gui.action.file_chooser.view.mne = A -gui.action.file_chooser.view.tip = Art der Ansicht wählen. - -gui.menu.file_chooser.view.thumbnails.label = Vorschau -gui.menu.file_chooser.view.icons.label = Symbol -gui.menu.file_chooser.view.list.label = Liste -gui.menu.file_chooser.view.details.label = Details - -gui.action.file_chooser.auto_arrange.label = Elemente automatisch anordnen -#gui.action.file_chooser.auto_arrange.icon = layout.png -gui.action.file_chooser.auto_arrange.tip = Elemente werden automatisch geordnet. - -gui.action.file_chooser.change_to_parent_directory.label = Zur übergeordneten Ansicht gehen -#gui.action.file_chooser.change_to_parent_directory.icon = folder_open_up.png -gui.action.file_chooser.change_to_parent_directory.tip = Zur übergeordneten Ansicht gehen. - -gui.action.file_chooser.go_back.label = Zurück -#gui.action.file_chooser.go_back.icon = arrow_left.png -gui.action.file_chooser.go_back.tip = Zum vorherigen Ordner zurückkehren. - -gui.action.file_chooser.go_home.label = Start -#gui.action.file_chooser.go_home.icon = home.png -gui.action.file_chooser.go_home.tip = Zum Startordner gehen. - -gui.action.file_chooser.open.label = Öffnen -#gui.action.file_chooser.open.icon = folder_open.png -gui.action.file_chooser.open.tip = Verzeichnis oder Datei öffnen. - -gui.action.file_chooser.select.label = Wählen -#gui.action.file_chooser.select.icon = folder_open.png - -gui.action.file_chooser.rename.label = Umbenennen -#gui.action.file_chooser.rename.icon = folder_open_edit.png - -gui.action.file_chooser.delete.label = Löschen -#gui.action.file_chooser.delete.icon = folder_open_delete.png - -gui.dialog.input.file_chooser.new_folder.title = Neuer Ordner -#gui.dialog.input.file_chooser.new_folder.icon = folder_open_new.png -gui.dialog.input.file_chooser.new_folder.message = Bitte einen Namen für den neuen Ordner angeben. - -gui.dialog.error.file_chooser.new_folder.rename.title = Ordner erstellen -gui.dialog.error.file_chooser.new_folder.rename.message = Beim Umbenennen des neuen Ordners in {0} trat ein Fehler auf. - -gui.dialog.error.cannot_export_pdf.title = PDF-Export -gui.dialog.error.cannot_export_pdf.message = PDF konnte nicht exportiert werden. - -gui.dialog.error.file_chooser.new_folder.create.title = Ordner erstellen -gui.dialog.error.file_chooser.new_folder.create.message = Der Ordner {0} konnte nicht erstellt werden. - -gui.dialog.input.file_chooser.bookmark_name.title = Lesezeichen erstellen -#gui.dialog.input.file_chooser.bookmark_name.icon = star_add.png -gui.dialog.input.file_chooser.bookmark_name.message = Name für Lesezeichen des Ordners {0} angeben. - -gui.dialog.confirm.file_chooser.delete.title = Löschen -#gui.dialog.confirm.file_chooser.delete.icon = folder_open_delete.png -gui.dialog.confirm.file_chooser.delete.message = Möchten Sie {0} wirklich löschen? - -gui.dialog.confirm.export_pdf.title = Überschreiben -gui.dialog.confirm.export_pdf.message = Datei {0} überschreiben? - -gui.dialog.error.file_chooser.delete.error.title = Löschen -gui.dialog.error.file_chooser.delete.error.message = {0} konnte nicht gelöscht werden. - -gui.dialog.input.file_chooser.rename.title = Umbenennen -#gui.dialog.input.file_chooser.rename.icon = folder_open_edit.png -gui.dialog.input.file_chooser.rename.message = Bitte geben Sie einen neuen Namen für {0} an. - -gui.dialog.error.file_chooser.rename.invalid.title = Umbenennen -gui.dialog.error.file_chooser.rename.invalid.message = Bitte geben Sie einen gültigen Namen an. - -gui.dialog.error.file_chooser.rename.error.title = Umbenennen -gui.dialog.error.file_chooser.rename.error.message = Beim Umbenennen der Datei trat ein Fehler auf. - -gui.dialog.confirm.result.really_close.title = Wirklich schlieߟen -gui.dialog.confirm.result.really_close.message = Sind Sie sicher? Wenn Sie diesen Tab schließen, werden die Ergebnisse nicht mehr in dieser Ansicht angezeigt. - -gui.dialog.error.importwizard.filetype_not_supported.title = Nicht unterstützter Datentyp -gui.dialog.error.importwizard.filetype_not_supported.message = Dateien des Formats {0} werden nicht unterstützt. - -gui.dialog.error.error_in_copy_repository_entry.title = Repository Fehler -gui.dialog.error.error_in_copy_repository_entry.message = Fehler beim Kopieren des Repositoryeintrags nach {0}: {1}. - -gui.dialog.error.error_downloading_metadata.title = Fehler beim Aufruf von Metadaten -gui.dialog.error.error_downloading_metadata.message = Fehler beim Aufruf von Metadaten für {0}: {1}. - -gui.dialog.error.update_md5_error.title = Download ist fehlgeschlagen -gui.dialog.error.update_md5_error.message = Der Download des packages {0} ist Fehlgeschlagen. Bitte versuchen Sie {0} erneut runter zu laden. - -gui.dialog.error.no_update_md5.message = Fehler beim vergleichen der Pr\u00FCfsummen. Bitte Versuchen Sie die Komponenten erneut runter zu laden. - -gui.dialog.error.malformed_repository_location.title = Fehlerhaftes Repository-Verzeichnis -gui.dialog.error.malformed_repository_location.message = Fehlerhaftes Repository-Verzeichnis : {0}. - -gui.dialog.example_visualizer_dialog.title = Beispiel {0} -gui.dialog.example_visualizer_dialog.message = Dieses Fenster beinhaltet genaue Informationen über das Beispiel Nr.{0}. -#gui.dialog.example_visualizer_dialog.icon = table_selection_row.png - -############################ -# Main Menu and Toolbar -############################ - -###### FILE MENU ############# - -gui.action.menu.file.label = Prozess öffnen -gui.action.menu.file.mne = D -gui.action.menu.file.tip = Prozesse öffnen, speichern und drucken. - -gui.action.new.label = Neuer Prozess -gui.action.new.mne = N -#gui.action.new.icon = document_empty_new.png -gui.action.new.tip = Leeren Prozess erstellen -#gui.action.new.acc = control N - -gui.action.open.label = Öffne Prozess als... -gui.action.open.mne = f -#gui.action.open.icon = folder_open.png -gui.action.open.tip = Prozessdatei öffnen -#gui.action.open.acc = control O - -gui.action.save.label = Speicher Prozess -gui.action.save.mne = S -#gui.action.save.icon = floppy_disk.png -gui.action.save.tip = Den aktuellen Prozess in seiner Datei speichern. -#gui.action.save.acc = control S - -gui.action.save_as.label = Speicher Prozess unter... -gui.action.save_as.mne = u -#gui.action.save_as.icon = save_as.png -gui.action.save_as.tip = Den aktuellen Prozess als neue Datei speichern. - -gui.action.import_process.label = Prozess einfügen... -gui.action.import_process.mne = e -#gui.action.import_process.icon = inbox_into.png -gui.action.import_process.tip = Prozess aus einer Datei einfügen. - -gui.action.link.label = Verknüpfe -#gui.action.link.icon = left_right.png -gui.action.link.tip = Öffnet das Repository-Verzeichnis des aktuellen Prozesses (so vorhanden). - -gui.action.export_process.label = Prozess exportieren... -gui.action.export_process.mne = x -#gui.action.export_process.icon = inbox_out.png -gui.action.export_process.tip = Prozess in eine Datei exportieren. - -gui.action.export_pdf.label = Exportiere {0} als PDF... -gui.action.export_pdf.mne = P -#gui.action.export_pdf.icon = document_empty_out.png -gui.action.export_pdf.tip = Den aktuellen Prozesses oder die Ergebnisse (je nach Ansichtsmodus) als PDF exportieren. - -gui.action.menu.file.import.label = Daten einfügen -gui.action.menu.file.import.mne = D -#gui.action.menu.file.import.icon = inbox_into.png -gui.action.menu.file.import.tip = Daten in das Repository einfügen. - - -gui.action.import.label = Daten einfügen... -#gui.action.import.icon = inbox_into.png -gui.action.import.tip = Daten in ein bestehendes Repository einfügen. - -gui.action.import_database_table.label = Datenbanktabelle einfügen... -#gui.action.import_database_table.icon = inbox_into.png -gui.action.import_database_table.tip = Datenbanktabelle in ein bestehendes Repository einfügen. -gui.action.import_database_table.mne = t - - -gui.action.import_excel_sheet.label = Exceldokument einfügen... -#gui.action.import_excel_sheet.icon = inbox_into.png -gui.action.import_excel_sheet.tip = Ein Dokument aus einer Exceldatei (.xls) in ein bestehendes Repository einfügen. -gui.action.import_excel_sheet.mne = E - -gui.action.import_csv_file.label = CSV-Datei einfügen... -#gui.action.import_csv_file.icon = inbox_into.png -gui.action.import_csv_file.tip = CSV-Datei (.csv) in ein bestehendes Repository einfügen. -gui.action.import_csv_file.mne = C - -gui.action.import_aml_file.label = AML-Datei einfügen... -#gui.action.import_aml_file.icon = inbox_into.png -gui.action.import_aml_file.tip = AML-Datei (.aml) in ein bestehendes Repository einfügen. -gui.action.import_aml_file.mne = A - - -gui.action.import_access_table.label = Access Datenbanktabelle einfügen... -#gui.action.import_access_table.icon = inbox_into.png -gui.action.import_access_table.tip = Tabelle aus einer Accessdatei (.mdb) in ein bestehendes Repository einfügen. -gui.action.import_access_table.mne = D - - -gui.action.import_blob.label = Binäre Datei einfügen... -#gui.action.import_blob.icon = inbox_into.png -gui.action.import_blob.tip = Datei beliebigen Formats in ein bestehendes Repository einfügen. -gui.action.import_blob.mne = B - -gui.action.import_xml_file.label = XML-Datei einfügen... -#gui.action.import_xml_file.icon = inbox_into.png -gui.action.import_xml_file.tip = Daten einer XML-Datei (.xml) in ein bestehendes Repository einfügen. -gui.action.import_xml_file.mne = X - -gui.action.print_preview.label = Druckvorschau... -gui.action.print_preview.mne = r -#gui.action.print_preview.icon = printer_view.png -gui.action.print_preview.tip = Druckvorschau des aktuellen Prozesses oder der Ergebnisse (je nach Ansichtsmodus) anzeigen. - -gui.action.print.label = Drucke {0}... -gui.action.print.mne = D -#gui.action.print.icon = printer.png -gui.action.print.tip = Den aktuellen Prozesses oder die Ergebnisse (je nach Ansichtsmodus) drucken. -#gui.action.print.acc = control P - -gui.action.page_setup.label = Seiteneigenschaften... -gui.action.page_setup.mne = S -#gui.action.page_setup.icon = printer_checkbox_checked.png -gui.action.page_setup.tip = Öffnet ein Fenster um die Eigenschaften der Seite für den Druck einzustellen. - -gui.action.export.label = Exportiere {0}... -gui.action.export.mne = E -#gui.action.export.icon = inbox_out.png -gui.action.export.tip = Den aktuellen Prozesses oder die Ergebnisse (je nach Ansichtsmodus) exportieren. - -gui.action.exit.label = Beenden -gui.action.exit.mne = B -#gui.action.exit.icon = door_exit.png -gui.action.exit.tip = RapidMiner Beenden - - -gui.action.menu.recent_files.label = Zuletzt verwendete Dateien -gui.action.menu.recent_files.mne = Z -#gui.action.menu.recent_files.icon = history2.png -gui.action.menu.recent_files.tip = Liste der zuletzt geöffneten Dateien. - -###### EDIT MENU ######### - -gui.action.menu.edit.label = Bearbeiten -gui.action.menu.edit.mne = B -gui.action.menu.edit.tip = Den Prozessaufbau bearbeiten. - -gui.action.undo.label = Rückgängig -gui.action.undo.mne = R -#gui.action.undo.icon = undo.png -gui.action.undo.tip = Letzten Vorgang rückgängig machen. -#gui.action.undo.acc = control Z - -gui.action.redo.label = Wiederherstellen -gui.action.redo.mne = W -#gui.action.redo.icon = redo.png -gui.action.redo.tip = Letzten rückgängig gemachten Vorgang wiederherstellen. - -gui.action.new_operator.label = Neuer Operator... -gui.action.new_operator.mne = N -#gui.action.new_operator.icon = element_new.png -gui.action.new_operator.tip = Neuen Operator aus einem Fenster auswählen und einfügen. -#gui.action.new_operator.acc = control I - -gui.action.new_building_block.label = Neuer Baustein... -gui.action.new_building_block.mne = B -#gui.action.new_building_block.icon = box_open_new.png -gui.action.new_building_block.tip = Neuen Baustein einfügen. -#gui.action.new_building_block.acc = control B - -gui.action.cut.label = Ausschneiden -gui.action.cut.mne = A -#gui.action.cut.icon = cut.png -gui.action.cut.tip = Ausgewählten Operator entfernen und in der Zwischenablage speichern. -#gui.action.cut.acc = control X - -gui.action.copy.label = Kopieren -gui.action.copy.mne = K -#gui.action.copy.icon = copy.png -gui.action.copy.tip = Ausgewählten Operator in der Zwischenablage speichern. -#gui.action.copy.acc = control C - -gui.action.paste.label = Einfügen -gui.action.paste.mne = E -#gui.action.paste.icon = clipboard_paste.png -gui.action.paste.tip = Operator aus der Zwischenablage einfügen. -#gui.action.paste.acc = control V - -gui.action.delete.label = Löschen -gui.action.delete.mne = L -#gui.action.delete.icon = element_delete.png -gui.action.delete.tip = Ausgewählten Operator löschen. -#gui.action.delete.acc = DELETE - -gui.action.operator_info.label = Operatorinformation anzeigen... -gui.action.operator_info.mne = O -#gui.action.operator_info.icon = element_information.png -gui.action.operator_info.tip = Information über den ausgewählten Operator anzeigen. -#gui.action.operator_info.acc = F1 - -gui.action.save_building_block.label = Als Baustein speichern... -gui.action.save_building_block.mne = A -#gui.action.save_building_block.icon = box_open_add.png -gui.action.save_building_block.tip = Ausgewählten Operator als neuen Baustein speichern. - -gui.action.menu.wiring.label = Neue Verbindung -gui.action.menu.wiring.mne = v -#gui.action.menu.wiring.icon = plug.png -gui.action.menu.wiring.tip = Operatoren verbinden. - -gui.action.wiring.label = Operatoren verbinden -#gui.action.wiring.icon = plug.png - -gui.action.wire.label = Automatisch verbinden -gui.action.wire.mne = A -gui.action.wire.tip = Operator Ein- und Ausg\u00E4nge automatisch verbinden. -#gui.action.wire.icon = plug.png - -gui.action.wire_recursive.label = Automatisch verbinden (rekursiv) -gui.action.wire_recursive.mne = R -gui.action.wire_recursive.tip = Operator Ein- und Ausg\u00E4nge automatisch rekursiv verbinden. -#gui.action.wire_recursive.icon = plug.png - -gui.action.rewire.label = Neu verbinden -gui.action.rewire.mne = W -gui.action.rewire.tip = Operator Ein- und Ausg\u00E4nge automatisch neu verbinden. -#gui.action.rewire.icon = plug.png - -gui.action.rewire_recursive.label = Neu verbinden (streng) -gui.action.rewire_recursive.mne = i -gui.action.rewire_recursive.tip = Operator Ein- und Ausg\u00E4nge automatisch rekursiv neu verbinden. -#gui.action.rewire_recursive.icon = plug.png - -##### RUN MENU ########### - -gui.action.menu.process.label = Prozess -gui.action.menu.process.mne = p -gui.action.menu.process.tip = Prozessaufbau modifizieren - -gui.action.validate.label = Prozess bestätigen -gui.action.validate.mne = b -#gui.action.validate.icon = checks.png -gui.action.validate.tip = Ein- und Ausgangsanschlüsse des Operators und der Prozessstruktur bestätigen. -#gui.action.validate.acc = F12 - -gui.action.validate_automatically.label = Automatisch bestätigen -gui.action.validate_automatically.mne = t -gui.action.validate_automatically.tip = Prozess wird bei Aktivierung automatisch bei jeder Änderung bestätigt. Bemerkung: Wenn nicht aktiv ist es möglich, dass die automatische Wiederverbindung nicht funktioniert. -#gui.action.validate_automatically.icon = checkbox.png - -gui.action.run.label = Ausführen -#gui.action.run.icon = media_play.png -gui.action.run.tip = Aktuellen Prozess ausführen oder fortsetzen. -gui.action.run.mne = A -#gui.action.run.acc = F11 - -gui.action.run_remote_now.label = Prozess jetzt auf RapidMiner Server ausführen -#gui.action.run_remote_now.icon = server2_play.png -gui.action.run_remote_now.tip = Den aktuellen Prozess sofort mit einem Klick auf RapidMiner Server ausführen. -gui.action.run_remote_now.disabled.tip = Um den aktuellen Prozess mit einem Klick auf RapidMiner Server ausführen zu können muss der Prozess in einem RapidMiner Server Repository gespeichert sein. -gui.action.run_remote_now.mne = -#gui.action.run_remote_now.acc = - -gui.action.pause.label = Pause -#gui.action.pause.icon = media_pause.png -gui.action.pause.tip = Aktuellen Prozess anhalten. -gui.action.pause.mne = P -#gui.action.pause.acc = F11 - -gui.action.stop.label = Stop -gui.action.stop.mne = S -#gui.action.stop.icon = media_stop.png -gui.action.stop.tip = Ausführung des aktuellen Prozesses beenden. -#gui.action.stop.acc = control pressed F11 - -gui.action.process_debug_mode.label = Metadaten mit reellwertigen Daten synchronisieren -#gui.action.process_debug_mode.icon = link.png -gui.action.process_debug_mode.mne = s -gui.action.process_debug_mode.tip = Bei Aktivierung werden die an den Anschlüssen zur Verfügung gestellten Metadaten nach Ausführung des Prozesses aktualisiert, sodass sie mit den reellwertigen Daten übereinstimmen. - -gui.action.run_remote.label = Mit RapidMiner Server ausführen -gui.action.run_remote.mne = t -#gui.action.run_remote.icon = server2_play.png -gui.action.run_remote.tip = Führe den Prozess auf dem RapidMiner Server aus. -#gui.action.run_remote.acc = alt pressed F11 - -#bis hier - -###### Tools - -gui.action.menu.tools.label = Werkzeuge -gui.action.menu.tools.mne = W -gui.action.menu.tools.tip = Werkzeuge zur generellen Verwendung. - -gui.action.manage_building_blocks.label = Bausteine verwalten... -gui.action.manage_building_blocks.mne = B -#gui.action.manage_building_blocks.icon = box_open_edit.png -gui.action.manage_building_blocks.tip = Verwaltung gespeicherter Bausteine. - -gui.action.preferences.label = Einstellungen... -gui.action.preferences.mne = P -#gui.action.preferences.icon = clipboard_check_edit.png -gui.action.preferences.tip = Öffnet ein Fenster in dem alle Einstellungen von RapidMiner geändert werden können. - -gui.action.attribute_editor.label = Attribut Editor... -gui.action.attribute_editor.mne = A -#gui.action.attribute_editor.icon = table_new.png -gui.action.attribute_editor.tip = Editor kann zur Erstellung von XML meta data beschreibenden Dokumenten (.aml) benutzt werden. - -gui.action.anova.label = ANOVA Rechner... -gui.action.anova.mne = R -#gui.action.anova.icon = scales.png -gui.action.anova.tip = Startet den ANOVA Rechner. - -gui.action.check_for_updates.label = Nach Updates suchen... -gui.action.check_for_updates.mne = U -#gui.action.check_for_updates.icon = download.png -gui.action.check_for_updates.tip = Suche nach neuen Versionen von RapidMiner. - -gui.action.show_database_drivers.label = Zeige Datenbanktreiber... -gui.action.show_database_drivers.mne = D -#gui.action.show_database_drivers.icon = data_network.png -gui.action.show_database_drivers.tip = Zeigt alle verfügbaren JDBC Datenbanktreiber, die zur Zeit für RapidMiner vorhanden sind. - -gui.action.manage_db_connections.label = Verwalte Datenbankverbindungen... -gui.action.manage_db_connections.mne = v -#gui.action.manage_db_connections.icon = data_network_edit.png -gui.action.manage_db_connections.tip = Datenbankverbindungen herstellen, ändern und löschen. - -gui.action.clear_db_cache.label = Metadaten aktualisieren -gui.action.clear_db_cache.mne = M -#gui.action.clear_db_cache.icon = data_refresh.png -gui.action.clear_db_cache.tip = Den Tabellen-Metadaten Cache aktualisieren. - -gui.action.attribute_wizard.label = Attributbeschreibung Dokumenten Assistent... -gui.action.attribute_wizard.mne = A -#gui.action.attribute_wizard.icon = magic_wand.png -gui.action.attribute_wizard.tip = Öffnet ein Fenster in dem Attribut beschreibende Dokumente (.aml) für fast beliebige Daten definiert werden können. - - -gui.action.wizard.data_import_wizard.label = Strukturassistent öffnen... -#gui.action.wizard.data_import_wizard.icon = magic_wand.png -gui.action.wizard.data_import_wizard.tip = Startet den Lesestruktur Assistenten, der den Einfügeoperator erstellt. - - -gui.action.wizard.validate_value_types.label = Daten erneut laden -gui.action.wizard.validate_value_types.mne = e -#gui.action.wizard.validate_value_types.icon = refresh.png -gui.action.wizard.validate_value_types.tip = Lädt Daten erneut und sucht nach Zellen, die nicht zu den definierten Formaten der Werte gehören. - -gui.action.wizard.abort_validate_value_types.label = Erneutes laden stoppen -gui.action.wizard.abort_validate_value_types.mne = s -#gui.action.wizard.abort_validate_value_types.icon = media_stop.png -gui.action.wizard.abort_validate_value_types.tip = Stoppt das erneute Laden der Daten. - -gui.action.wizard.guess_value_types.label = Wertformat raten -gui.action.wizard.guess_value_types.mne = r -#gui.action.wizard.guess_value_types.icon = question_and_answer.png -gui.action.wizard.guess_value_types.tip = Lädt die Daten erneut und rät das Format der Werte jedes Attributs. - -gui.action.wizard.abort_guess_value_types.label = Raten abbrechen -gui.action.wizard.abort_guess_value_types.mne = a -#gui.action.wizard.abort_guess_value_types.icon = media_stop.png -gui.action.wizard.abort_guess_value_types.tip = Stoppt das Raten des Formats der Werte. - -gui.action.wizard.show_error_rows.label = Nur Fehler anzeigen -gui.action.wizard.show_error_rows.mne = F -#gui.action.wizard.show_error_rows.icon = table_selection_row_delete.png -gui.action.wizard.show_error_rows.tip = Zeigt nur die Zeilen mit wichtigen Fehlern an. - -gui.action.wizard.abort_show_error_rows.label = Filterung nach Fehlern abbrechen -#gui.action.wizard.abort_show_error_rows.icon = delete.png -gui.action.wizard.abort_show_error_rows.tip = Stoppt die Filterung nach Zeilen mit Fehlern. - -gui.action.wizard.error_tolerant.label = Fehler ignorieren -gui.action.wizard.error_tolerant.mne = i -gui.action.wizard.error_tolerant.tip = Ignoriert Fehler, wenn es aktiviert ist - -gui.action.show_usage_statistics.label = Benutzungsstatistik anzeigen -#gui.action.show_usage_statistics.icon = chart_column.png -gui.action.show_usage_statistics.mne = B -gui.action.show_usage_statistics.tip = Zeigt Statistik über die Häufigkeit der Benutzung der einzelnen Operatoren an. - -gui.label.date_format.label = Datumsformat -gui.label.date_format.mne = D -gui.label.date_format.tip = Schema des Datums, dass zum Parsen von Daten benutzt werden soll. - -#################################################### -# ManageDatabaseDriversDialog -#################################################### -gui.dialog.manage_database_drivers.title = Datenbanktreiber verwalten -gui.dialog.manage_database_drivers.message = Um neue Datenbanktreiber zu installieren, .jar Datei auswählen und eine Treiberklasse, die dort beinhaltet ist. Manche geschützte JDBC Treiber betehen aus mehreren Dateien, z.B. einer Treiber- und einer Lizenzdatei. Mehrere .jar Dateien und Treiberklassen können durch Kommata getrennt werden. Nach einer Ä„nderung dieser Daten muss RapidMiner neu gestartet werden. -#gui.dialog.manage_database_drivers.icon = data_network_edit.png - -gui.label.manage_database_drivers.name.label = Name -gui.label.manage_database_drivers.name.mne = N -gui.label.manage_database_drivers.urlprefix.label = URL Prefix -gui.label.manage_database_drivers.urlprefix.mne = U -gui.label.manage_database_drivers.port.label = Port -gui.label.manage_database_drivers.port.mne = P -gui.label.manage_database_drivers.jarfile.label = Jar Datei -gui.label.manage_database_drivers.jarfile.mne = J -gui.label.manage_database_drivers.classname.label = Treiberklasse -gui.label.manage_database_drivers.classname.mne = T -gui.action.manage_database_drivers.jarfile.label = -gui.label.manage_database_drivers.dbseparator.label = Schema Separator -gui.label.manage_database_drivers.dbseparator.mne = S - -#gui.action.manage_database_drivers.jarfile.icon = folder_open.png -gui.action.manage_database_drivers.label = Datenbanktreiber verwalten -#gui.action.manage_database_drivers.icon = data_network_edit.png -gui.action.manage_database_drivers.tip = JDBC Treiber ändern oder neue hinzufügen -gui.action.manage_database_drivers.mne = T - -gui.action.manage_database_drivers.add.label = Hinzufügen -gui.action.manage_database_drivers.add.mne = H -gui.action.manage_database_drivers.add.tip = Neuen Treiber hinzufügen -#gui.action.manage_database_drivers.add.icon = data_connection_new.png - -gui.action.manage_database_drivers.delete.label = Löschen -gui.action.manage_database_drivers.delete.mne = L -gui.action.manage_database_drivers.delete.tip = Ausgewählten Treiber löschen. -#gui.action.manage_database_drivers.delete.icon = data_network_delete.png - -gui.action.manage_database_drivers.save.label = Speichern -gui.action.manage_database_drivers.save.mne = S -gui.action.manage_database_drivers.save.tip = Ausgewählte Treiber speichern. -#gui.action.manage_database_drivers.save.icon = floppy_disk.png - -gui.dialog.error.manage_database_drivers.error_saving.title = Speichern der JDBC Eigenschaften misslungen -gui.dialog.error.manage_database_drivers.error_saving.message = Speichern der JDBC Eigenschaften {0} misslungen - -gui.dialog.confirm.manage_database_drivers.restart.title = Neustart erforderlich -gui.dialog.confirm.manage_database_drivers.restart.message = Um Änderungen zu übernehmen muss RapidMiner neu gestartet werden. Jetzt neu starten? - -###### VIEW ################ - -gui.action.menu.view.label = Ansicht -gui.action.menu.view.mne = A -gui.action.menu.view.tip = Benutzerschnittstelle anpassen. - -gui.action.menu.perspectives.label = Sichten -#gui.action.menu.perspectives.icon = windows.png -gui.action.menu.perspectives.mne = S -gui.action.menu.perspectives.tip = Sicht wählen - -gui.action.new_perspective.label = Neue Sicht... -#gui.action.new_perspective.icon = window_new.png -gui.action.new_perspective.mne = N -gui.action.new_perspective.tip = Neue Sicht erstellen. - -gui.action.restore_predefined_perspective_default.label = Sicht zurücksetzen -gui.action.restore_predefined_perspective_default.mne = z -#gui.action.restore_predefined_perspective_default.icon = window_ok.png -gui.action.restore_predefined_perspective_default.message = Stellt das ursprüngliche Layout der derzeitigen Sicht wieder her. - -gui.dialog.input.new_perspective.title = Neue Sicht -#gui.dialog.input.new_perspective.icon = window_new.png -gui.dialog.input.new_perspective.message = Neue Sicht benennen. - -gui.action.delete_perspective.label = Sicht löschen -gui.action.delete_perspective.mne = l -#gui.action.delete_perspective.icon = window_delete.png -gui.action.delete_perspective.tip = Diese Ansicht löschen. - -gui.action.menu.show_view.label = Ansicht zeigen -#gui.action.menu.show_view.icon = window_view.png -gui.action.menu.show_view.mne = A -gui.action.menu.show_view.tip = Schaltet die Komponenten der Benutzerschnittstelle an und aus. - -gui.action.expert.label = Experten Modus -gui.action.expert.mne = E -#gui.action.expert.icon = graduate.png -gui.action.expert.tip = Schaltet in den Experten Modus um (alle verfügbaren Parameter sind sichtbar). -#gui.action.expert.acc = F4 - -gui.action.beginner.label = Anfänger Modus -gui.action.beginner.mne = B -#gui.action.beginner.icon = user.png -gui.action.beginner.tip = Schaltet in den Anfänger Modus um (nur die wichtigsten Parameter sind sichtbar). -#gui.action.beginner.acc = F4 - -gui.action.result_history.label = Ergebnisverlauf... -gui.action.result_history.mne = v -#gui.action.result_history.icon = history.png -gui.action.result_history.tip = Zeigt ein Fenster mit allen Ergebnissen dieser Sitzung an. - -gui.action.edit_view.label = Ansicht bearbeiten -gui.action.edit_view.mne = b -gui.action.edit_view.tip = Dargestellte Ansichten markieren und demarkieren. - -############## HELP ################# - -gui.action.menu.help.label = Hilfe -gui.action.menu.help.mne = H -gui.action.menu.help.tip = Hilfe zur Benutzung von RapidMiner. - -gui.action.tour.label = RapidMiner Tour... -gui.action.tour.mne = R -#gui.action.tour.icon = signpost.png -gui.action.tour.tip = Startet die Interaktive RapidMiner Tour. - -gui.action.tutorial.label = RapidMiner Tutorium... -gui.action.tutorial.mne = T -#gui.action.tutorial.icon = book.png -gui.action.tutorial.tip = Startet das RapidMiner Onlinetutorium. - -gui.action.about.label = Info über RapidMiner... -gui.action.about.mne = I -#gui.action.about.icon = about.png -gui.action.about.tip = Zeigt Informationen zu RapidMiner an. - -#gui.action.gui_manual.label = RapidMiner GUI Handbuch... -#gui.action.gui_manual.mne = G -#gui.action.gui_manual.icon = question.png -#gui.action.gui_manual.tip = RapidMiner GUI Handbuch durchsuchen. - -gui.action.help_support.label = Unterstützung benötigt? -gui.action.help_support.mne = U -#gui.action.help_support.icon = lifebelt.png -gui.action.help_support.tip = Mehr über die Möglichkeiten der professionellen Unterstützung zu RapidMiner erfahren. - -gui.action.help_videotutorials.label = Videotutorien -gui.action.help_videotutorials.mne = V -#gui.action.help_videotutorials.icon = movie.png -gui.action.help_videotutorials.tip = Videotutorien von RapidMiner im Netz anschauen. - -gui.action.help_forum.label = Community Forum -gui.action.help_forum.mne = F -#gui.action.help_forum.icon = question_and_answer.png -gui.action.help_forum.tip = RapidMiner Community Forum besuchen für Fragen und Diskussionen rund um RapidMiner und Data-Mining im Allgemeinen. - - -gui.action.about_extension.label = Informationen zur {0} Erweiterung... -#gui.action.about_extension.icon = piece2.png -gui.action.about_extension.tip = Zeigt Informationen über die {0} Erweiterung an. - -######################################## -# ExtendedJTable -######################################## -gui.action.menu.move_column_menu.label = Spalte verschieben -#gui.action.menu.move_column_menu.icon = table_refresh.png -gui.action.menu.move_column_menu.mne = S -gui.action.menu.move_column_menu.tip = Spalte auf eine andere Position verschieben. -gui.action.move_column.label = Spalte nach {0} verschieben -gui.action.move_column.tip = Markierte Spalte zu einer anderen Position hin verschieben. - -######################################## -# OPERATOR CONTEXT MENU -######################################## - -gui.action.enable_operator.label = Operator einschalten -gui.action.enable_operator.tip = Auswählen, ob der Operatur ausgeführt werden soll. -gui.action.enable_operator.mne = e -#gui.action.enable_operator.acc = control E -#gui.action.enable_operator.icon = element_ok.png - -gui.action.enable_operator_multiple.label = Operatoren {0} einschalten -gui.action.enable_operator_multiple.tip = Alle ausgewählten Operatoren einschlaten. -gui.action.enable_operator_multiple.mne = e -#gui.action.enable_operator_multiple.icon = element_ok.png - -gui.action.disable_operator_multiple.label = Operatoren {0} ausschalten -gui.action.disable_operator_multiple.tip = Alle ausgewählten Operatoren ausschalten. -gui.action.disable_operator_multiple.mne = a -#gui.action.disable_operator_multiple.icon = element_ok.png - - -gui.action.make_dirty.label = Als fehlerhaft markieren -gui.action.make_dirty.tip = Diesen Operator als fehlerhaft markieren, d.h. er sollte erneut ausgeführt werden. -gui.action.make_dirty.mne = f -#gui.action.make_dirty.icon = checkbox_unchecked.png - -gui.action.breakpoint_before.label = Unterbrechung vorher -#gui.action.breakpoint_before.icon = breakpoint_up.png -gui.action.breakpoint_before.tip = Unterbrechung vor dem aktuellen Operator einfügen. - -gui.action.breakpoint_after.label = Unterbrechung nachher -#gui.action.breakpoint_after.icon = breakpoint_down.png -gui.action.breakpoint_after.tip = Unterbrechung nach dem aktuellen Operator einfügen. -#gui.action.breakpoint_after.acc = F7 - -gui.action.breakpoint_within.label = Unterbrechung während -#gui.action.breakpoint_within.icon = breakpoint.png -gui.action.breakpoint_within.tip = Unterbrechung in dem aktuellen Operator einfügen. - -#gui.action.add_breakpoints.label = Unterbrechungen hinzufügen (Debug-Modus an) -#gui.action.add_breakpoints.mne = h -#gui.action.add_breakpoints.icon = bug_ok.png -#gui.action.add_breakpoints.tip = Unterbrechung nach jedem Operator einfügen. (Debug-Modus an). -# -#gui.action.remove_breakpoints.label = Unterbrechungen aufheben (Debug-Modus aus) -#gui.action.remove_breakpoints.mne = R -#gui.action.remove_breakpoints.icon = bug_error.png -#gui.action.remove_breakpoints.tip = Alle Unterbrechungen aufheben (Debug-Modus aus). - -gui.action.toggle_all_breakpoints.label = Alle Unterbrechungen (Debug-Modus) -gui.action.toggle_all_breakpoints.mne = D -#gui.action.toggle_all_breakpoints.icon = bug_stop.png -gui.action.toogle_all_breakpoints.tip = Unterbrechung nach jedem Operator einfügen. - -################################################################################################ -# Other general actions -################################################################################################ -gui.action.store_in_repository.label = {0} im Repository speichern -#gui.action.store_in_repository.icon = data_floppy_disk.png -gui.action.store_in_repository.mne = s -gui.action.store_in_repository.tip = Dieses Ergebnis im Repository speichern. - -gui.action.export_and_print.label = Exportieren/Drucken -gui.action.export_and_print.mne = x -gui.action.export_and_print.tip = Ergebnisse drucken oder als Dateien exportieren. -#gui.action.export_and_print.icon = inbox_out.png - -gui.action.close_all_results.label = Alle Ergebnisse schließen -#gui.action.close_all_results.icon = selection_delete.png -gui.action.close_all_results.mne = C -gui.action.close_all_results.tip = Schließt alle Ergebnisse die momentan geöffnet sind. - -################################################################################################ -# COMPONENTS -################################################################################################ - -gui.action.open_file.label = Öffnen -#gui.action.open_file.icon = folder_open.png -gui.action.open_file.tip = Öffnet das ausgewählte. - -gui.action.save_file.label = Speichern -#gui.action.save_file.icon = flopfloppy_disk -gui.action.save_file.tip = Speichert das ausgewählte. - -#OperatorPropertyPanel -gui.label.compatibility_level.label = Kompatibilitätsmodus -gui.label.compatibility_level.mne = K -gui.label.compatibility_level.tip = Der Kompatibilitätsmodus gibt an welche RapidMiner oder erweiterte Version simuliert werden soll. Ä„ndert sich der Aufbau der Operatoren mit der Zeit kann jederzeit auf ältere Versionen zurückgegriffen werden, die mit dem Prozess gespeichert wurden. - -# XMLEditor -gui.action.xml_editor.apply_changes.label = Änderungen anwenden -gui.action.xml_editor.apply_changes.mne = a -gui.action.xml_editor.apply_changes.tip = Änderungen, die im XML Code der Prozessbeschreibung gemacht wurden anwenden. -#gui.action.xml_editor.apply_changes.icon = check.png - -gui.action.editor.delete.label = Löschen -#gui.action.editor.delete.icon = document_text_delete.png -#gui.action.editor.delete.acc = DELETE -gui.action.editor.delete.tip = Ausgewählten Inhalt löschen. - -gui.action.editor.cut.label = Ausschneiden -#gui.action.editor.cut.acc = control X -#gui.action.editor.cut.icon = cut.png -gui.action.editor.cut.tip = Ausgewählten Inhalt ausschneiden und in der Zwischenablage speichern. - -gui.action.editor.copy.label = Kopieren -#gui.action.editor.copy.acc = control C -#gui.action.editor.copy.icon = copy.png -gui.action.editor.copy.tip = Ausgewählten Inhalt in der Zwischenablage speichern. - -gui.action.editor.paste.label = Einfügen -#gui.action.editor.paste.acc = control V -#gui.action.editor.paste.icon = clipboard_paste.png -gui.action.editor.paste.tip = Inhalt aus der Zwischenablage einfügen. - -gui.action.editor.select_all.label = Alles markieren -#gui.action.editor.select_all.acc = control A -#gui.action.editor.select_all.icon = documents_preferences.png -gui.action.editor.select_all.tip = Ganzen Inhalt auswählen. - -gui.action.editor.search_replace.label = Suchen und ersetzen... -#gui.action.editor.search_replace.icon = binocular.png -#gui.action.editor.search_replace.acc = control F -gui.action.editor.search_replace.tip = Textstücke suchen und ersetzen. - - -# Error table -gui.errortable.header.message.label = Nachricht -gui.errortable.header.fixes.label = Lösungen -gui.errortable.header.location.label = Position -gui.errortable.header.message.tip = Die Fehlermeldung. -gui.errortable.header.fixes.tip = Die verfügbare Schnelllösung des Fehlers, die mit einem Doppelklick angewendet werden kann. -gui.errortable.header.location.tip = Der Operator und Anschluss an dem der Fehler auftritt. - -gui.action.error_table_only_current.label = Ausgewählten Operator herausfiltern -gui.action.error_table_only_current.tip = Bei Aktivierung werden nur Fehler des aktuell ausgewählten Operators angezeigt. -#gui.action.error_table_only_current.icon = funnel_checkbox_checked.png -gui.action.error_table_only_current.mne = O - -gui.errortable.no_quickfix_available.label = Keine Schnelllösung verfügbar -#gui.errortable.no_quickfix_available.icon = question.png -gui.errortable.no_quickfix_available.tip = Es steht keine Schnelllösung für diesen Operator zur Verfügung. - -gui.errortable.choose_quickfix.label = Zwischen {0} zur Verfügung stehenden Schnelllösungen wählen... -#gui.errortable.choose_quickfix.icon = first_aid.png -gui.errortable.choose_quickfix.tip = Fenster öffnen, um zwischen zur Verfügung stehenden Schnelllösungen für diesen Fehler zu wählen. - -gui.action.menu.quick_fixes.label = Schnelllösungen -gui.action.menu.quick_fixes.mne = S -gui.action.menu.quick_fixes.tip = Zeigt Lösungen der Probleme des Prozessaufbaus. -#gui.action.menu.quick_fixes.icon = first_aid.png - -#gui.action.quickfix.connect_to.icon = plug.png -#gui.action.quickfix.reconnect_to.icon = plug.png -#gui.action.quickfix.add_compatible.icon = element_new.png -#gui.action.quickfix.disconnect.icon = plug_delete.png -#gui.action.quickfix.insert_id_tagging.icon = table_selection_column_add.png -#gui.action.quickfix.insert_model_applier.icon = lightbulb_on.png -#gui.action.quickfix.insert_discretization.icon = objects_transform.png -#gui.action.quickfix.insert_missing_value_replenishment.icon = table_new.png -#gui.action.quickfix.insert_nominal_to_numerical_label.icon = objects_transform.png -#gui.action.quickfix.insert_nominal_to_binominal_label.icon = objects_transform.png -#gui.action.quickfix.insert_nominal_to_numerical_attributes.icon = objects_transform.png -#gui.action.quickfix.set_parameter.icon = form_edit.png -#gui.action.quickfix.set_parameters_using_wizard.icon = form_edit.png -#gui.action.quickfix.set_parameter_list.icon = form_edit.png -#gui.action.quickfix.correct_parameter_settings_by.icon = form_edit.png -#gui.action.quickfix.correct_parameter_settings_list.icon = form_edit.png -#gui.action.quickfix.correct_parameter_settings_boolean_enable.icon = form_edit.png -#gui.action.quickfix.correct_parameter_settings_boolean_disable.icon = form_edit.png -#gui.action.quickfix.correct_parameter_settings_with_wizard.icon = form_edit.png -#gui.action.quickfix.replace_by_dictionary.icon = form_edit.png -#gui.action.quickfix.change_attribute_role.icon = form_edit.png -#gui.action.quickfix.insert_binominal_to_multiclass_learner.icon = lightbulb_off.png -#gui.action.quickfix.insert_classification_by_regression_learner.icon = lightbulb_off.png - -gui.dialog.input.quickfix.replace_by_dictionary.title = Wert wählen -#gui.dialog.input.quickfix.replace_by_dictionary.icon = form_edit.png -gui.dialog.input.quickfix.replace_by_dictionary.message = {0} - -gui.dialog.set_parameter.title = Parameter bestimmen: {0} -#gui.dialog.set_parameter.icon = form_edit.png - -gui.dialog.input.cannot_connect.title = Verbindung nicht möglich -#gui.dialog.input.cannot_connect.icon = plug.png -gui.dialog.input.cannot_connect.message = Verbindung von {0} mit {1} nicht möglich: {2}. Bitte weiteres Vorgehen aus den Optionen wählen. -gui.dialog.input.cannot_connect.reason.both_connected = beide Anschlüsse sind bereits verbunden -gui.dialog.input.cannot_connect.reason.source_connected = ausgehender Anschluss ist bereits verbunden mit {0} -gui.dialog.input.cannot_connect.reason.dest_connected = Zielanschluss ist bereits mit {0} verbunden -gui.dialog.input.cannot_connect.option.disconnect_connect = Anschlüsse trennen und verbinden -gui.dialog.input.cannot_connect.option.insert_multiplier = Bei Bedarf den Operator Multiply einfügen. -gui.dialog.input.cannot_connect.option.dont_connect = Anschlüsse nicht verbinden. - - -# Message viewer -gui.action.clear_message_viewer.label = Nachrichtenanzeige löschen -gui.action.clear_message_viewer.mne = N -#gui.action.clear_message_viewer.icon = erase.png -gui.action.clear_message_viewer.tip = Alle Nachrichten in der Nachrichtenanzeige löschen - -gui.action.save_log_file.label = Logdatei speichern... -gui.action.save_log_file.mne = s -#gui.action.save_log_file.icon = floppy_disk.png -gui.action.save_log_file.tip = Logdaten in einer Datei speichern. - -gui.action.menu.log_level.label = Loganzahl festlegen -gui.action.menu.log_level.mne = L -gui.action.menu.log_level.tip = Mindestanzahl der Nachrichten festlegen, die gelogt werden. - -gui.action.search_log.label = Lognachrichten durchsuchen... -gui.action.search_log.mne = s -#gui.action.search_log.icon = binocular.png -gui.action.search_log.tip = Text der gelogten Nachrichten durchsuchen. -#gui.action.search_log.acc = control F - -gui.action.start_search.label = Suchen -gui.action.start_search.mne = S -#gui.action.start_search.icon = binocular.png -gui.action.start_search.tip = Jetzt suchen. - -gui.action.start_replace.label = Ersetzen/Suchen -gui.action.start_replace.mne = E -#gui.action.start_replace.icon = replace.png -gui.action.start_replace.tip = Nächstes Vorkommen suchen und ersetzen. - -gui.label.search_what.label = Suchen -gui.label.search_what.tip = Gesuchten Text eingeben. - -gui.label.replace_with.label = Ersetzen durch -gui.label.replace_with.tip = Ersetzenden Text eingeben. - -gui.action.case_sensitive.label = Groߟ-/Kleinschreibung -gui.action.case_sensitive.tip = Wählen, ob die Groߟ-/Kleinschreibung beachtet werden soll. - -gui.action.search_regular_expression.label = Reguläre Ausdrücke -gui.action.search_regular_expression.tip = Wählen, ob der Suchtext ein regulärer Ausdruck ist. - -gui.action.search_forward.label = Weiter -gui.action.search_forward.tip = Abwärts vom letzten Treffer suchen. - -gui.action.search_backward.label = Zurück -gui.action.search_backward.tip = Aufwärts vom letzten Treffer suchen. - - -# NewOperator panel -#gui.label.auto_wire_on_add.label = Automatically wire new operators -#gui.label.auto_wire_on_add.tip = If checked, newly added operators are automatically connected. -#gui.label.auto_wire_on_add.icon = 16/plug.png -gui.action.auto_wire_on_add.label = Neue Operatoren automatisch verbinden -gui.action.auto_wire_on_add.tip = Aktivierung/Deaktivierung der automatischen Verbindung neu hinzugefügter Operatoren. -#gui.action.auto_wire_on_add.icon = plug_new.png -gui.action.auto_wire_inputs_on_add.label = Eingangsanschlüsse Auto-Verbindung -gui.action.auto_wire_inputs_on_add.mne = E -#gui.action.auto_wire_inputs_on_add.icon = plug_new_next.png -gui.action.auto_wire_inputs_on_add.tip = Bei Aktivierung werden die Eingangsanschlüsse neu hinzugefügter Operatoren automatisch verbunden. -gui.action.auto_wire_outputs_on_add.label = Ausgangsanschlüsse Auto-Verbindung -gui.action.auto_wire_outputs_on_add.mne = A -#gui.action.auto_wire_outputs_on_add.icon = plug_new_previous.png -gui.action.auto_wire_outputs_on_add.tip = Bei Aktivierung werden die Ausgangsanschlüsse neu hinzugefügter Operatoren automatisch verbunden. - -gui.action.filter_deprecated.label = Abgelehnte Operatoren herausfiltern -#gui.action.filter_deprecated.icon = funnel.png -gui.action.filter_deprecated.tip = Bei Aktivierung werden abgelehnte Operatoren herausgefiltert. - -gui.action.sort_by_usage.label = Nach Verwendung sortieren -#gui.action.sort_by_usage.icon = sort_descending.png -gui.action.sort_by_usage.tip = Bei Aktivierung werden die Operatoren nach ihrer Verwendung sortiert, am häufigsten gebrauchte zuerst. - -gui.filter_text_field.label = Suchen - -gui.field.filter_deprecated.tip = Sucheingaben einfügen, um den neuen Operatorbaum zu suchen. - -gui.action.clear_filter.label = Suche zurücksetzen -#gui.action.clear_filter.icon = delete.png -gui.action.clear_filter.tip = Aktuelle Suche löschen - - -gui.action.add_operator_now.label = Operator hinzufügen -gui.action.add_operator_now.mne = h -gui.action.add_operator_now.tip = Operator dem Prozess hinzufügen. -#gui.action.add_operator_now.icon = element_add.png - -# ProcessRenderer -gui.action.connect_port_to_repository_location.label = {0} zu Repository-Verzeichnis verbinden -gui.action.connect_port_to_repository_location.mne = v -#gui.action.connect_port_to_repository_location.icon = plug.png -gui.action.connect_port_to_repository_location.tip = {0} mit einem im Repository aufbewahrten Dateneintrag verbinden. - -gui.action.select_all.label = Alle markieren -#gui.action.select_all.acc = control pressed A -gui.action.select_all.tip = Alle Operatoren in dieser Kette auswählen. - -gui.action.selection_history.label = -#gui.action.selection_history.icon = clock_preferences.png -gui.action.selection_history.tip = Vor kurzem benutzten Operator auswählen (rückwärts). - -gui.action.select_backward.label = -#gui.action.select_backward.icon = arrow_left.png -gui.action.select_backward.tip = Vor kurzem benutzten Operator durchsuchen (rückwärts). - -gui.action.select_forward.label = -#gui.action.select_forward.icon = arrow_right.png -gui.action.select_forward.tip = Vor kurzem benutzten Operator auswählen (vorwärts). - -gui.action.select_parent.label = -#gui.action.select_parent.icon = arrow_up.png -gui.action.select_parent.tip = Gehe zu Üœbergeordnetem des aktuell gezeigten Teilprozesses. - -gui.action.menu.new_operator.label = Neuer Operator -#gui.action.menu.new_operator.icon = element_new.png -gui.action.menu.new_operator.tip = Neuen Operator einfügen. - -gui.action.menu.replace_operator.label = Operator ersetzen -#gui.action.menu.replace_operator.icon = element_replace.png -gui.action.menu.replace_operator.tip = Durch einen neuen Operator ersetzen. - -gui.action.menu.operator_group.label = -#gui.action.menu.operator_group.icon = folder.png -gui.action.menu.operator_group.tip = Die Operatoren der Gruppe {0}. -#gui.action.menu.operator_group.open.icon = folder_open.png -#gui.action.menu.operator_group.closed.icon = folder.png - -gui.action.menu.new_building_block.label = Neuer Baustein -#gui.action.menu.new_building_block.icon = box_open_new.png - -gui.action.show_execution_order.label = Reihenfolge der Ausführung zeigen -#gui.action.show_execution_order.icon = sort_up_down.png -gui.action.show_execution_order.mne = R -gui.action.show_execution_order.tip = Zeigt ein Informationsfenster mit der Reihenfolge der Ausführung der Operatoren der Operatorenkette an. - -gui.action.bring_operator_to_front.label = Operator nach vorn bringen -#gui.action.bring_operator_to_front.icon = element_previous.png -gui.action.bring_operator_to_front.mne = b -gui.action.bring_operator_to_front.tip = Versetzt den Operator an den Anfang der Reihenfolge der Ausführung, sofern möglich ohne die anderen Operatoren zu verschieben. - -gui.action.menu.execution_order.label = Reihenfolge der Operatorausführung -gui.action.menu.execution_order.mne = O -#gui.action.menu.execution_order.icon = sort_up_down.png -gui.action.menu.execution_order.tip = Reihenfolge der Operatorausführung anzeigen und festlegen. - -gui.action.render_execution_order.label = Ausführungsreihenfolge -gui.action.render_execution_order.mne = r -#gui.action.render_execution_order.icon = sort_up_down_question.png -gui.action.render_execution_order.tip = Reihenfolge der Operatorausführung zeigen und ändern. - -gui.dialog.execution_order_info.title = Ausführungsreihenfolge -gui.dialog.execution_order_info.message = Reihenfolge der Operatorausführung der aktuellen Kette. -#gui.dialog.execution_order_info.icon = sort_up_down.png - -gui.action.rename_in_processrenderer.label = Umbenennen -#gui.action.rename_in_processrenderer.icon = element_edit.png -gui.action.rename_in_processrenderer.mne = U -#gui.action.rename_in_processrenderer.acc = F2 -gui.action.rename_in_processrenderer.tip = Aktuellen Operator umbenennen. - -gui.dialog.input.rename_operator.title = Operator umbenennen -#gui.dialog.input.rename_operator.icon = element_edit.png -gui.dialog.input.rename_operator.message = Bitte den Namen des Operators einfügen. - -gui.action.arrange_operators.label = Operatoren anordnen -#gui.action.arrange_operators.icon = layout.png -gui.action.arrange_operators.mne = a -gui.action.arrange_operators.tip = Operatoren automatisch im Prozess anordnen. - -gui.action.auto_fit.label = Größe anpassen -gui.action.auto_fit.mne = G -#gui.action.auto_fit.icon = fit_to_size.png -gui.action.auto_fit.tip = Gröߟe des Prozesses den Operatoren anpassen. - -gui.action.delete_selected_connection.label = Verbindung trennen -#gui.action.delete_selected_connection.icon = delete.png -gui.action.delete_selected_connection.tip = Aktuell ausgewählte Verbindung trennen. -#gui.action.delete_selected_connection.acc = DELETE - -gui.action.disconnect.label = Anschluss trennen -gui.action.disconnect.mne = t -gui.action.disconnect.tip = Diesen Anschluss trennen. -#gui.action.disconnect.icon = plug_delete.png - -gui.action.show_port_data.label = Ergebnis {0} zeigen -#gui.action.show_port_data.icon = presentation_chart.png -gui.action.show_port_data.tip = {0} in der Ergebnisübersicht anzeigen. - -gui.action.add_subprocess.label = Hinzufügen -#gui.action.add_subprocess.icon = element_selection_add.png -gui.action.add_subprocess.tip = Teilprozess zu diesem Operator hinzufügen. -gui.action.add_subprocess.tip.after = Teilprozess zu diesem Operator nach Teilprozess ''{0}'' hinzufügen. -gui.action.add_subprocess.tip.before = Teilprozess zu diesem Operator vor Teilprozess ''{0}'' hinzufügen. - -gui.action.delete_subprocess.label = Löschen -#gui.action.delete_subprocess.icon = element_selection_delete.png -gui.action.delete_subprocess.tip = Teilprozess dieses Operators löschen. -gui.action.delete_subprocess.tip.after = Teilprozess ''{0}'' dieses Operators löschen. - -gui.action.menu.process_layout.label = Prozesslayout -#gui.action.menu.process_layout.icon = layout.png -gui.action.menu.process_layout.tip = Prozesslayout ändern -gui.action.menu.process_layout.mne = l - -gui.action.specify_context.label = Kontext angeben... -#gui.action.specify_context.icon = environment.png -gui.action.specify_context.tip = Öffnet Fenster in dem die Ein- und Ausgaben und Makros des Prozesses angegeben werden können. - -gui.action.define_macros.label = Makros definieren... -#gui.action.define_macros.icon = keyboard_key_a.png -gui.action.define_macros.tip = Makros für den aktuellen Prozess definieren. - -#DateFormatValueCellEditor -gui.action.no_matches_found.label = Keine Übereinstimmungen gefunden -gui.action.no_matches_found.icon = -gui.action.no_matches_found.tip = - -#RepositoryBrowser -#gui.repository.db.icon = data_network.png -#gui.repository.local.icon = hard_drive.png -#gui.repository.remote.icon = server2.png -#gui.repository.resource.icon = box_open.png -#gui.repository.enterprise.icon = hard_drive.png - -gui.repository.not_accessible.message = KEIN ZUGRIFF - -gui.action.add_repository.label = Repository hinzufügen -gui.action.add_repository.mne = h -#gui.action.add_repository.icon = server_add.png -gui.action.add_repository.tip = Verbindung zu einem neuen Repository-Server hinzufügen. - -gui.action.configure_repository.label = Repository konfigurieren -gui.action.configure_repository.mne = k -#gui.action.configure_repository.icon = server_edit.png -gui.action.configure_repository.tip = Vorhandene Repository-Konfiguration ändern. - -gui.action.open_repository_entry.label = Öffnen -gui.action.open_repository_entry.mne = f -#gui.action.open_repository_entry.icon = folder_open.png -gui.action.open_repository_entry.tip = Prozess öffnen oder Daten herunterladen und in der Ergebnisübersicht anzeigen. - -gui.dialog.error.error_rename.title = Fehler -gui.dialog.error.error_rename.message = Fehler bei Umbenennung von: {0} - -#gui.action.open_process_from_repository.label = Prozess öffnen -#gui.action.open_process_from_repository.mne = f -#gui.action.open_process_from_repository.icon = folder_open.png -#gui.action.open_process_from_repository.tip = Prozess von einem Repository-Server herunterladen und in RapidMiner öffnen. - -#gui.action.store_process_in_folder.label = Prozess speichern... -#gui.action.store_process_in_folder.mne = s -#gui.action.store_process_in_folder.icon = floppy_disk.png -#gui.action.store_process_in_folder.tip = Aktuellen Prozess in RapidMiner Server Repository hinaufladen. - -#gui.action.show_data_as_result.label = Als Ergebnis öffnen -#gui.action.show_data_as_result.mne = E -#gui.action.show_data_as_result.icon = presentation_chart.png -#gui.action.show_data_as_result.tip = Daten von einem Repository-Server herunterladen und in RapidMiner öffnen. - -gui.action.repository_refresh_folder.label = Aktualisieren -gui.action.repository_refresh_folder.mne = A -#gui.action.repository_refresh_folder.icon = folder_open_refresh.png -gui.action.repository_refresh_folder.tip = Daten in diesem Ordner aktualisieren. -#gui.action.repository_refresh_folder.acc = F5 - -gui.action.repository_open_in_filebrowser.label = In Dateimanager öffnen -gui.action.repository_open_in_filebrowser.mne = D -#gui.action.repository_open_in_filebrowser.icon = folder_open_view.png -gui.action.repository_open_in_filebrowser.tip = Öffnet den Ordner im Dateimanager des Betriebssystems. - -gui.action.repository_create_folder.label = Neuer Ordner -gui.action.repository_create_folder.mne = N -#gui.action.repository_create_folder.icon = folder_open_new.png -gui.action.repository_create_folder.tip = Neuen Unterordner hier erstellen. - -gui.action.repository_store_process.label = Prozess speichern unter... -gui.action.repository_store_process.mne = s -#gui.action.repository_store_process.icon = floppy_disk.png -gui.action.repository_store_process.tip = Aktuellen Prozess an gewählter Position speichern. - -gui.action.repository_copy_location.label = Position in die Zwischenablage kopieren -gui.action.repository_copy_location.mne = k -#gui.action.repository_copy_location.icon = copy.png -gui.action.repository_copy_location.tip = Position des Repository in die Zwischenablage kopieren. - -gui.action.repository_paste.label = Einfügen -#gui.action.repository_paste.acc = control V -#gui.action.repository_paste.icon = clipboard_paste.png -gui.action.repository_paste.tip = Inhalt der Zwischenablage einfügen. - -gui.action.repository_copy.label = Kopieren -#gui.action.repository_copy.acc = control C -#gui.action.repository_copy.icon = copy.png -gui.action.repository_copy.tip = Ausgewählten Inhalt in Zwischenablage kopieren. - -gui.action.repository_delete_entry.label = Löschen -gui.action.repository_delete_entry.mne = L -#gui.action.repository_delete_entry.acc = DELETE -#gui.action.repository_delete_entry.icon = folder_open_delete.png -gui.action.repository_delete_entry.tip = Ausgewählte Eingabe löschen. - -gui.action.repository_rename_entry.label = Umbenennen -gui.action.repository_rename_entry.mne = U -#gui.action.repository_rename_entry.acc = F2 -#gui.action.repository_rename_entry.icon = folder_open_edit.png -gui.action.repository_rename_entry.tip = Ausgewählte Eingabe umbenennen. - -gui.dialog.message.please_create_repository.title = Ausgangsrepository erstellen -gui.dialog.message.please_create_repository.message = Sie haben kein Repository für RapidMiner festgelegt. Dies kann möglich sein, wenn Sie RapidMiner zum ersten Mal benutzen. Bitte wählen Sie im nächsten Fenster einen Ort, um ein lokales Repository zu speichern und nutzten Sie dieses, um Ihre Daten und Prozesse zu speichern. Nur für Daten und Prozesse, die in diesem Repository gespeichert sind wird es möglich sein alle Funktionen von RapidMiner zu nutzen, besonders die neuen Regeln zur Transformation von Metadaten. - -gui.dialog.repositorydialog.title = Neues Repository -gui.dialog.repositorydialog.message = Geben Sie Parameter an, um ein neues lokales oder RapidMiner Server Repository zu erstellen. -#gui.dialog.repositorydialog.icon = server_add.png - -gui.dialog.repositoryconfigdialog.title = Repository konfigurieren -gui.dialog.repositoryconfigdialog.message = Geben Sie Parameter an, um Ihr Repository zu konfigurieren. -#gui.dialog.repositoryconfigdialog.icon = server_edit.png - -gui.label.repositorydialog.url.label = Repository URL: -gui.label.repositorydialog.root_directory.label = Root Adresse: -gui.label.repositorydialog.root_directory.mne = R -gui.label.repositorydialog.url.mne = d -gui.label.repositorydialog.alias.label = Alias: -gui.label.repositorydialog.alias.mne = A -gui.label.repositorydialog.user.label = Benutzer: -gui.label.repositorydialog.user.mne = B -gui.label.repositorydialog.password.label = Passwort: -gui.label.repositorydialog.password.mne = P -gui.label.repositorydialog.askpassword.message = Passwort von Benutzer {0} für Repository {1} nötig. -gui.dialog.add_repository.error = Repository kann nicht erstellt werden. - -gui.dialog.input.repository.new_folder.title = Neuer Ordner -#gui.dialog.input.repository.new_folder.icon = folder_open_new.png -gui.dialog.input.repository.new_folder.message = Bitte einen Namen für den neuen Ordner eingeben. - -gui.dialog.input.store_process.title = Prozess speichern -#gui.dialog.input.store_process.icon = floppy_disk.png -gui.dialog.input.store_process.message = Bitte einen Namen für den Prozess eingeben. - -gui.action.new_local_repositiory.label = Neues lokales Repository -gui.action.new_local_repositiory.mne = l -gui.action.new_remote_repositiory.label = Neues RapidMiner Server Repository -gui.action.new_remote_repositiory.mne = R - -#bis hier - -## Remote repository actions -gui.dialog.error.error_contacting_repository.title = RapidMiner Server Repository Fehler -gui.dialog.error.error_contacting_repository.message = Fehler beim Kontaktieren des RapidMiner Server Repository: {0} - -gui.dialog.error.schedule_on_ra_no_ra_repo_found.title = Kein RapidMiner Server Repository gefunden -gui.dialog.error.schedule_on_ra_no_ra_repo_found.message = Um einen Prozess mit RapidMiner Server auszuführen muss ein RapidMiner Server Repository vorhanden sein. Dieses können Sie im Repository-Browser hinzufügen. - - -gui.action.repository.new_revision.label = Starte neue Revision -gui.action.repository.new_revision.new = R -gui.action.repository.new_revision.tip = Neue Version dieses Eintrags starten. - -gui.dialog.repository.edit_access_rights.title = Zugriffsrechte editieren: {0} -gui.dialog.repository.edit_access_rights.message = Zugang für Eintrag {0} editieren. -#gui.dialog.repository.edit_access_rights.icon = key.png - -gui.action.repository.edit_access_rights.label = Zugriffsrechte editieren -gui.action.repository.edit_access_rights.mne = Z -#gui.action.repository.edit_access_rights.icon = key.png -gui.action.repository.edit_access_rights.tip = Erlaubnis diesen Eintrag zu editieren, zu überschreiben, zu lesen und auszuführen. - -gui.action.confirm.yes.label = Ja -#gui.action.confirm.yes.icon = ok.png -gui.action.confirm.no.label = Nein -#gui.action.confirm.no.icon = error.png - -#gui.dialog.confirm.icon = question.png - -gui.dialog.confirm.save_before_show_tutorial_process.title = Tutorial Prozess öffnen -#gui.dialog.confirm.save_before_show_tutorial_process.icon = floppy_disk.png -gui.dialog.confirm.save_before_show_tutorial_process.message = Aktuellen Prozess speichern bevor der Tutorial Prozess geöffnet wird? - -gui.dialog.confirm.show_tutorial_process.title = Tutorial Prozess öffnen -#gui.dialog.confirm.show_tutorial_process.icon = question.png -gui.dialog.confirm.show_tutorial_process.message = Den ausgewählten Tutorial Prozess öffnen? - -gui.action.start.without.extensions.label = Erweiterungen deaktivieren - -gui.action.start.normally.label = Normal starten - -gui.dialog.confirm.exit.title = RapidMiner beenden -#gui.dialog.confirm.exit.icon = door_exit.png -gui.dialog.confirm.exit.message = Wollen Sie RapidMiner wirklich beenden? - -gui.dialog.confirm.close_running_process.title = Laufenden Prozess abbrechen -#gui.dialog.confirm.close_running_process.icon = sign_warning.png -gui.dialog.confirm.close_running_process.message = Wenn Sie fortfahren, wird der laufende Prozess abgebrochen. Wirklich fortfahren? - -gui.dialog.confirm.exit_despite_running_process.title = RapidMiner beenden -#gui.dialog.confirm.exit_despite_running_process.icon = sign_warning.png -gui.dialog.confirm.exit_despite_running_process.message = Wollen Sie RapidMiner wirklich beenden und damit den laufenden Prozess abbrechen? - -gui.dialog.confirm.save.title = Änderungen speichern -#gui.dialog.confirm.save.icon = floppy_disk.png -gui.dialog.confirm.save.message = Änderungen speichern unter {0}? - -gui.dialog.close_all_results.title = Alle Ergebnisse schließen -gui.dialog.close_all_results.icon = question.png -gui.dialog.close_all_results.message = Wollen Sie wirklich alle geöffneten Ergebnisse schließen? - -gui.dialog.confirm.save_before_remote_run.title = Änderungen speichern und Prozess ausführen? -#gui.dialog.confirm.save_before_remote_run.icon = floppy_disk.png -gui.dialog.confirm.save_before_remote_run.message = Änderungen am Prozess müssen vor der Ausführung auf RapidMiner Server gespeichert werden (andernfalls würde die letzte Version ausgeführt). Prozess speichern und dann auf RapidMiner Server ausführen? - -gui.dialog.execute_process_remotely_now.title = Prozess auf RapidMiner Server ausführen -#gui.dialog.execute_process_remotely_now.icon = question.png -gui.dialog.execute_process_remotely_now.message = Den Prozess wirklich jetzt auf dem RapidMiner Server ausführen? - -gui.dialog.execute_process_remotely_hide_success.title = Verstecke Erfolgsmeldung beim nächsten Mal -gui.dialog.execute_process_remotely_hide_success.icon = question.png -gui.dialog.execute_process_remotely_hide_success.message = Der Prozess wird auf RapidMiner Server ausgeführt. Diese Meldung in Zukunft verstecken? - -gui.dialog.open_in_filebrowser.title = Verzeichnis in Dateimanager öffnen -#gui.dialog.open_in_filebrowser.icon = sign_warning.png -gui.dialog.open_in_filebrowser.message = Das Repository im Dateimanager zu öffnen und manuell zu editieren ist NICHT empfehlen und kann Datenverlust zur Folge haben! Desweiteren wird darauf hingewiesen das manuell hinzugefügte Dateien NICHT in RapidMiner angezeigt werden. Wollen Sie trotzdem fortfahren? - - -gui.dialog.confirm.overwrite_entry.title = Repositoryeintrag ersetzen -#gui.dialog.confirm.overwrite_entry.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite_entry.message = Soll {0} wirklich ersetzt werden? - -gui.dialog.confirm.overwrite_entry_different_type.title = Repositoryeintrag ersetzen -#gui.dialog.confirm.overwrite_entry_different_type.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite_entry_different_type.message = Der Eintrag {0} hat ein anderes Format als der neue Eintrag. Sind Sie wirklich sicher, dass Sie ihn ersetzen wollen? - - -gui.dialog.confirm.overwrite.title = Datei ersetzen -#gui.dialog.confirm.overwrite.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite.message = Soll {0} wirklich ersetzt werden? - -gui.dialog.confirm.editor.search_replace.no_more_hits.title = Kein Treffer -gui.dialog.confirm.editor.search_replace.no_more_hits.message = Es ergaben sich keine Üœbereinstimmungen. Soll von {0} gesucht werden? - -#gui.dialog.message.icon = information.png - - -#RepositoryBrowserDialog -gui.action.repository_select_location.label = Position auswählen -#gui.action.repository_select_location.icon = folder_open.png -gui.action.repository_select_location.mne = a - -gui.label.repository_location.location_entry_name.label = Name -gui.label.repository_location.location_entry_name.mne = N -gui.dialog.repository_location.location_invalid.icon = sign_warning.png -gui.dialog.repository_location.location_invalid_char.label = Ungültiger Name. Ungültiges Zeichen: {0} -gui.dialog.repository_location.location_invalid_empty.label = Name darf nicht leer sein. -gui.dialog.repository_location.location_invalid_no_selection.label = Vor dem Fortfahren bitte einen Ort in einem Repository auswählen. - -gui.dialog.repository_chooser.title = Repository Browser -#gui.dialog.repository_chooser.icon = server.png -gui.dialog.repository_chooser.message = Wählen Sie einen Ort für das Repository. - -gui.label.repository_chooser.entry_name.label = Name -gui.label.repository_chooser.entry_name.mne = N - -gui.label.repository_chooser.location.label = Ort - -gui.action.repository_chooser.resolve.label = Relativ zu {0} auflösen -gui.action.repository_chooser.resolve.mne = R -gui.action.repository_chooser.resolve.tip = Ausgewählte Elemente werden bei Aktivierung relativ zu diesem Ort aufgelöst. - -gui.dialog.error.repository_entry_already_exists.title = Eintrag vorhanden -gui.dialog.error.repository_entry_already_exists.message = Der Eintrag ''{0}'' existiert bereits und ist kein Prozess. - -gui.dialog.error.repository_folder_already_exists.title = Ordner vorhanden -gui.dialog.error.repository_folder_already_exists.message = Es existiert bereits ein Ordner mit dem Namen ''{0}''. - -gui.dialog.error.repository_entry_with_same_name_already_exists.title = Eintrag vorhanden -gui.dialog.error.repository_entry_with_same_name_already_exists.message = Das Repository enthält bereits einen Eintrag mit dem Namen''{0}''. Ein Order mit dem selben Namen kann nicht erstellt werden. - -gui.dialog.error.repository_move_same_folder.title = Identischer Zielort -gui.dialog.error.repository_move_same_folder.message = Der Ursprungs- und Zielort sind identisch, Eintrag verschieben nicht möglich. - -gui.dialog.error.repository_copy_same_folder.title = Identischer Zielort -gui.dialog.error.repository_copy_same_folder.message = Der Ursprungs- und Zielort sind identisch, Eintrag kopieren nicht möglich. - -gui.dialog.error.repository_move_into_subfolder.title = Ungültiger Zielort -gui.dialog.error.repository_move_into_subfolder.message = Der Zielort ist ein Unterordner des Ursprungsortes, Eintrag verschieben nicht möglich. - -gui.dialog.error.repository_copy_into_subfolder.title = Ungültiger Zielort -gui.dialog.error.repository_copy_into_subfolder.message = Der Zielort ist ein Unterordner des Ursprungsortes, Eintrag kopieren nicht möglich. - - -#RunRemoteDialog -gui.dialog.runremotedialog.title = Prozess ferngesteuert laufen lassen -#gui.dialog.runremotedialog.icon = server2_play.png -gui.dialog.runremotedialog.message = Planen Sie den Durchlauf des Prozesses auf einem Server. Sollten Sie einen anderen Kontext für den Prozess wünschen, als die Grundeinstellungen, können Sie ihre Änderungen in den entsprechenden Zeilen vornehmen. - -gui.tabs.runremotedialog.schedule.label = Zeiplan -gui.tabs.runremotedialog.schedule.mne = Z -gui.tabs.runremotedialog.schedule.tip = Server und Zeit der Ausführung wählen -#gui.tabs.runremotedialog.schedule.icon = server2_play.png - -gui.tabs.runremotedialog.context.label = Kontext -gui.tabs.runremotedialog.context.mne = K -gui.tabs.runremotedialog.context.tip = Kontext der Prozessausführung festlegen. -#gui.tabs.runremotedialog.context.icon = environment.png - -gui.label.context.input.label = Prozesseingaben -#gui.label.context.input.icon = 16/plug_next.png -gui.label.context.output.label = Prozessausgabe -#gui.label.context.output.icon = 16/plug_previous.png - -gui.label.macros.label = Makros -#gui.label.macros.icon = 16/keyboard_key_a.png - -gui.action.macros.add_macro.label = Makro hinzufügen -gui.action.macros.add_macro.mne = h -gui.action.macros.add_macro.tip = Liste ein Makro hinzufügen. -#gui.action.macros.add_macro.icon = keyboard_key_a_add.png - -gui.action.macros.delete_macro.label = Makro löschen -gui.action.macros.delete_macro.mne = l -gui.action.macros.delete_macro.tip = Ausgewähltes Makro von der Liste löschen. -#gui.action.macros.delete_macro.icon = keyboard_key_a_delete.png - -gui.label.processcontext_help.help = In diesem Fenster k\u00F6nnen Sie den Kontext in dem der Prozess l\u00E4uft ver\u00E4ndern.Dies ist besonders n\u00FCtzlich, wenn der Prozess in unterschiedlichen Umgebungen ausgef\u00FChrt wird, z.B. selbsst\u00E4ndiges oder eingebettetes System, lokale oder ferngesteuerte Bedienung oder als angebotene Leistung. -gui.action.context.apply.label = Anwenden -gui.action.context.apply.mne = A -gui.action.context.apoply.tip = Änderungen anwenden -#gui.action.context.apply.icon = check.png - -gui.action.context.input.add_row.label = Anschluss hinzufügen -gui.action.context.input.add_row.tip = Neue Prozessquelle hinzufügen. -#gui.action.context.input.add_row.icon = plug_add.png - -gui.action.context.input.delete_row.label = Anschluss löschen -gui.action.context.input.delete_row.tip = Ausgewählte Prozessquelle löschen. -#gui.action.context.input.delete_row.icon = plug_delete.png - -gui.action.context.output.add_row.label = Anschluss hinzufügen -gui.action.context.output.add_row.tip = Neue Prozesssenke hinzufügen. -#gui.action.context.output.add_row.icon = plug_add.png - -gui.action.context.output.delete_row.label = Anschluss löschen -gui.action.context.output.delete_row.tip = Ausgewählte Prozesssenke löschen. -#gui.action.context.output.delete_row.icon = plug_delete.png - -gui.label.runremotedialog.repository.label = Repository -gui.label.runremotedialog.repository.mne = R -#gui.label.runremotedialog.repository.icon = data.png -gui.label.runremotedialog.date.label = Datum -gui.label.runremotedialog.date.mne = D -#gui.label.runremotedialog.date.icon = 16/clock_run.png -gui.label.runremotedialog.cronexpression.label = Ausdruck -gui.label.runremotedialog.cronexpression.mne = u -#gui.label.runremotedialog.cronexpression.icon = 16/calendar_clock.png -gui.label.runremotedialog.process_location.label = Prozessposition -gui.label.runremotedialog.process_location.mne = P - -gui.action.runremotedialog.now.label = Jetzt -gui.action.runremotedialog.now.mne = J -#gui.action.runremotedialog.now.icon = media_play.png -gui.action.runremotedialog.now.tip = Prozess sofort ausführen. - -gui.action.runremotedialog.once.label = einmalig -gui.action.runremotedialog.once.mne = e -gui.action.runremotedialog.once.tip = Prozess einmal zu einem späteren Zeitpunkt ausführen. - -gui.action.runremotedialog.cron.label = Cron Zeitplan -gui.action.runremotedialog.cron.mne = C -gui.action.runremotedialog.cron.tip = Cron-Ausdruck eingeben, um die mehrfache Ausführung des Prozesses zu planen. - -gui.action.runremotedialog.cronstart.label = Start -gui.action.runremotedialog.cronstart.mne = S -gui.action.runremotedialog.cronstart.tip = Ersten Zeitpunkt der Ausführung eingeben. - -gui.action.runremotedialog.cronend.label = Ende -gui.action.runremotedialog.cronend.mne = E -gui.action.runremotedialog.cronend.tip = Letzter Zeitpunkt der Ausführung eingeben. - -gui.action.cron_help.label = Was ist das? -gui.action.cron_help.mne = W -#gui.action.cron_help.icon = question.png -gui.dialog.message.cron_long_help.title = Cron-Ausdrücke -gui.dialog.message.cron_long_help.message = Das Format aller Daten ist tt-MM-jjjj HH\:mm\:ss. Cron-Ausdr\u00FCcke bestehen aus sechs oder sieben mit Leerzeichen getrennten Feldern\:
     Sekunden Minuten Stunden TagimMonat Monat TagderWoche [Jahr].
    Jedes Feld kann eine Nummer sein, wobei Januar und Sonntag jeweils die 1 sind. TagderWoche kann Son-Sam und Monat kann JAN-DEZ sein. Aufz\u00E4hlungen werden durch ein Komma (,) getrennt und Bereiche durch Bindestriche (-) definiert. Das Sternchen (*) passt zu allen Werten und f\u00FCr TagderWoch und TagimMonat bedeutet ein Fragezeichen (?) "kein spezifischer Wert". Intervalle werden mit einem forward Slash (/) angegeben, z.B. bedeutet 0/5 im Minuten Feld alle f\u00FCnf Minuten, angefangen bei Null. F\u00FCr TagimMonat, w\u00E4hlt L den letzten Tag im Monat und ein Nachsilbe am W legt den n\u00E4chstliegenden Wochentag fest. Einem TagderWoche kann ein \#n anh\u00E4ngen, um das nte Vorkommen dieses Tages im Monat festzulegen und L um das letzte festzulegen. - - -#RemoteProcessViewer, RemoteEntry, and AccessRightsDialog -gui.action.remoteprocessviewer.open.label = Öffnen -#gui.action.remoteprocessviewer.open.icon = folder_open.png -gui.action.remoteprocessviewer.open.mne = f -gui.action.remoteprocessviewer.open.tip = Ausgewählten Prozess oder IO Objekt in RapidMiner öffnen. - -gui.action.remoteprocessviewer.browse.label = Browser -#gui.action.remoteprocessviewer.browse.icon = window_earth.png -gui.action.remoteprocessviewer.browse.mne = B -gui.action.remoteprocessviewer.browse.tip = Ausgewählten Prozess oder IO Objekt in einem Internet Browser öffnen. - -gui.action.remoteprocessviewer.stop.label = Stop -#gui.action.remoteprocessviewer.stop.icon = media_stop.png -gui.action.remoteprocessviewer.stop.mne = S -gui.action.remoteprocessviewer.stop.tip = Ausgewählten Remoteprozess stoppen. - -gui.action.remoteprocessviewer.show_log.label = Log anzeigen -#gui.action.remoteprocessviewer.show_log.icon = history.png -gui.action.remoteprocessviewer.show_log.mne = L -gui.action.remoteprocessviewer.show_log.tip = Logverlauf dieses Prozesses anzeigen. - -gui.label.remoteprocessviewer.filter.label = Filtern -gui.label.remoteprocessviewer.filter.mne = F -#gui.label.remoteprocessviewer.filter.icon = funnel.png -gui.combo.remoteprocessviewer.since_session_start = Sitzung -gui.combo.remoteprocessviewer.for_today = Heute -gui.combo.remoteprocessviewer.all = Alle - -gui.action.remoterepository.administer.label = Administrieren (Netzinterface) -#gui.action.remoterepository.administer.icon = control_panel.png -gui.action.remoterepository.administer.mne = A -gui.action.remoterepository.administer.tip = Repository administrieren durch Benutzung des Netzinterface. - -gui.dialog.error.remoteprocessviewer.stop_failed.title = Stop fehlgeschlagen -gui.dialog.error.remoteprocessviewer.stop_failed.message = Remoteprozess konnte nicht gestoppt werden: {0} - -gui.action.accessrights.add_row.label = Zeile hinzufügen -#gui.action.accessrights.add_row.icon = table_selection_row_add.png -gui.action.accessrights.add_row.mne = h -gui.action.accessrights.add_row.tip = Tabelle eine Genehmigungszeile hinzufügen. - -gui.action.accessrights.remove_row.label = Zeile entfernen -#gui.action.accessrights.remove_row.icon = table_selection_row_delete.png -gui.action.accessrights.remove_row.mne = t -gui.action.accessrights.remove_row.tip = Genehmigung der ausgewählten Zeile entfernen. - -#DecisionRememberingConfirmDialog -gui.action.remember_decision.label = Entscheidung speichern -gui.action.remember_decision.mne = s -gui.action.remember_decision.tip = Bei Aktivierung wird die Antwort dieser Frage in Ihrer Datei für Einstellungen gespeichert. - -gui.action.yes.label = Ja -gui.action.yes.mne = J -#gui.action.yes.icon = ok.png -gui.action.yes.tip = Zustimmen - -gui.action.no.label = Nein -gui.action.no.mne = N -#gui.action.no.icon = error.png -gui.action.no.tip = Ablehnen - -gui.dialog.show_results_on_creation.title = Neue Ergebnisse -#gui.dialog.show_results_on_creation.icon = presentation_chart.png -gui.dialog.show_results_on_creation.message = Es wurden neue Ergebnisse erzeugt. Wollen Sie zur Ergebnisübersicht wechseln? - -gui.dialog.save_before_run.title = Speichern -#gui.dialog.save_before_run.icon = floppy_disk.png -gui.dialog.save_before_run.message = Wollen Sie den Prozess speichern bevor er ausgeführt wird? - -gui.dialog.save_over_with_new_version.title = Sicheres überschreiben mit neuer Version? -#gui.dialog.save_over_with_new_version.icon = floppy_disk.png -gui.dialog.save_over_with_new_version.message = Die Prozessdatei mit der Sie arbeiten enthält einen Prozess mit veraltetem RapidMiner-Format. Stellen Sie bitte sicher, dass der Prozess richtig in die aktuelle Version importiert wurde bevor Sie ihn überschreiben. Möchten Sie nun fortfahren? - -######################################### -# Miscellaneous Dialogs -######################################### - -## UpdateDialog -gui.action.update_manager.label = RapidMiner aktualisieren... -#gui.action.update_manager.icon = download.png -gui.action.update_manager.mne = a -gui.action.update_manager.tip = RapidMiner und Erweiterungen installieren. - -gui.dialog.error.update_error_development_build.title = Aktualisierungs Manager -gui.dialog.error.update_error_development_build.message = Dies scheint eine Entwicklungsversion von RapidMiner zu sein. Aktualisierung ist nicht möglich. - -gui.dialog.update.title = RapidMiner Marktplatz -gui.dialog.update.message = W\u00E4hlen Sie unten die zu aktualisierenden und installierenden Module aus. Bei den Einstellungen k\u00F6nnen Sie ausw\u00E4hlen, ob Erweiterungen global (standard) oder im Benutzerverzeichnis installiert werden sollen. Aktualisierungen von RapidMiner werden immer global installiert. Jede globale Aktualisierung muss als Administrator ausgef\u00FChrt werden, sowohl w\u00E4hrend der Aktualisierung als auch beim anschlie\u00DFenden Neustart. -#gui.dialog.update.icon = download.png - -gui.action.install.select.label = Makieren/Demarkieren -#gui.action.install.select.icon = checkbox.png -gui.action.install.select.mne = M -gui.action.install.select.tip = Aktuelles Element zur Installation markieren oder demarkieren. - -gui.action.update.select.label = Makieren/Demarkieren -#gui.action.update.select.icon = checkbox.png -gui.action.update.select.mne = M -gui.action.update.select.tip = Aktuelles Element zur Aktualisierung markieren oder demarkieren. - -gui.action.update.purchase.label = Erweiterung kaufen -gui.action.update.purchase.mne = K - -gui.label.update.need_to_log_in.label = Einloggen um die kommerzielle Erweiterung zu installieren. -gui.label.update.extension_homepage.label = Besuche die Erweiterungs Homepage -gui.label.update.product_homepage.label = Besuhe die Produkt Homepage - -gui.action.update.fetch_bookmarks.label = Lesezeichen abrufen -#gui.action.update.fetch_bookmarks.icon = bookmark.png -gui.action.update.fetch_bookmarks.mne = L -gui.action.update.fetch_bookmarks.tip = Lesezeichen werden von Ihrem Account bei rapidupdate.de abgerufen. Es wird nach einem Benutzernamen und Passwort gefragt. - -gui.action.update.install.label = Installieren -#gui.action.update.install.icon = download.png -gui.action.update.install.mne = I -gui.action.update.install.tip = Ausgewählte Module installieren/aktualisieren - -gui.dialog.error.error_during_update.title = Aktualisierung fehlgeschlagen -gui.dialog.error.error_during_update.message = Fehler beim Aufrufen des Servers für Aktualisierungen: {0} - -gui.dialog.error.error_accessing_marketplace_account.title = Keine Verbundung zum Marktplatzkonto -gui.dialog.error.error_accessing_marketplace_account.message = Fehler bei der Verbindung zum Marktplatzkonto. Fehlernachricht lautete\: {0} - -gui.dialog.error.failed_update_server.title = Aktualisierung fehlgeschlagen -gui.dialog.error.failed_update_server.message = Server für Aktualisierungen ''{0}'' konnte nicht erreicht werden. Bitte überprüfen Sie Ihre Internetverbindung. - -gui.dialog.error.failed_update_server_simple.title = Aktualisierung fehlgeschlagen -gui.dialog.error.failed_update_server_simple.message = Marketplace-Server für Aktualisierungen konnte nicht erreicht werden. Bitte überprüfen Sie Ihre Internetverbindung. - -gui.dialog.confirm.update.complete_restart.title = Aktualisierung vollständig -gui.dialog.confirm.update.complete_restart.message = Aktualisierung wurde erfolgreich heruntergeladen. Damit die \u00C4nderungen \u00FCbernommen werden k\u00F6nnen ist ein Neustart erforderlich. M\u00F6chten Sie RapidMiner jetzt neu starten? - -gui.dialog.error.error_installing_update.title = Aktualisierung fehlgeschlagen -gui.dialog.error.error_installing_update.message = Fehler bei der Installierung der Aktualisierung: {0}. Stellen Sie bitte sicher, dass Sie RapidMiner als Administrator ausführen, sollten Sie globale Aktualisierungen installieren. - -# Dies ist zur Zeit eine nicht benutzte Funktion. Keine Sorge. RapidMiner ist weiterhin und wird immer -# open source und kostenlos sein. Trotzdem werden zukünftige Erweiterungen, wie die Verbindung zu SAP -# oder anderen Datenquellen, geschütze Treiber mit teuren Lizenzgebühren benötigen. Dies wird dann nur auf -# komerzieller Basis zur Verfügung stehen, aus naheliegenden Gründen :-) - -gui.dialog.message.purchase_package.title = {0} kaufen -gui.dialog.message.purchase_package.message = Wenn Sie die Erweiterung {0} für RapidMiner kaufen möchten, klicken Sie bitte auf den link "Diese Erweiterung bestellen" unter der Beschreibung der Erweiterung oder besuchen Sie unseren Shop auf www.rapidminer.com. - -#bis hier - -gui.progress.check_for_updates.label = Suche nach Aktualisierungen -gui.progress.fetching_updates.label = Lade Aktualisierungen -gui.progress.installing_updates.label = Installiere Aktualisierungen - -gui.dialog.confirm.updates_exist.title = Aktualisiere RapidMiner -#gui.dialog.confirm.updates_exist.icon = package_add.png -gui.dialog.confirm.updates_exist.message = Es gibt für RapidMiner neue Aktualisierungen. Möchten Sie den Aktualisierungsverwalter öffnen? Das automatische Suchen nach Aktualisierungen kann in den Eigenschaften deaktiviert werden. - -## ExtensionDialog -gui.dialog.manage_extensions.title = Erweiterungen verwalten -gui.dialog.manage_extensions.message = Installierte Erweiterungen können unten ein- und ausgeschaltet werden. Sollten mehrere Versionen der selben Erweiterung installiert sein, können Sie wählen welche tatsächlich genutzt wird. Jede Ä„nderung benötigt einen Neustart von RapidMiner. Stellen Sie bitte sicher, dass Sie RapidMiner als Administrator ausführen, wenn Sie globale Änderungen an installierten Erweiterungen vornehmen. -#gui.dialog.manage_extensions.icon = piece2_edit.png - -gui.action.manage_extensions.label = Erweiterungen verwalten... -gui.action.manage_extensions.mne = v -#gui.action.manage_extensions.icon = piece2_edit.png - -gui.action.uninstall_extension.label = -#gui.action.uninstall_extension.icon = piece2_delete.png -gui.action.uninstall_extension.tip = Alle mit der ausgewählten Version dieser Erweiterung installierten Dateien löschen. - -gui.dialog.confirm.really_uninstall_extension.title = Deinstallierung bestätigen -gui.dialog.confirm.really_uninstall_extension.message = Alle zu Erweiterung {0} gehörenden Dateien werden gelöscht. Möchten Sie nun fortfahren? - -gui.action.menu.about_extensions.label = Informationen über installierte Erweiterungen -gui.action.menu.about_extensions.mne = E -#gui.action.menu.about_extensions.icon = pieces.png - -gui.dialog.confirm.manage_extensions.restart.title = Neustart erforderlich -gui.dialog.confirm.manage_extensions.restart.message = Damit die Änderungen in Kraft treten können muss RapidMiner neu gestartet werden. Möchten Sie jetzt neu starten? - -gui.label.no_extensions_installed.label = Es sind keine Erweiterungen installiert. Benutzten Sie den Aktualisierungsverwalter, um Erweiterungen zu installieren. - -gui.dialog.error.error_uninstalling_extension.title = Deinstallierung fehlgeschlagen -gui.dialog.error.error_uninstalling_extension.message = Deinstallierung ist fehlgeschlagen. Sollten Sie eine global installierte Erweiterung deinstallieren, stellen Sie bitte sicher, dass Sie RapidMiner als Administrator ausführen. - -gui.dialog.update.tab.updates = Updates -gui.dialog.update.tab.top_downloads = Top Downloads -gui.dialog.update.tab.top_rated = Top Bewertungen -gui.dialog.update.tab.purchased = Erworben -gui.dialog.update.tab.bookmarks = Lesezeichen -gui.dialog.update.tab.search = Suche - -gui.dialog.update.tab.search.search_button = Suchen -gui.dialog.update.box.description.title = Beschreibung - -gui.dialog.update.tab.updates.update_all_button = Wähle alle Aktualisierungen - -gui.field.update.search.tip = Gib einen Suchbegriff ein, drücke dann auf Ender oder den Such-Knopf um nach Erweiterungen zu suchen. -gui.dialog.update.tab.loading = Lade Erweiterungen... {0}% -gui.dialog.update.tab.no_packages = Keine Erweiterungen verfügbar. -gui.dialog.update.tab.search.no_results = Die Suche ergab keine Treffer. - -gui.dialog.update.account_button.logged_in = Sie sind eingeloggt als {0}. (Ausloggen) -gui.dialog.update.account_button.logged_out = Sie sind nicht eingeloggt. (Einloggen) - -# ExtensionPurchasedButNotInstalledDialog - -gui.dialog.purchased_not_installed.title = Installiere erworbene Erweiterungen -gui.dialog.purchased_not_installed.message = Es scheint, als ob Sie vor kurzem eine oder mehrere Erweiterungen erworben haben, die noch nicht installiert wurden. Diese Erweiterungen sind hier aufgelistet. -#gui.dialog.purchased_not_installed.icon = download.png - -gui.dialog.purchased_not_installed.should_install = Möchen Sie diese Erweiterungen jetzt installieren? -gui.dialog.purchased_not_installed.not_check_on_startup = Beim Starten nicht überprüfen. - -gui.action.ask_later.label = Später erinnern -gui.action.ask_later.tip = Schließt den Dialog und fragt später noch einmal. -#gui.action.ask_later.acc = ESCAPE -#gui.action.ask_later.icon = timer.png - -gui.action.ask_never.label = Nein -gui.action.ask_never.tip = Schließt den Dialog. -#gui.action.ask_never.icon = error.png - -## ConfirmLicenseDialog - -gui.dialog.confirm_license.title = Nutzungsbedingungen -gui.dialog.confirm_license.message = Damit Sie {0} installieren können, müssen Sie die folgenden Nutzungsbedingungen akzeptieren. - -gui.action.accept_license.label = Ich akzeptiere die Nutzungsbedingungen. -gui.action.accept_license.mne = a -#gui.action.accept_license.icon = ok.png -gui.action.accept_license.tip = Werden Nutzungsbedingungen nicht akzeptieren wird die Installation des Pakets übersprungen. - -gui.action.reject_license.label = Ich akzeptiere nicht die Nutzungsbedingungen. -gui.action.reject_license.mne = n -#gui.action.reject_license.icon = delete.png - -gui.action.skip_install.label = Nicht installieren -gui.action.skip_install.mne = N -gui.action.skip_install.tip = Diese Erweiterung nicht installieren. -#gui.action.skip_install.icon = delete.png - -## PasswordDialog - -gui.dialog.authentication.title = Authentifikation benötigt -#gui.dialog.authentication.icon = key.png -gui.dialog.authentication.message = Benutzername und Passwort sind nötig, um {0} aufzurufen. - -gui.label.authentication.username.label = Benutzername -gui.label.authentication.username.mne = B -gui.label.authentication.username.tip = Bitte geben Sie ihren Benutzernamen für {0} ein. - -gui.label.authentication.password.label = Passwort -gui.label.authentication.password.mne = P -gui.label.authentication.password.tip = Bitte geben Sie ihr Passwort für {0} ein. - -gui.action.authentication.remember.label = Passwort speichern -gui.action.authentication.remember.mne = s -gui.action.authentication.remember.tip = Bei aktivierung wird das Passwort dauerhaft gespeichert. - -## UsageStatistics transmission / TransmissionDialog -gui.dialog.transmit_usage_statistics.title = Benutzungsstatistik der Operatoren übertragen -#gui.dialog.transmit_usage_statistics.icon = chart_column.png -gui.dialog.transmit_usage_statistics.message = Das Entwicklerteam von RapidMiner bittet Sie die Benutzungsstatistik der Operatoren zu \u00FCbertragen, um RapidMiner weiterhin verbessern zu k\u00F6nnen. RapidMiner respektiert dabei die Privatsph\u00F6re der RapidMiner Benutzer. Es werden keine vertraulichen Daten \u00FCbermittelt. Alle \u00FCbermittelten Daten sind in der Tabelle unten aufgelistet. Soe k\u00F6nnen diese Informationen jederzeit anzeigen, indem Sie 'Benutzungsstatistik anzeigen' im 'Werkzeuge' Men\u00FC ausw\u00E4hlen. Sollten Sie die Option 'Nie' ausw\u00E4hlen k\u00F6nnen Sie dies in den Einstellungen wieder \u00E4ndern. - -gui.action.never.label = Nie -#gui.action.never.icon = error.png -gui.action.never.mne = i -gui.action.never.tip = Antwort ''Nein'' und kein weiteres Mal fragen. - -gui.action.always.label = Immer -#gui.action.always.icon = ok.png -gui.action.always.mne = m -gui.action.always.tip = Antwort ''Ja'' und kein weiteres Mal fragen - -gui.action.no_later.label = Später nachfragen -#gui.action.no_later.icon = question.png -gui.action.no_later.mne = S -gui.action.no_later.tip = Antwort ''Nein'' und zu einem späteren Zeitpunkt erneut fragen. - -gui.action.yes_later.label = Ja -#gui.action.yes_later.icon = nav_refresh.png -gui.action.yes_later.mne = J -gui.action.yes_later.tip = Antwort ''Ja'' und zu einem späteren Zeitpunkt erneut fragen. - -gui.progress.transmit_usagestats.label = Statistik senden - -#gui.action.content_assist.icon = magic_wand.png -gui.action.content_assist_enabled.tip = Klicken um inhaltsgestützte Eingabehilfe anzuzeigen. -gui.action.content_assist_disabled.tip = Keine inhaltsgestützte Eingabehilfe verfügbar. - -gui.action.regex_description.label = - -gui.action.date_picker.tip = Bitte das Datum auswählen. - -## Table Panel -gui.label.table_panel.no_content_assist_items.title = Kein Inhalt -gui.label.table_panel.no_content_assist_items.tip = Keine inhaltsgestützten Daten verfügbar. - -## Custom Filters -gui.comparator.numerical.equals.label = = -gui.comparator.numerical.equals.tip = Erlaubt nichts außer den gewählten exakten numerischen Wert. -gui.comparator.numerical.not_equals.label = \u2260 -gui.comparator.numerical.not_equals.tip = Erlaubt alles außer den gewählten exakten numerischen Wert. -gui.comparator.numerical.less.label = < -gui.comparator.numerical.less.tip = Erlaubt nur Werte kleiner als der gewählte numerische Wert. -gui.comparator.numerical.less_equals.label = \u2264 -gui.comparator.numerical.less_equals.tip = Erlaubt nur Werte kleiner oder gleich dem gewählten numerischen Wert. -gui.comparator.numerical.greater_equals.label = \u2265 -gui.comparator.numerical.greater_equals.tip = Erlaubt nur Werte größer oder gleich dem gewählten numerischen Wert. -gui.comparator.numerical.greater.label = > -gui.comparator.numerical.greater.tip = Erlaubt nur Werte größer als der gewählte numerische Wert. - -gui.comparator.nominal.equals.label = ist gleich -gui.comparator.nominal.equals.tip = Erlaubt nichts außer den gewählten exakten nominalen Wert. -gui.comparator.nominal.not_equals.label = ist nicht gleich -gui.comparator.nominal.not_equals.tip = Erlaubt alles außer den gewählten exakten nominalen Wert. -gui.comparator.nominal.is_in.label = ist in -gui.comparator.nominal.is_in.tip = Erlaubt nichts au\u00DFer den gew\u00E4hlten exakten nominalen Werten. Syntax\: 'wert1;wert2;wertX'. Semikolons die kein Trennsymbol sind m\u00FCssen zu '\\;' ge\u00E4ndert werden. -gui.comparator.nominal.is_not_in.label = ist nicht in -gui.comparator.nominal.is_not_in.tip = Erlaubt alles au\u00DFer den gew\u00E4hlten exakten nominalen Werten. Syntax\: 'wert1;wert2;wertX'. Semikolons die kein Trennsymbol sind m\u00FCssen zu '\\;' ge\u00E4ndert werden. -gui.comparator.nominal.contains.label = enthält -gui.comparator.nominal.contains.tip = Erlaubt nichts außer Werten die den gewählten nominalen Wert enthalten. -gui.comparator.nominal.not_contains.label = enthält nicht -gui.comparator.nominal.not_contains.tip = Erlaubt alles außer Werten die den gewählten nominalen Wert enthalten. -gui.comparator.nominal.starts_with.label = beginnt mit -gui.comparator.nominal.starts_with.tip = Erlaubt nichts außer Werten die mit dem gewählten nominalen Wert beginnen. -gui.comparator.nominal.ends_with.label = endet mit -gui.comparator.nominal.ends_with.tip = Erlaubt nichts außer Werten die mit dem gewählten nominalen Wert enden. -gui.comparator.nominal.regex.label = stimmt überein mit -gui.comparator.nominal.regex.tip = Erlaubt nichts außer Werten die mit dem gewählten regulären Ausdruck übereinstimmen. - -gui.comparator.special.is_missing.label = fehlender Wert -gui.comparator.special.is_missing.tip = Erlaubt nichts außer fehlende Werte. -gui.comparator.special.is_not_missing.label = kein fehlender Wert -gui.comparator.special.is_not_missing.tip = Erlaubt alles außer fehlende Werte. - -## ProcessInfoScreen -gui.dialog.process_info.title = Prozessinformation -#gui.dialog.process_info.icon = information.png -gui.dialog.process_info.message = Information über Prozess {0}. - -## ToolTipDialog -gui.label.F3_for_focus.label = ''F3'' zur Fokussierung drücken. - -## QuickFixDialog -gui.dialog.quick_fix_dialog.title = Schnelllösungen -gui.dialog.quick_fix_dialog.message = Schnelllösungen aus der Liste unten auswählen und anwenden. -#gui.dialog.quick_fix_dialog.icon = first_aid.png - -gui.action.apply_quick_fix.label = Anwenden -gui.action.apply_quick_fix.mne = A -#gui.action.apply_quick_fix.icon = check.png -gui.action.apply_quick_fix.tip = Ausgewählte Schnelllösung anwenden. - -gui.dialog.error.quickfix_failed.title = Schnelllösung fehlgeschlagen -gui.dialog.error.quickfix_failed.message = Schnelllösung schlug fehl: {0} - -## Anova Calculator -gui.dialog.anova_calculator.title = ANOVA Rechner -gui.dialog.anova_calculator.message = Dieses Fenster ermöglicht die Durchführung eines ANOVA Tests. -#gui.dialog.anova_calculator.icon = scales.png - -gui.action.anova_calculator.clear.label = Löschen -#gui.action.anova_calculator.clear.icon = erase.png -gui.action.anova_calculator.clear.mne = L -gui.action.anova_calculator.clear.tip = Matrix löschen. - -gui.action.anova_calculator.calculate.label = Berechnen... -#gui.action.anova_calculator.calculate.icon = scales.png -gui.action.anova_calculator.calculate.mne = B -gui.action.anova_calculator.calculate.tip = ANOVA Berechnung durchführen. - -gui.action.anova_calculator.add_row.label = Zeile hinzufügen -#gui.action.anova_calculator.add_row.icon = table_selection_row_add.png -gui.action.anova_calculator.add_row.mne = h -gui.action.anova_calculator.add_row.tip = Tabelle eine Zeile hinzufügen. - -gui.action.anova_calculator.remove_row.label = Zeile entfernen -#gui.action.anova_calculator.remove_row.icon = table_selection_row_delete.png -gui.action.anova_calculator.remove_row.mne = t -gui.action.anova_calculator.remove_row.tip = Ausgewählte Zeile entfernen. - -gui.dialog.results.anova.title = Ergebnis des ANOVA Tests -gui.dialog.results.anova.message = Ergebnisse des Anova Tests können unten angesehn werden. - - -gui.dialog.data_import_wizard.title = Assistent zum Importieren von Daten -gui.dialog.data_import_wizard.message = Dieser Assistent hilft Ihnen beim Importieren von Daten. -#gui.dialog.data_import_wizard.icon = magic_wand.png - - - -## AnnotationsRenderer -gui.action.add_annotation.label = Anmerkung hinzufügen -gui.action.add_annotation.mne = h -gui.action.add_annotation.tip = Diesem Objekt eine Anmerkung hinzufügen. -#gui.action.add_annotation.icon = table_selection_row_add.png - -gui.action.delete_annotation.label = Anmerkung löschen -gui.action.delete_annotation.mne = l -gui.action.delete_annotation.tip = Eine Anmerkung zu diesem Objektes löschen. -#gui.action.delete_annotation.icon = table_selection_row_delete.png - -gui.dialog.input.select_annotation.title = Anmerkung auswählen -gui.dialog.input.select_annotation.message = Anmerkung, die dem Obejekt hinzugefügt werden soll auswählen. -#gui.dialog.input.select_annotation.icon = table_selection_row_add.png - -## -gui.dialog.import_message.title = Prozess Import Nachrichten -#gui.dialog.import_message.icon = information.png -gui.dialog.import_message.message = Eine Liste mit Nachrichten, die während des Impoortes der Prozessdatei erstellt wurden, wird unten angezeigt. Sie beinhaltet alle Änderungen, die aufgrund der Veränderungen von früheren RapidMiner Versionen zur jetzigen vorgenommen wurden und hilft dabei mögliche Probleme, die während des Imports auftraten, zu lösen. Sollten diese Nachrichten nicht rot makiert sein, können Sie sie ignorieren. - -gui.dialog.operator_info.title = Operator Information -#gui.dialog.operator_info.icon = question.png - -gui.dialog.parameter.list.title = Parameter Liste ändern -#gui.dialog.parameter.list.icon = notebook_edit.png - -gui.dialog.parameter.text.title = Parameter Text ändern -#gui.dialog.parameter.text.icon = notebook_edit.png - -gui.dialog.parameter.sql.title = SQL Query erstellen -#gui.dialog.parameter.sql.icon = code_edit.png - -gui.dialog.parameter.parameter_optimization.title = Parameter auswählen -#gui.dialog.parameter.parameter_optimization.icon = form_edit.png - -gui.dialog.error.parameter_grid.title = Wert ungültig -gui.dialog.error.parameter_grid.message = Der eingegebene Wert ''{1}'' ist ungültig. Nur Zahlen oder Makros sind als {0} erlaubt. - -#gui.dialog.building_block.source.icon = user.png -gui.dialog.building_block.source.tip = Benutzerdefinierter Baustein. - -gui.dialog.new_building_block.title = Neuer Baustein -#gui.dialog.new_building_block.icon = box_open_new.png -gui.dialog.new_building_block.message = Bitte Baustein auswählen, der dem Prozess hinzugefügt werden soll. - -gui.dialog.manage_building_blocks.title = Bausteine verwalten -#gui.dialog.manage_building_blocks.icon = box_open_edit.png -gui.dialog.manage_building_blocks.message = Diese Fenster ermöglicht das Verändern von benutzerdefinierten Bausteinen. -gui.action.delete_building_block.label = Löschen -gui.action.delete_building_block.mne = L -#gui.action.delete_building_block.icon = box_open_delete.png -gui.action.delete_building_block.tip = Diesen Baustein löschen. - -gui.dialog.save_building_block.title = Baustein speichern -#gui.dialog.save_building_block.icon = box_open_add.png -gui.dialog.save_building_block.message = Diesen Operator mit seinen Parametern und untergeordneten Prozessen als Baustein speichern, sodass zukünftige Prozessaufbauten erleichtert werden. Bitte geben Sie einen Namen und eine kurze Beschreibung des Bausteins ein. - -gui.label.save_building_block.name.label = Name -gui.label.save_building_block.name.tip = Name des Bausteins. - -gui.label.save_building_block.description.label = Beschreibung -gui.label.save_building_block.description.tip = Kurze Beschreibung des Bausteins. - -gui.dialog.error.save_building_block.name_used.title = Speichern fehlgeschlagen -gui.dialog.error.save_building_block.name_used.message = Der Name ''{0}'' wird bereits verwendet. Bitte ändern Sie den Namen oder löschen Sie zuerst den alten Baustein. - -gui.dialog.new_operator.title = Neuer Operator -#gui.dialog.new_operator.icon = element_new.png -gui.dialog.new_operator.message = Dieses Fenster stellt eine Suche zur Verfügung, die es erlaubt Operatoren aufgrund eingestellter Einschränkungen zu suchen. - -gui.dialog.jdbc_drivers.title = Verfügbare Datenbanktreiber -#gui.dialog.jdbc_drivers.icon = data_network.png -gui.dialog.jdbc_drivers.message = Die derzeitig verfügbaren JDBC Treiber sind unten aufgeführt. Bitte ändern Sie ihre jdbc_properties.xml Konfigurationsdatei entsprechend, um weitere Treiber zu installieren. Beachten Sie das RapidMiner Wiki für weitere Details. - -# Manage DB connections dialog -gui.dialog.manage_db_connections.title = Datenbankverbindung verwalten -#gui.dialog.manage_db_connections.icon = data_network_edit.png -gui.dialog.manage_db_connections.message = Verbindungen zu Datenbanken können in diesem Fenster gebildet, geändert und gelöscht werden. - -gui.dialog.db_connection_advanced.title = Fortgeschrittene Verbindungseigenschaften -#gui.dialog.db_connection_advanced.icon = data_gearwheel.png -gui.dialog.db_connection_advanced.message = Alle verfügbaren Eigenschaften der ausgewählten Verbindung ändern. WARNUNG: Einstellung hier nur ändern, wenn Sie wissen was sie machen! - -gui.dialog.db_connection_advanced.table.key.tooltip = Name der Eigenschaft. -gui.dialog.db_connection_advanced.table.value.tooltip = Wert der Eigenschaft. -gui.dialog.db_connection_advanced.table.override.tooltip = Deaktiviert wird die Grundeinstellung der Eigenschaft verwendet. Aktiviert wird der eingegebene Wert verwendet. - -gui.border.manage_db_connections.connections = Verfügbare Verbindungen -gui.border.manage_db_connections.details = Verbindungsdetails - -gui.label.manage_db_connections.name.label = Name -gui.label.manage_db_connections.system.label = Datenbanksystem -gui.label.manage_db_connections.host.label = Betreiber -gui.label.manage_db_connections.port.label = Anschluss -gui.label.manage_db_connections.database.label = Datenbankstruktur -gui.label.manage_db_connections.user.label = Benutzer -gui.label.manage_db_connections.password.label = Passwort -gui.label.manage_db_connections.url.label = URL - -#gui.dialog.manage_db_connections.connection_entry.icon = data_network.png -#gui.dialog.manage_db_connections.connection_readonly_entry.icon = data_lock.png -gui.dialog.manage_db_connections.status.unknown.label = Verbindungsstatus unbekannt -#gui.dialog.manage_db_connections.status.unknown.icon = question.png -gui.dialog.manage_db_connections.status.ok.label = Verbindung in Ordnung -#gui.dialog.manage_db_connections.status.ok.icon = ok.png -gui.dialog.manage_db_connections.status.error.label = Verbindung fehlgeschlagen -#gui.dialog.manage_db_connections.status.error.icon = error.png - -gui.action.manage_db_connections.new.label = Neu -#gui.action.manage_db_connections.new.icon = data_connection_new.png -gui.action.manage_db_connections.new.tip = Neue Datenbankverbindung erstellen. - -gui.action.manage_db_connections.clone.label = Kopieren -#gui.action.manage_db_connections.clone.icon = data_copy.png -gui.action.manage_db_connections.clone.tip = Ausgewählte Datenbankverbindung kopieren. - -gui.action.manage_db_connections.advanced.label = Fortgeschritten -#gui.action.manage_db_connections.advanced.icon = data_gearwheel.png -gui.action.manage_db_connections.advanced.tip = Fortgeschrittene Verbindungseigenschaften konfigurieren. - -gui.action.manage_db_connections.delete.label = Löschen -#gui.action.manage_db_connections.delete.icon = data_network_delete.png -gui.action.manage_db_connections.delete.tip = Ausgewählte Datenbankverbindung löschen. - -gui.action.manage_db_connections.open.label = Öffnen -#gui.action.manage_db_connections.open.icon = folder_open.png -gui.action.manage_db_connections.open.tip = Ausgewählte Datenbankverbindung öffnen. - -gui.action.manage_db_connections.save.label = Speichern -#gui.action.manage_db_connections.save.icon = floppy_disk.png -gui.action.manage_db_connections.save.tip = Datenbankverbindung speichern. - -gui.action.manage_db_connections.test.label = Test -#gui.action.manage_db_connections.test.icon = data_connection_unknown.png -gui.action.manage_db_connections.test.tip = Datenbankverbindung testen. - -gui.dialog.error.db_driver_not_found.title = {0} Treiber wurde nicht gefunden -gui.dialog.error.db_driver_not_found.message = Der {0} Treiber konnte nicht gefunden werden. Keine weiterführenden Optionen verfügbar. - -gui.dialog.error.manage_db_connections.missing.title = {0} Fehlt -gui.dialog.error.manage_db_connections.missing.message = {0} fehlt. Bitte geben Sie den Eintrag genau an. - -gui.dialog.confirm.manage_db_connections.overwrite.title = Verbindung überschreiben -#gui.dialog.confirm.manage_db_connections.overwrite.icon = data_connection_warning.png -gui.dialog.confirm.manage_db_connections.overwrite.message = Es exisitiert bereits eine Verbindung namens {0}. Soll diese Verbindung überschrieben werden? - -gui.dialog.confirm.manage_db_connections.delete.title = Verbindung löschen -#gui.dialog.confirm.manage_db_connections.delete.icon = data_connection_warning.png -gui.dialog.confirm.manage_db_connections.delete.message = Verbindung {0} wirklich von der Liste löschen? - -gui.dialog.error.db_connection_failed.title = Verbindung fehlgeschlagen -gui.dialog.error.db_connection_failed.message = Verbindung zu Datenbank ''{0}'' des Betreibers ''{1}'' (Port: {2}) ist fehlgeschlagen. Bitte überprüfen Sie ihre Einstellungen und bestätigen Sie erneut die Verbindungs URL ''{3}''. - -gui.dialog.error.db_connection_failed_url.title = Verbindung fehlgeschlagen -gui.dialog.error.db_connection_failed_url.message = Verbindung zu Datenbank bei ''{0}'' ist fehlgeschlagen. Bitte überprüfen Sie die Einstellungen ihrer Datenbankverbindung und die Erreichbarkeit der Datenbank. - -gui.dialog.error.db_connection_failed_simple.title = Verbindung fehlgeschlagen -gui.dialog.error.db_connection_failed_simple.message = Verbindung zur Datenbank ist fehlgeschlagen: {0} - -gui.dialog.error.importwizard.unknown_error.title = Fehler während des Imports -gui.dialog.error.importwizard.unknown_error.message = Import ist fehlgeschlagen. Grund: {0} - -gui.dialog.import_database_table.title = Datenbanktabelle importieren -#gui.dialog.import_database_table.icon = inbox_into.png -gui.dialog.import_database_table.message = Dieser Assistent ermöglicht es eine Datenbanktabelle in ein existierendes Repository zu importieren. - -gui.dialog.import_excel_sheet.title = Exceldatei importieren -#gui.dialog.import_excel_sheet.icon = inbox_into.png -gui.dialog.import_excel_sheet.message = Dieser Assistent ermöglicht es ein Tabelle aus einer Excel Arbeitsmappe in ein existierendes Repository zu importieren. - -gui.dialog.import_csv_file.title = CSV Datei importieren -#gui.dialog.import_csv_file.icon = inbox_into.png -gui.dialog.import_csv_file.message = Dieser Assistent ermöglicht es eine CSV Datei in ein existierendes Repository zu importieren. - -gui.dialog.import_access_table.title = Access Tabelle importieren -#gui.dialog.import_access_table.icon = inbox_into.png -gui.dialog.import_access_table.message = Dieser Assistent ermöglicht es ein Tabelle aus einer Access Datenbank in ein existierendes Repository zu importieren. - -gui.dialog.import_blob.title = Datei importieren -#gui.dialog.import_blob.icon = inbox_into.png -gui.dialog.import_blob.message = Dieser Assistent ermöglicht es eine Datei in ein existierendes Repository zu importieren. Der Inhalt der Datei wird in keiner Weise interpretiert. - -gui.dialog.error.import_blob_failed.title = Import fehlgeschlagen -gui.dialog.error.import_blob_failed.message = Import einer binären Datei ist fehlgeschlagen: {0}. - -################################## -# DATA IMPORT WIZARDS -################################## - - -########################### -# BEGIN xml import wizard -# - - -# Namespace Mapping Step -gui.dialog.step.importwizard.xml.namespace_mapping.title = Namensraum zuordnen -gui.dialog.step.importwizard.xml.namespace_mapping.message = Definieren Sie eine eigene id für jeden im xml-Dokument vorkommenden Namensraum, welche im Weiteren als Abkürzung verwendet wird. - -gui.label.importwizard.xml.namespace_mapping.default_namespace = Standard Namensraum -gui.label.importwizard.xml.namespace_mapping.namespace_table.id_column = id -gui.label.importwizard.xml.namespace_mapping.namespace_table.namespace_column = Namensraum - - - -# Example Expression Step -gui.dialog.step.importwizard.xml.example_expression.title = Beispiele auswählen -gui.dialog.step.importwizard.xml.example_expression.message = Dieser Schritt ermöglicht es einen XPath für alle Elemente, deren Attribute und Textknoten als Eigenschaft der endgültigen Beispielgruppe genutzt werden, zu definieren. Wählen Sie eine Gruppe von Elementen in der XML-Struktur auf der linken Seite (halten Sie Strg gedrückt, um mehrere Knoten zu wählen). Alle Attribute mit gleichem Wert in allen ausgewählten Elementen werden in der Tabelle ganz unten angezeigt. Wählen Sie keines oder mehr von ihnen und klicken Sie 'Auswahl anwenden', um den einfachsten XPath zu generieren bei dem alle Elemente mit den selben Eigenschaften, wie zuvor ausgewählt, übereinstimmen. - -gui.action.importwizard.xml.example_expression.apply_selection.label = Auswahl anwenden -#gui.action.importwizard.xml.example_expression.apply_selection.icon = -#gui.action.importwizard.xml.example_expression.apply_selection.acc = -gui.action.importwizard.xml.example_expression.apply_selection.tip = Xpath erstellen, der mit allen ausgewählten Elementen übereinstimmt deren Attribute und Attributwerte mit den ausgewählten Attributen übereinstimmen. -gui.action.importwizard.xml.example_expression.apply_selection.mne = a - -gui.label.importwizard.xml.example_expression.attribute_table.element_column_header = Element -gui.label.importwizard.xml.example_expression.attribute_table.attribute_column_header = Attribut -gui.label.importwizard.xml.example_expression.attribute_table.value_column_header = Wert - -gui.label.xml_reader.wizard.xpath_non_element_nodes = Der XPath-Ausdruck wählt einen Knoten, der kein Element ist: {0} -gui.label.xml_reader.wizard.xpath_result = XPath stimmt mit {0} Elementen überein. -gui.label.xml_reader.wizard.illegal_xpath = Illegaler XPath: {0}. -gui.label.xml_reader.wizard.evaluating = Berechnet... -gui.label.xml_reader.wizard.cannot_load_dom = Dokument kann nicht gelesen werden: Datei kann nicht gefunden werden oder ist ein ungültiges XML. -gui.label.xml_reader.wizard.undefined_default_namespace = Es wurde kein standard Namensraum definiert. -gui.label.xml_reader.wizard.undefined_or_duplicate_namespace_prefix = Doppeltes oder nicht definiertes Namensraum Prefix. -gui.label.xml_reader.wizard.status_ok = Bereit zum Fortsetzen. - -gui.label.importwizard.xml.example_expression.matches_label = Übereinstimmende Elemente (top {0}): - -# Attribute Expression Step -gui.dialog.step.importwizard.xml.attribute_expression.title = Ausgewählte Attribute -gui.dialog.step.importwizard.xml.attribute_expression.message = In diesem Schritt können Sie die Attribute wählen, die als Eigenschaft der endgültigen Beispielgruppe verwendet werden. Um durch die Elemente, die mit dem XPath des vorherigen Schritts übereinstimmen, zu navigieren, benutzen Sie die oberen Schaltflächen. - -gui.action.importwizard.xml.attribute_expression.add_xpath.label = -#gui.action.importwizard.xml.attribute_expression.add_xpath.icon = nav_right.png -#gui.action.importwizard.xml.attribute_expression.add_xpath.acc = -gui.action.importwizard.xml.attribute_expression.add_xpath.tip = Ausgewählte Attribute hinzufügen. -gui.action.importwizard.xml.attribute_expression.add_xpath.mne = - -gui.action.importwizard.xml.attribute_expression.remove_xpath.label = -#gui.action.importwizard.xml.attribute_expression.remove_xpath.icon = nav_left.png -#gui.action.importwizard.xml.attribute_expression.remove_xpath.acc = -gui.action.importwizard.xml.attribute_expression.remove_xpath.tip = Ausgewählte XPaths entfernen. -gui.action.importwizard.xml.attribute_expression.remove_xpath.mne = - -gui.action.importwizard.xml.attribute_expression.next_match.label = Nächste Üœbereinstimmung -#gui.action.importwizard.xml.attribute_expression.next_match.icon = arrow_right.png -#gui.action.importwizard.xml.attribute_expression.next_match.acc = -gui.action.importwizard.xml.attribute_expression.next_match.tip = Zeigt das nächste XML element an, das mit dem XPath aus dem vorherigen Schritt übereinstimmt. -gui.action.importwizard.xml.attribute_expression.next_match.mne = e - -gui.action.importwizard.xml.attribute_expression.previous_match.label = Vorherige Übereinstimmung -#gui.action.importwizard.xml.attribute_expression.previous_match.icon = arrow_left.png -#gui.action.importwizard.xml.attribute_expression.previous_match.acc = -gui.action.importwizard.xml.attribute_expression.previous_match.tip = Zeigt das vorherige XML element an, das mit dem XPath aus dem vorherigen Schritt übereinstimmt. -gui.action.importwizard.xml.attribute_expression.previous_match.mne = r - -gui.label.importwizard.xml.attribute_expression.xml_tree_label = Derzeitige Elementstruktur: -gui.label.importwizard.xml.attribute_expression.xpath_table_label XPaths für Attribute: -gui.label.importwizard.xml.attribute_expression.attribute_table_label Neue Attribute in aktuell gewähltem Knoten: - -gui.label.importwizard.xml.attribute_expression.attribute_table.attribute_column_header = Attribute -gui.label.importwizard.xml.attribute_expression.attribute_table.value_column_header = Wert - -gui.label.importwizard.xml.attribute_expression.xpath_table.xpath_column_header = XPath -gui.label.importwizard.xml.attribute_expression.xpath_table.value_column_header = Aktueller Wert - -# -# END xml import wizard -########################### - -gui.progress.guessing_value_types.label = Wertetyp raten -gui.progress.importing_data.label = Daten importieren -gui.progress.loading_data.label = Daten laden -gui.progress.generate_preview.label = Erzeuge Vorschau -gui.action.importwizard.limited_preview.label = Vorschau benutzt nur die ersten {0} Zeilen. - -gui.dialog.step.select_file.title = Datei auswählen -gui.dialog.step.select_file.message = Bitte die Datei auswählen, die importiert werden soll. - -gui.dialog.step.specify_csv_parsing_options.title = Parsen -gui.dialog.step.specify_csv_parsing_options.message = Bitte angeben wie die Datei geparst und wie die Spalten getrennt werden sollen. - -gui.dialog.step.value_type_selection.title = Wertetypen -gui.dialog.step.value_type_selection.message = Bitte definieren wie Zahlen geparst werden sollen. - -#bis hier - -gui.dialog.step.select_attributes.title = Rollen, Wertetypen und Namen von Attributen auswählen -gui.dialog.step.select_attributes.message = Bitte Rollen, Wertetypen und Namen der Attribute angeben. Entwählen Sie eine Spalte, wenn sie ignoriert werden soll. Spezielle Attribute wie Label, ID oder Gewichtung können makiert werden. - -gui.dialog.step.select_repository_location.title = Repository Platz auswählen -gui.dialog.step.select_repository_location.message = Bitte einen Platz für das Repository auswählen. - -gui.dialog.step.importwizard.excel_data_selection.title = Daten Auswahl -gui.dialog.step.importwizard.excel_data_selection.message = Eine Excel Datei kann mehrere Dokumente enthalten. Bitte w\u00E4hlen Sie jenes, das in RapidMiner eingef\u00FCgt werden soll. Au\u00DFerdem k\u00F6nnen Sie einen Zellenbereich markieren, der geladen werden soll. - - -gui.dialog.step.importwizard.annotations.title = Anmerkungs Definition -gui.dialog.step.importwizard.annotations.message = In RapidMiner kann jedes Attribut eine Anmerkung erhalten. Die wichtigste ist der Name des Attributes - eine Zeile mit dieser Anmerkung definiert die Namen der Attribute. Sollten Ihre Daten keine Namen für die Attribute haben, aktivieren Sie diese Eigenschaft nicht. Sind in den Reihen Ihres Datendokuments weitere Anmerkungen enthalten können Sie diese hier zuordnen. - -gui.dialog.step.importwizard.metadata.title = Metadaten Definition -gui.dialog.step.importwizard.metadata.message = RapidMiner verwendet stark typisierte Attribute. In diesem Schritt können Sie den Datentyp Ihrer Attribute festlegen. Auߟerdem ordnet RapidMiner den Attributen Rollen zu, die definieren wofür die Attribute von den verschiedenen Operatoren verwendet werden können. Zudem können ihre Rollen hier definiert werden. Desweiteren können die Attribute hier umbenannt werden oder komplett entwählt werden. - -gui.dialog.step.database_connection.title = Datenbankverbindung -gui.dialog.step.database_connection.message = Bitte wählen Sie Ihre Datenbankverbindung aus. - -gui.dialog.step.database_query.title = Abfrage -gui.dialog.step.database_query.message = Bitte erstellen Sie eine Abfrage, die die Datentabelle erstellt. - -gui.label.loading_excel_sheets.label = Lädt Excel Arbeitsmappe... -#gui.label.loading_excel_sheets.icon = 48/hourglass.png - -gui.label.loading_data.label = Lädt Daten... - -gui.dialog.build_sql_query.title = SQL Abfragen Ersteller -gui.dialog.build_sql_query.message = Erstellen Sie eine SQL Abfrage durch die Auswahl von Tabellen und Attributen. - -gui.dialog.error.importwizard.io_error.title = Fehler beim Einfügen von Daten -gui.dialog.error.importwizard.io_error.message = Fehler trat beim Einfügen von {0} auf: {1} - -gui.dialog.error.importwizard.error_creating_wizard.title = Fehler beim Einfügen von Daten -gui.dialog.error.importwizard.error_creating_wizard.message = Fehler trat beim Starten des Assistenten auf. - -gui.dialog.filter_table_model.column_name_attribute.title = Attribut -gui.dialog.filter_table_model.column_name_attribute.tip = Attribut für den Filter auswählen. -gui.dialog.filter_table_model.column_name_compare.title = Vergleich -gui.dialog.filter_table_model.column_name_field.title = Wert -gui.dialog.filter_table_model.column_name_field.tip = Wert für den gewählten Filter eingeben. -gui.dialog.filter_table_model.upper_bound.title = (Max) -gui.dialog.filter_table_model.lower_bound.title = (Min) - - -#FilterPropertyDialog -gui.dialog.filter_property_dialog.logic.title = - -gui.action.filter_property_dialog.radio_and.label = Alle Filter -gui.action.filter_property_dialog.radio_and.tip = Auswählen wie mehrere Filter logisch verbunden werden sollen. -gui.action.filter_property_dialog.radio_and.mne = A -gui.action.filter_property_dialog.radio_or.label = Beliebiger Filter -gui.action.filter_property_dialog.radio_or.tip = Auswählen wie mehrere Filter logisch verbunden werden sollen. -gui.action.filter_property_dialog.radio_or.mne = B -gui.action.filter_property_dialog.check_metadata.label = Komparator-Vorauswahl -gui.action.filter_property_dialog.check_metadata.tip = Komparator-Vorauswahl anhand der Metadaten. -gui.action.filter_property_dialog.check_metadata.mne = V - -gui.dialog.tutorial.title = RapidMiner Tutorium -#gui.dialog.tutorial.icon = book.png -gui.dialog.tutorial.message = Das RapidMiner Tutorium zeigt Ihnen anhand von Beispielen wie RapidMiner bedient wird. Mit den Feldern unten können Sie durch das Tutorium navigieren. - -gui.dialog.check_for_updates.title = Nach Aktualisierungen suchen -gui.dialog.check_for_updates.message = - -gui.dialog.message.no_updates_available.title = Keine Aktualisierungen verfügbar -#gui.dialog.message.no_updates_available.icon = download.png -gui.dialog.message.no_updates_available.message = Es sind keine aktuelleren Versionen der RapidMiner Community Edition verfügbar. - -gui.dialog.message.update_available.title = Neue Version verfügbar -#gui.dialog.message.update_available.icon = download.png -gui.dialog.message.update_available.message = RapidMiner Community Edition {0} ist verfügbar. Bitte laden Sie sie von http://www.rapidminer.com runter. - -gui.dialog.attribute_editor.title = Attributeditor -#gui.dialog.attribute_editor.icon = table_new.png -gui.action.menu.attribute_editor_file.label = Datei -gui.action.menu.attribute_editor_file.mne = D -gui.action.menu.attribute_editor_file.tip = Dateien öffnen und speichern -gui.action.menu.attribute_editor_table.label = Tabelle -gui.action.menu.attribute_editor_table.mne = T -gui.action.menu.attribute_editor_table.tip = Tabellengröߟe ändern und Format raten - -gui.action.attribute_editor.remove_column.label = Spalte entfernen -gui.action.attribute_editor.remove_column.mne = S -gui.action.attribute_editor.remove_column.tip = Aktuelle Spalte entfernen. -#gui.action.attribute_editor.remove_column.icon = table_selection_column_delete.png - -gui.action.attribute_editor.remove_row.label = Zeile entfernen -gui.action.attribute_editor.remove_row.mne = Z -gui.action.attribute_editor.remove_row.tip = Aktuelle Zeile entfernen. -#gui.action.attribute_editor.remove_row.icon = table_selection_row_delete.png - -gui.action.attribute_editor.use_row_as_names.label = Zeile als Namen der Attribute verwenden -gui.action.attribute_editor.use_row_as_names.mne = N -gui.action.attribute_editor.use_row_as_names.tip = Aktuelle Zeile als Namen der Attribute verwenden, z.B. für CSV Dateien. -#gui.action.attribute_editor.use_row_as_names.icon = table_selection_row_add.png - -gui.action.attribute_editor.guess_value_type.label = Wertformat erraten -gui.action.attribute_editor.guess_value_type.mne = W -gui.action.attribute_editor.guess_value_type.tip = Das Format der Werte der aktuellen Spalte aufgrund der Daten erraten. -#gui.action.attribute_editor.guess_value_type.icon = question.png - -gui.action.attribute_editor.guess_all_value_types.label = Alle Wertformate erraten -gui.action.attribute_editor.guess_all_value_types.mne = A -gui.action.attribute_editor.guess_all_value_types.tip = Das Format der Werte aller Spalten aufgrund der aktuellen Daten (erneut) raten. -#gui.action.attribute_editor.guess_all_value_types.icon = question.png - -gui.action.attribute_editor.open_aml_file.label = Datei zur Attributbeschreibung öffnen... -gui.action.attribute_editor.open_aml_file.mne = f -gui.action.attribute_editor.open_aml_file.tip = Eine existierende XML Attributbeschreibungsdatei (.aml) öffnen. -#gui.action.attribute_editor.open_aml_file.icon = code_add.png - -gui.action.attribute_editor.save_aml_file.label = Datei zur Attributbeschreibung speichern... -gui.action.attribute_editor.save_aml_file.mne = p -gui.action.attribute_editor.save_aml_file.tip = Aktuelle Beschreibung der Metadaten der Attribute als XML Datei (.aml) speichern. -#gui.action.attribute_editor.save_aml_file.icon = floppy_disk.png - -gui.action.attribute_editor.load_data.label = Daten laden... -gui.action.attribute_editor.load_data.mne = D -gui.action.attribute_editor.load_data.tip = Datendatei öffnen und der Tabelle weitere Spalten hinzufügen. -#gui.action.attribute_editor.load_data.icon = data_add.png - -gui.action.attribute_editor.load_series_data.label = Zeitreihendaten laden... -gui.action.attribute_editor.load_series_data.mne = l -gui.action.attribute_editor.load_series_data.tip = Zeitreihendatei öffnen und der Tabelle weitere Spalten mit Zeitreihenwerten hinzufügen. -#gui.action.attribute_editor.load_series_data.icon = window_oscillograph.png - -gui.action.attribute_editor.save_data_as.label = Daten speichern unter... -gui.action.attribute_editor.save_data_as.mne = s -gui.action.attribute_editor.save_data_as.tip = Inhalt der Tabelle in einer Datendatei speichern. -#gui.action.attribute_editor.save_data_as.icon = data_floppy_disk.png - -gui.action.attribute_editor.clear.label = Löschen -gui.action.attribute_editor.clear.mne = L -gui.action.attribute_editor.clear.tip = Inhalt der Tabelle löschen. -#gui.action.attribute_editor.clear.icon = table_new.png - -gui.action.attribute_editor.close.label = Beenden -gui.action.attribute_editor.close.mne = B -gui.action.attribute_editor.close.tip = Schlieߟt das Fenster des Attributeditors. -#gui.action.attribute_editor.close.icon = door_exit.png - -gui.dialog.file_chooser.import_process.title = Prozess einfügen -#gui.dialog.file_chooser.import_process.icon = inbox_into.png -gui.dialog.file_chooser.import_process.message = Prozess wählen, der eingefügt werden soll. - -gui.dialog.file_chooser.export_process.title = Prozess exportieren -#gui.dialog.file_chooser.export_process.icon = inbox_out.png -gui.dialog.file_chooser.export_process.message = Ort auswählen zu dem der Prozess exportiert werden soll. - -# DateFormatValueCellEditor -gui.action.dateformat.select_sample.label = Beispiele zeigen -#gui.action.dateformat.select_sample.icon = calendar.png -gui.action.dateformat.select_sample.tip = Beispielwert auswählen, der als Hilfe zum Editieren in das Textfeld kopiert wird. - -# AttributesPropertyDialog -gui.dialog.parameter.attributes.title = Attribute auswählen -#gui.dialog.parameter.attributes.icon = document_text_view.png -gui.dialog.parameter.attributes.attributes.border = Attribute -gui.dialog.parameter.attributes.selected_attributes.border = Ausgewählte Attribute - -# RegExpPropertyDialog -gui.dialog.parameter.regexp.title = Reguläre Ausdrücke editieren -#gui.dialog.parameter.regexp.icon = document_text_view.png -gui.dialog.parameter.regexp.constructs.any_character = jedes Zeichen -gui.dialog.parameter.regexp.constructs.bracket_expression = jedes Zeichen in Klammern -gui.dialog.parameter.regexp.constructs.not_bracket_expression = jedes Zeichen ohne Klammern -gui.dialog.parameter.regexp.constructs.capturing_group = Erfassungsgruppe -gui.dialog.parameter.regexp.constructs.zero_one_quantifier = Gewichtung: null oder eins des folgenden Elements -gui.dialog.parameter.regexp.constructs.zero_more_quantifier = Gewichtung: null oder mehrere des folgenden Elements -gui.dialog.parameter.regexp.constructs.one_more_quantifier = Gewichtung: eins oder mehrere des folgenden Elements -gui.dialog.parameter.regexp.constructs.exact_quantifier = Gewichtung: folgendes Element kommt genau n mal vor -gui.dialog.parameter.regexp.constructs.min_quantifier = Gewichtung: folgendes Element kommt mindestens min mal vor -gui.dialog.parameter.regexp.constructs.min_max_quantifier = Gewichtung: folgendes Element kommt zwischen min und max mal vor -gui.dialog.parameter.regexp.constructs.disjunction = Trennung von Elementen -gui.dialog.parameter.regexp.shortcuts.arbitrary = mehrere beliebige Zeichen -gui.dialog.parameter.regexp.shortcuts.letter = jeder Buchstabe -gui.dialog.parameter.regexp.shortcuts.lowercase_letter = jeder klein geschriebene Buchstabe -gui.dialog.parameter.regexp.shortcuts.uppercase_letter = jeder groߟ geschriebene Buchstabe -gui.dialog.parameter.regexp.shortcuts.digit = jede Ziffer -gui.dialog.parameter.regexp.shortcuts.word = ein Wort, wie [a-zA-Z0-9_] -gui.dialog.parameter.regexp.shortcuts.non_word = nicht ein Wort, wie [^\\w] -gui.dialog.parameter.regexp.shortcuts.whitespace = ein Leerzeichen, wie [ \\t\\r\\n\\v\\f] -gui.dialog.parameter.regexp.shortcuts.non_whitespace = nicht ein Leerzeichen, wie [^\\s] -gui.dialog.parameter.regexp.shortcuts.punctuation = Interpunktions Zeichen -gui.dialog.parameter.regexp.regular_expression.border = Regulärer Ausdruck -gui.dialog.parameter.regexp.regular_expression.tip = Der reguläre Ausdruck. -gui.dialog.parameter.regexp.regular_expression.constructs_table.title = Konstruktionen -gui.dialog.parameter.regexp.regular_expression.constructs_table.tip = Konstruktionen für reguläre Ausdrücke. Konstruktion durch Doppelklick zu dem regulären Ausdruck hinzufügen. -gui.dialog.parameter.regexp.regular_expression.constructs_table.construct_header = Konstruktion -gui.dialog.parameter.regexp.regular_expression.constructs_table.description_header = Beschreibung -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.title = Abkürzungen -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.tip = Abkürzungen für reguläre Ausdrücke. Abkürzung durch Doppelklick zu dem regulären Ausdruck hinzufügen. -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.shortcuts_header = Abkürzung -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.description_header = Beschreibung -gui.dialog.parameter.regexp.regular_expression.inline_search.title = Textsuche -gui.dialog.parameter.regexp.regular_expression.inline_search.search = Suche in Text: -gui.dialog.parameter.regexp.regular_expression.inline_search.replaced = Ersetzter Text: -gui.dialog.parameter.regexp.regular_expression.result_list.title = Trefferliste -gui.dialog.parameter.regexp.regular_expression.result_list.match = Treffer {0}: {1} -gui.dialog.parameter.regexp.regular_expression.result_list.group_match = Gruppe entspricht: {0} -gui.dialog.parameter.regexp.regular_expression.result_list.empty = Keine Treffer. -gui.dialog.parameter.regexp.regular_expression.regexp_options.title = Regexp Optionen -gui.dialog.parameter.regexp.regular_expression.regexp_options.case_insensitive = Groß-/Kleinschreibung ignorieren -gui.dialog.parameter.regexp.regular_expression.regexp_options.multiline_mode = Mehrzeilen-Modus -gui.dialog.parameter.regexp.regular_expression.regexp_options.dotall_mode = Dotall-Modus -gui.dialog.parameter.regexp.regular_expression.regexp_options.unicode_case = Unicode Groß-/Kleinschreibung beachten -gui.dialog.parameter.regexp.regular_expression.regexp_options.case_insensitive.tip = Bei der Suche wird die Groß-/Kleinschreibung ignoriert. Der Vergleich geschiet auf Basis des US-ASCII Zeichensatzes. -gui.dialog.parameter.regexp.regular_expression.regexp_options.multiline_mode.tip = Im Mehrzeilen-Modus entsprechen die Ausdrücke ^ und $ dem Anfang bzw. dem Ende einer neuen Zeile. -gui.dialog.parameter.regexp.regular_expression.regexp_options.dotall_mode.tip = Im Dotall-Modus trifft der Ausdruck . auf alle Zeichen zu, inklusive Zeilenumbrüchen. Standardmäßig ignoriert der Ausdruck Zeilenumbrüche. -gui.dialog.parameter.regexp.regular_expression.regexp_options.unicode_case.tip = Wenn die Groß-/Kleinschreibung ignoriert wird, geschiet der Vergleich nun auf Basis des Unicode Zeichensatzes. -gui.dialog.parameter.regexp.replacement.border = Ersetzung (nur zur Vorschau) -gui.dialog.parameter.regexp.replacement.tip = Der Text, welcher alle Treffer in der Vorschau ersetzt. - -gui.dialog.parameter = Element Abkürzungen -gui.dialog.parameter.regexp.item_shortcuts.tip = Elemente, die durch den regulären Ausdruck beschrieben werden sollen. Element durch Doppelklick zu dem regulären Ausdruck hinzufügen. -gui.dialog.parameter.regexp.matched_items.border = Angepasste Elemente -gui.dialog.parameter.regexp.matched_items.tip = Durch regulären Ausdruck angepasste Elemente. -gui.dialog.parameter.regexp.error.label = Regulärer Ausdruck ist ungültig. Bitte gültigen Ausdruck eingeben! -#gui.dialog.parameter.regexp.error.icon = error.png -gui.dialog.parameter.regexp.no_error.label = Regulärer Ausdruck gültig. -#gui.dialog.parameter.regexp.no_error.icon = ok.png - -# OperatorInfoScreen & OperatorInfoPanel panel -gui.label.input_ports.label = Quelle -#gui.label.input_ports.icon = 16/arrow_right.png -#gui.label.input_ports.icon = 16/plug_next.png -gui.label.output_ports.label = Senke -#gui.label.output_ports.icon = 16/arrow_left.png -#gui.label.output_ports.icon = 16/plug_previous.png -gui.label.inner_sources.label = Innere Quelle -#gui.label.inner_sources.icon = 16/arrow_left_green.png -#gui.label.inner_sources.icon = 16/plug_previous.png -gui.label.inner_sinks.label = Innere Senke -#gui.label.inner_sinks.icon = 16/arrow_right_green.png -#gui.label.inner_sinks.icon = 16/plug_next.png - -gui.label.subprocesses.label = Teilprozess -#gui.label.subprocesses.icon = groups/16/meta.png - -#NewOperatorDialog -gui.label.new_op_dialog.search_text.label = Suche Text: -gui.label.new_op_dialog.search_text.mne = S -gui.label.new_op_dialog.operator_group.label = Operatorgruppe: -gui.label.new_op_dialog.operator_group.mne = g -gui.label.new_op_dialog.required_input.label = Benötigte Eingabe: -gui.label.new_op_dialog.required_input.mne = E -gui.label.new_op_dialog.delivered_output.label = Ausgabe: -gui.label.new_op_dialog.delivered_output.mne = A -gui.label.new_op_dialog.first_capability.label = Erste Fähigkeit: -gui.label.new_op_dialog.first_capability.mne = F -gui.label.new_op_dialog.second_capability.label = Zweite Fähigkeit: -gui.label.new_op_dialog.second_capability.mne = h -gui.action.new_op_dialog.clear_search_field.label = -#gui.action.new_op_dialog.clear_search_field.icon = delete.png -gui.action.new_op_dialog.clear_search_field.tip = Sucheingabe löschen. -gui.dialog.new_op_dialog.matching_operators = Passende Operatoren -gui.dialog.new_op_dialog.operator_info = Operatorbeschreibung: -gui.dialog.new_op_dialog.search_constraints = Bedingung suchen: - -gui.action.new_op_dialog.full_text_search.label = Volltextsuche -gui.action.new_op_dialog.full_text_search.mne = V - -gui.tabs.operator_info_panel.description.label = Beschreibung -#gui.tabs.operator_info_panel.description.icon = information.png -gui.tabs.operator_info_panel.description.mne = B -gui.tabs.operator_info_panel.description.tip = Detaillierte Beschreibung des Operators. - -gui.tabs.operator_info_panel.capabilities.label = Fähigkeiten -#gui.tabs.operator_info_panel.capabilities.icon = briefcase2.png -gui.tabs.operator_info_panel.capabilities.mne = F -gui.tabs.operator_info_panel.capabilities.tip = Fähigkeiten des Operators. - -gui.tabs.operator_info_panel.deprecation.label = Veraltet -#gui.tabs.operator_info_panel.deprecation.icon = sign_warning.png -gui.tabs.operator_info_panel.deprecation.mne = a -gui.tabs.operator_info_panel.deprecation.tip = Information zur veralteten Gebräuchlichkeit. - -gui.tabs.operator_info_panel.ports.label = Anschlüsse -#gui.tabs.operator_info_panel.ports.icon = plug.png -gui.tabs.operator_info_panel.ports.mne = A -gui.tabs.operator_info_panel.ports.tip = Die Ein- und Ausgangsanschlüsse des Operators. - -gui.tabs.operator_info_panel.subprocess.label = Teilprozess ''{0}'' -#gui.tabs.operator_info_panel.subprocess.icon = element_selection.png -gui.tabs.operator_info_panel.subprocess.tip = Der Teilprozess ''{0}'' des Operators. - -#PropertyValueCellEditors -gui.action.edit_text.label = Text editieren... -gui.action.edit_text.tip = Text in separatem Editor bearbeiten. -#gui.action.edit_text.icon = edit.png - -gui.action.build_sql.label = Abfrage erstellen... -gui.action.build_sql.tip = SQL Abfrage erstellen oder editieren. -#gui.action.build_sql.icon = code_edit.png - -gui.action.choose_file.label = -gui.action.choose_file.tip = Datei auswählen. -#gui.action.choose_file.icon = folder_open.png - -gui.action.edit_attributefile.label = -gui.action.edit_attributefile.tip = Text in separatem Editor bearbeiten. -#gui.action.edit_attributefile.icon = table_edit.png - -gui.action.wizard.dataloading.label = Assistent zum Laden der Daten starten... -gui.action.wizard.dataloading.tip = Assistent starten, der beim laden der Daten hilft. -#gui.action.wizard.dataloading.icon = magic_wand.png - -gui.action.wizard.datawriting.label = Assistent zum Speichern der Daten starten... -gui.action.wizard.datawriting.tip = Assistent starten, der beim speichern der Daten hilft. -#gui.action.wizard.datawriting.icon = magic_wand.png - -gui.action.wizard.configure.label = Parametereinstellungen editieren... -gui.action.wizard.configure.tip = Parameter dieses Fensters in einem neu geöffneten editieren. -#gui.action.wizard.configure.icon = form_edit.png - -gui.action.attributes.label = Attribute wählen... -gui.action.attributes.tip = Öffnet ein Fenster zum Auswählen der Attribute. -#gui.action.attributes.icon = document_text_view.png -gui.action.attributes.clear.label = -#gui.action.attributes.clear.icon = delete.png -gui.action.attributes.clear.tip = Eingabefeld löschen. -gui.action.attributes.add.label = -#gui.action.attributes.add.icon = add.png -gui.action.attributes.add.tip = Weiteres wählbares Attribut hinzufügen. -gui.action.attributes_select.label = -gui.action.attributes_select.tip = Attribute auswählen. -#gui.action.attributes_select.icon = nav_right.png -gui.action.attributes_deselect.label = -gui.action.attributes_deselect.tip = Attribute entwählen. -#gui.action.attributes_deselect.icon = nav_left.png - -gui.action.regexp.label = -gui.action.regexp.tip = Reguläre Ausdrücke editieren und vorher betrachten. -#gui.action.regexp.icon = document_text_view.png - -gui.action.list.label = Liste {0} editieren... -#gui.action.list.icon = notebook_edit.png - -gui.action.enumeration.label = Aufzählung {0} editieren... -#gui.action.enumeration.icon = notebook_edit.png - -#ListPropertyDialog -gui.action.list.add_row.label = Eintrag hinzufügen -gui.action.list.add_row.mne = h -gui.action.list.add_row.tip = Fügt der Liste einen Eintrag hinzu. -#gui.action.list.add_row.icon = notebook_add.png - -gui.action.list.remove_row.label = Eintrag entfernen -gui.action.list.remove_row.mne = e -gui.action.list.remove_row.tip = Entfernt den gewählten Eintrag von der Liste. -#gui.action.list.remove_row.icon = notebook_delete.png - -gui.action.list.remove_entry.title = -gui.action.list.remove_entry.tip = Entfernt den Eintrag. -#gui.action.list.remove_entry.icon = delete.png - -#ExpressionPropertyDialog -gui.dialog.parameter.expression.title = Ausdruck -#gui.dialog.parameter.expression.icon = calculator.png - -#bis hier - -#MatrixPropertyDialog -gui.dialog.parameter.matrix.title = Parametermatrix editieren -#gui.dialog.parameter.matrix.icon = table_edit.png - -gui.action.matrix.add_row.label = Zeile hinzufügen -gui.action.matrix.add_row.mne = z -gui.action.matrix.add_row.tip = Eine Zeile zur Matrix hinzufügen. -#gui.action.matrix.add_row.icon = table_selection_row_add.png - -gui.action.matrix.remove_row.label = Zeile entfernen -gui.action.matrix.remove_row.mne = e -gui.action.matrix.remove_row.tip = Eine Zeile aus der Matrix entfernen. -#gui.action.matrix.remove_row.icon = table_selection_row_delete.png - -gui.action.matrix.add_column.label = Spalte hinzufügen -gui.action.matrix.add_column.mne = S -gui.action.matrix.add_column.tip = Eine Spalte zur Matrix hinzufügen. -#gui.action.matrix.add_column.icon = table_selection_column_add.png - -gui.action.matrix.remove_column.label = Spalte entfernen -gui.action.matrix.remove_column.mne = n -gui.action.matrix.remove_column.tip = Eine Spalte aus der Matrix entfernen. -#gui.action.matrix.remove_column.icon = table_selection_column_delete.png - -gui.action.matrix.increase_size.label = Vergröߟern -gui.action.matrix.increase_size.mne = V -gui.action.matrix.increase_size.tip = Eine Spalte und eine Zeile zur Matrix hinzufügen. -#gui.action.matrix.increase_size.icon = table_selection_row_add.png - -gui.action.matrix.decrease_size.label = Verkleinern -gui.action.matrix.decrease_size.mne = k -gui.action.matrix.decrease_size.tip = Eine Spalte und eine Zeile aus der Matrix entfernen. -#gui.action.matrix.decrease_size.icon = table_selection_row_delete.png - -gui.action.matrix.edit.label = Matrix bearbeiten... -gui.action.matrix.edit.tip = Matrix in einem neuen Fenster bearbeiten. -#gui.action.matrix.edit.icon = table_edit.png - -#ResultObjects -gui.action.save_result.label = Speichern... -gui.action.save_result.mne = S -#gui.action.save_result.icon = floppy_disk.png -gui.action.save_result.tip = Dieses Ergebnis speichern. -#gui.action.save_result.acc = ctrl S - -gui.action.save_image.label = Bild exportieren... -gui.action.save_image.tip = Angezeigtes Bild als Datei speichern. -gui.action.save_image.mne = e -#gui.action.save_image.icon = inbox_out.png - -gui.dialog.save_image.title = Bild exportieren -gui.dialog.save_image.message = Ort und Format der Datei des exportierten Bildes bestimmen. -#gui.dialog.save_image.icon = inbox_out.png - -gui.action.image_options.label = Bild Einstellungen... -gui.action.image_options.tip = Formateinstellungen festlegen. -#gui.action.image_options.icon = form_edit.png - -gui.dialog.image_options.title = Bild Einstellungen -gui.dialog.image_options.message = {0} konfigurieren. -#gui.dialog.image_options.icon = form_edit.png - -gui.action.import_regex_refresh.label = -gui.action.import_regex_refresh.tip = Den Regulären Ausdruck anwenden. -#gui.action.import_regex_refresh.icon = document_text_refresh.png - - -#SettingsDialog -gui.dialog.settings.title = RapidMiner Einstellungen -#gui.dialog.settings.icon = clipboard_check_edit.png -gui.dialog.settings.message = Konfiguration des Verhaltens und der Darstellung von RapidMiner Studio. - -gui.action.settings_apply.label = Speichern -gui.action.settings_apply.mne = S -#gui.action.settings_apply.icon = floppy_disk.png -gui.action.settings_apply.tip = Einstellungen anwenden und in der RapidMiner Konfigurationsdatei speichern. - -gui.action.settings_ok.label = Anwenden -#gui.action.settings_ok.icon = check.png -gui.action.settings_ok.mne = A -gui.action.settings_ok.tip = Einstellungen speichern und Dialog schliessen. - -#ErrorDialog -gui.dialog.error.title = Fehler aufgetreten -#gui.dialog.error.icon = error.png -gui.dialog.error.show_details.label = Details anzeigen -#gui.dialog.error.show_details.icon = document_text_view.png -gui.dialog.error.show_details.tip = Detaillierte Fehlerbeschreibung anzeigen - -gui.action.show_offending_operator.label = Fehlerhafter Operator: {0} -gui.action.show_offending_operator.mne = F - -gui.dialog.error.entry_of_wrong_type.title = Eingabe im falschen Werteformat. -gui.dialog.error.entry_of_wrong_type.message = Die ausgewählte Eingabe {0} hat nicht das richtige Format. -gui.dialog.error.enter_email.title = Formular unvollständig -gui.dialog.error.enter_email.message = Bitte eine Emailadresse eingeben. -gui.dialog.error.enter_correct_email.title = Formular unvollständig -gui.dialog.error.enter_correct_email.message = Bitte eine gültige Emailadresse eingeben. -gui.dialog.error.enter_password.title = Formular unvollständig -gui.dialog.error.enter_password.message = Bitte Passwort eingeben. -gui.dialog.error.enter_summary.title = Formular unvollständig -gui.dialog.error.enter_summary.message = Bitte eine beschreibende Zusammenfassung des Fehlers eingeben. -gui.dialog.error.enter_descriptive_summary.title = Formular unvollständig -gui.dialog.error.enter_descriptive_summary.message = Bitte eine beschreibende Zusammenfassung des Fehlers eingeben. (Ein Wort ist keine beschreibende Zusammenfassung!) -gui.dialog.error.enter_description.title = Formular unvollständig -gui.dialog.error.enter_description.message = Bitte eine kurze Beschreibung des Fehlers eingeben. -gui.dialog.error.bugreport_creation_failed.title = Bugbericht fehlgeschlagen -gui.dialog.error.bugreport_creation_failed.message = Bericht kann nicht erstellt werden. - -gui.dialog.error.cannot_start_attr_editor.title = Attributeditor kann nicht gestartet werden -gui.dialog.error.cannot_start_attr_editor.message = Attributeditor kann nicht gestartet werden: Erstellung eines BeispielQuellen Operators nicht möglich! - -gui.dialog.error.must_contain_mean_real.title = Eingabefeld 'Durchschnitt' ist unzulässig -gui.dialog.error.must_contain_mean_real.message = Das Eingabefeld 'Durchschnitt' muss einen realen Wert enthalten. - -gui.dialog.error.must_contain_variance_real.title = Eingabefeld 'Varianz' ist unzulässig -gui.dialog.error.must_contain_variance_real.message = Das Eingabefeld 'Varianz' muss einen realen Wert enthalten. - -gui.dialog.error.must_contain_number_pos_integer.title = Eingabefeld 'Nummer' ist unzulässig -gui.dialog.error.must_contain_number_pos_integer.message = Das Eingabefeld 'Nummer' muss einen ganzzahligen Wert > 1 enthalten. - -gui.dialog.error.sign_lvl_between_0_1.title = Das Signifikanzlevel ist unzulässig -gui.dialog.error.sign_lvl_between_0_1.message = Das Signifikanzlevel muss einen Wert zwischen 0 und 1 enthalten. - -gui.dialog.error.two_rows_to_calc_anova_test.title = ANOVA-Test -gui.dialog.error.two_rows_to_calc_anova_test.message = Sie müssen mindestens zwei Reihen hinzufügen, um einen ANOVA-Test durchzuführen. - -gui.dialog.error.only_num_values_for_min_nr_of_items.title = Nur numerische Werte sind erlaubt -gui.dialog.error.only_num_values_for_min_nr_of_items.message = Für die minimale Anzahl an Elementen sind nur numerische Werte erlaubt. - -gui.dialog.error.enter_k_value.title = Parameter unvollständig -gui.dialog.error.enter_k_value.message = Bitte geben Sie einen ganzzahligen Wert für k ein - -gui.dialog.error.mandatory_parameters_missing.title =Pflichtparameter fehlen -gui.dialog.error.mandatory_parameters_missing.message = Bitte Werte für alle Pflichtparameter eingeben. - - -gui.dialog.error.same_output_as_input_file.title = Es kann nicht die gleiche Eingangsdatei als Ausgangsdatei verwendet werden -gui.dialog.error.same_output_as_input_file.message = Es kann nicht die gleiche Eingangsdatei als Ausgangsdatei verwendet werden: Bitte wählen Sie einen anderen Dateinamen. - -gui.dialog.error.no_data_file_and_proper_settings.title = Keine Datendatei oder vollständige Einstellungen festgelegt -gui.dialog.error.no_data_file_and_proper_settings.message = Es müssen eine Datendatei und vollständige Einstellunge festgelegt werden - ohne wird der Operator nicht funktionieren. Zum Beenden dieses Assistenten drücken Sie "Abbrechen". - -gui.dialog.error.no_file_name_for_attr_desc.title = Es wurde kein Dateiname für die Attributbeschreibungs Datei angegeben -gui.dialog.error.no_file_name_for_attr_desc.message = Es muss eine Dateiname für die Attributsbeschreibungs Datei angegeben werden - ohne wird der Operator nicht funktionieren. Zum Beenden dieses Assistenten drücken Sie "Abbrechen". - -gui.dialog.error.no_building_block_name.title = Name für die Vorlage nicht angegeben -gui.dialog.error.no_building_block_name.message = Bitte geben Sie einen Namen für diese Voralge ein! - -gui.dialog.error.no_user_name.title = Kein Benutzername angegeben -gui.dialog.error.no_user_name.message = Bitte geben Sie einen Benutzernamen ein! - -gui.dialog.error.no_connection_data.title = Keine Verbindungsdaten angegeben -gui.dialog.error.no_connection_data.message = Bitte geben Sie die benötigten Verbindungsdaten ein! - -gui.dialog.error.no_name_or_ip.title = Kein Servername oder IP angegeben -gui.dialog.error.no_name_or_ip.message = Bitte geben Sie den Servernamen oder die IP einer Datenbank ein! - -gui.dialog.error.no_db_name.title = Kein Datenbankname angegeben -gui.dialog.error.no_db_name.message = Bitte geben Sie den Datenbanknamen ein! - -gui.dialog.error.no_db_connection_and_settings.title = Sie müssen eine Datenbankverbindung und die richtigen Einstellungen angeben -gui.dialog.error.no_db_connection_and_settings.message = Sie müssen eine Datenbankverbindung und die richtigen Einstellungen angeben - ohne wird der Operator nicht funktionieren. Zum Beenden dieses Assistenten drücken Sie "Abbrechen". - -gui.dialog.error.cannot_insert_operator.title = Operator kann nicht eingefügt werden -gui.dialog.error.cannot_insert_operator.message = Operator kann nicht eingefügt werden. - -gui.dialog.error.invalid_perspective_name.title = Perspektivenname unzulässig -gui.dialog.error.invalid_perspective_name.message = Perspektive kann nicht erstellt werden: bitte einen zulässigen Namen angeben. - -gui.dialog.error.illegal_url.title = Illegale URL -gui.dialog.error.illegal_url.message = Illegale URL - -gui.dialog.error.run_proc_remote.title = Fehler beim Remotedurchlauf des Prozesses -gui.dialog.error.run_proc_remote.message = Fehler beim Remotedurchlauf des Prozesses. - -gui.dialog.error.default_workspace.title = Benutze standard Arbeitsplatzverzeichnis -gui.dialog.error.default_workspace.message = RapidMiner benötigt ein Arbeitsplatzverzeichnis um richtig zu funktionieren. Benutzte nun die Standardeinstellung, dies kann im Dateimenü geändert werden. - -gui.dialog.error.op_replaced_failed_connections_restored.title = Operator ersetzt -gui.dialog.error.op_replaced_failed_connections_restored.message = Der Operator wurde ersetzt, aber {0} Verbindung(en) konnten nicht automatisch wieder hergestellt werden. - -gui.dialog.error.proc_failed_out_of_mem.title = Prozess fehlgeschlagen -gui.dialog.error.proc_failed_out_of_mem.message = Dieser Prozess würde mehr als den maximal verfügbaren Speicherplatz benötigen. Entweder lassen Sie diesen Prozess auf einem Computer mit mehr Speicherkapazität laufen, mit einem Stichprobenoperator die Datenmenge reduzieren, den Prozess durch andere Lernverfahren oder Vorverarbeitungsschritte optimieren oder direkt in einem Datenbanksystem arbeiten, z.B. durch Verwendung der Stream Datenbank. - -gui.dialog.error.proc_failed_without_obv_reason.title = Prozess fehlgeschlagen -gui.dialog.error.proc_failed_without_obv_reason.message = Der Aufbau scheint keine ersichtlichen Fehler zu enthalten, dennoch sollten Sie die Lognachrichten überprüfen oder den Debugmudus bei den Einstellungen aktivieren, um mehr Informtaionen über dieses Problem zu erhalten. - -gui.dialog.error.proc_failed_errors.title = Prozess fehlgeschlagen -gui.dialog.error.proc_failed_errors.message = Der Aufbau scheint Fehler zu enthalten, bitte überprüfen Sie ihn und die Lognachrichten. - -gui.dialog.error.op_deleted.title = Operator gelöscht -gui.dialog.error.op_deleted.message = Der Operator {0} wurde aus dem Prozess gelöscht. - -gui.dialog.error.som.only_nr_width.title = Falscher Parameter -gui.dialog.error.som.only_nr_width.message = Es sind für die SOM Breite nur Zahlen erlaubt. - -gui.dialog.error.som.only_nr_height.title = Falscher Parameter -gui.dialog.error.som.only_nr_height.message = Es sind für die SOM Höhe nur Zahlen erlaubt. - -gui.dialog.error.som.only_nr_radius.title = Falscher Parameter -gui.dialog.error.som.only_nr_radius.message = Es sind für den Radius nur Zahlen erlaubt. - -gui.dialog.error.som.only_nr_rounds.title = Falscher Parameter -gui.dialog.error.som.only_nr_rounds.message = Es sind für die Anzahl der Traningsrunden nur Zahlen erlaubt. - -gui.dialog.error.cannot_retrieve_obj_inf.title = Es können keine Informationen für Objekt {0} aufgerufen werden -gui.dialog.error.cannot_retrieve_obj_inf.message = Es können keine Informationen für Objekt {0} aufgerufen werden. - -gui.dialog.error.no_visual_for_obj.title = Das Objekt mit der ID {0} kann nicht abgebildet werden! -gui.dialog.error.no_visual_for_obj.message = Für das Objekt mit der ID {0} steht keine Visualisierung zur Verfügung! - - -gui.dialog.error.cannot_write_es_to_file.title = Beispielgruppe kann nicht in Datei ''{0}'' gespeichert werden -gui.dialog.error.cannot_write_es_to_file.message = Beispielgruppe kann nicht in Datei ''{0}'' gespeichert werden. - -gui.dialog.error.cannot_instantiate_building_block.title = Baustein ''{0}'' kann nicht instanziiert werden -gui.dialog.error.cannot_instantiate_building_block.message = Baustein ''{0}'' kann nicht instanziiert werden. - -gui.dialog.error.cannot_create_building_block.title = Baustein kann nicht erstellt werden -gui.dialog.error.cannot_create_building_block.message = Baustein kann nicht erstellt werden. - -gui.dialog.error.printer_error.title = Druckerfehler -gui.dialog.error.printer_error.message = Druckerfehler. - -gui.dialog.error.malformed_rep_location.title = Fehlerhaftes Repository-Verzeichnis ''{0}'' -gui.dialog.error.malformed_rep_location.message = Fehlerhaftes Repository-Verzeichnis ''{0}''. - -gui.dialog.error.cannot_store_obj_at_location.title = Objekt kann nicht in ''{0}'' gespeichert werden -gui.dialog.error.cannot_store_obj_at_location.message = Objekt kann nicht in ''{0}'' gespeichert werden. - -gui.dialog.error.cannot_load_obj_from_location.title = Objekt kann nicht aus ''{0}'' geladen werden -gui.dialog.error.cannot_load_obj_from_location.message = Objekt kann nicht aus ''{0}'' geladen werden. - -gui.dialog.error.cannot_calc_anova.title = ANOVA kann nicht berechnet werden -gui.dialog.error.cannot_calc_anova.message = ANOVA kann nicht berechnet werden. - -gui.dialog.error.cannot_find_url.title = ''{0}'' kann nicht gefunden werden -gui.dialog.error.cannot_find_url.message = ''{0}'' kann nicht gefunden werden! - -gui.dialog.error.cannot_calc_statistical_significance.title = Statistische Signifikanz kann nicht berechnet werden -gui.dialog.error.cannot_calc_statistical_significance.message = Statistische Signifikanz kann nicht berechnet werden - -gui.dialog.error.cannot_open_browser.title = Browser kann nicht geöffnet werden -gui.dialog.error.cannot_open_browser.message = Browser kann nicht geöffnet werden. - -gui.dialog.error.cannot_write_building_block_file.title = Bausteindatei kann nicht erstellt werden -gui.dialog.error.cannot_write_building_block_file.message = Bausteindatei kann nicht erstellt werden. - -gui.dialog.error.cannot_save_properties.title = Eigenschaften können nicht gespeichert werden -gui.dialog.error.cannot_save_properties.message = Eigenschaften können nicht gespeichert werden. - -gui.dialog.error.cannot_write_to_file.title = Kann nicht in Datei schreiben -gui.dialog.error.cannot_write_to_file.message = Kann nicht in Datei schreiben. - -gui.dialog.error.cannot_write_to_file_0.title = Kann nicht in Datei ''{0}'' schreiben -gui.dialog.error.cannot_write_to_file_0.message = Kann nicht in Datei ''{0}'' schreiben. - -gui.dialog.error.cannot_rename_entry.title = Umbenennung fehlgeschlagen -gui.dialog.error.cannot_rename_entry.message = Eintrag ''{0}'' kann nicht in ''{1}'' umbenannt werden.

    Grund: {2} - -gui.dialog.error.cannot_store_process_in_repository.title = Speicherprozess fehlgeschlagen -gui.dialog.error.cannot_store_process_in_repository.message = Prozess ''{0}'' kann nicht im Repository gespeichert werden. - -gui.dialog.error.cannot_create_operator.title = Operator kann nicht erstellt werden -gui.dialog.error.cannot_create_operator.message = Operator kann nicht erstellt werden. - -gui.dialog.error.error_during_logging.title = Fehler beim Loggen -gui.dialog.error.error_during_logging.message = Fehler beim Loggen. - -gui.dialog.error.es_conf_wizard_was_not_able_to_write_file.title = Der Datenquellen-Konfigurationsassistent konnte keine Datei erstellen -gui.dialog.error.es_conf_wizard_was_not_able_to_write_file.message = Der Assistent zur Datenquellen-Konfiguration konnte keine Datei erstellen. - -gui.dialog.error.cannot_guess_value_types.title = Wertformat kann nicht erraten werden -gui.dialog.error.cannot_guess_value_types.message = Wertformat kann nicht erraten werden. - -gui.dialog.error.cannot_close_stream_to_data_file.title = Fehler beim Schlieߟen der Datei -gui.dialog.error.cannot_close_stream_to_data_file.message = Datei kann nicht geschlossen werden. - -gui.dialog.error.while_loading.title = Fehler beim Öffnen von ''{0}'' -gui.dialog.error.while_loading.message = Fehler beim Öffnen von ''{0}'': {1} - -gui.dialog.error.no_data_or_process.title = Illegales Eingabeformat -gui.dialog.error.no_data_or_process.message = Bitte wählen Sie entwerder eine Prozess- oder Dateneingabe. - -gui.dialog.error.please_enter_non_empty_name.title = Bitte Namen eingeben -gui.dialog.error.please_enter_non_empty_name.message = Es muss ein nicht leerer Name eingegeben werden, um den Prozess zu speichern. - -gui.dialog.error.name_contains_illegal_chars.title = Bitte gültigen Namen eingeben -gui.dialog.error.name_contains_illegal_chars.message = ''{0}'' enthält ungültige Zeichen welche nicht auf dem Dateisystem gespeichert werden können. Bitte gültigen Namen eingeben! - -gui.dialog.error.run_remote_now_repo_error.title = Repository-Fehler -gui.dialog.error.run_remote_now_repo_error.message = Konnte Repository des Prozesses nicht finden. - -gui.dialog.error.run_remote_now_general_error.title = Fehler beim Ausführen des Prozesses auf RapidMiner Server -gui.dialog.error.run_remote_now_general_error.message = Der Prozess ist kein Remote-Prozess und konnte somit nicht auf RapidMiner Server ausgeführt werden. - - - -gui.dialog.error.while_following_link.title = Fehler beim Öffnen des Links -gui.dialog.error.while_following_link.message = Fehler beim Öffnen des Links. - -gui.dialog.error.cannot_create_process_embedder.title = Prozesseinbinder kann nicht erstellt werden -gui.dialog.error.cannot_create_process_embedder.message = Prozesseinbinder kann nicht erstellt werden - -gui.dialog.error.cannot_create_reader_for_file.title = Datei ''{0}'' kann nicht zum Lesen geöffnet werden -gui.dialog.error.cannot_create_reader_for_file.message = Datei ''{0}'' kann nicht zum Lesen geöffnet werden. - -gui.dialog.error.cannot_load_attr_weights_from_file.title = Attributgewichtung kann nicht aus Datei ''{0}'' geladen werden -gui.dialog.error.cannot_load_attr_weights_from_file.message = Attributgewichtung kann nicht aus Datei ''{0}'' geladen werden. - -gui.dialog.error.cannot_write_attr_weights_to_file.title = Attributgewichtung kann nicht in Datei ''{0}'' gespeichert werden -gui.dialog.error.cannot_write_attr_weights_to_file.message = Attributgewichtung kann nicht in Datei ''{0}'' gespeichert werden - -gui.dialog.error.cannot_create_repository.title = Repository kann nicht erstellt werden -gui.dialog.error.cannot_create_repository.message = Repository kann nicht erstellt werden. Bitte Ort und Alias auf Gültigkeit prüfen. - -gui.dialog.error.cannot_configure_repository.title = Repository kann nicht konfiguriert werden -gui.dialog.error.cannot_configure_repository.message = Repository kann nicht konfiguriert werden. Bitte Ort und Alias auf Gültigkeit prüfen. - -gui.dialog.error.error_connecting_to_server.title = Fehler bei der Verbindung zum Server -gui.dialog.error.error_connecting_to_server.message = Fehler bei der Verbindung zum Server. - -gui.dialog.message.process_will_first_run.title = Geplanter Prozess -gui.dialog.message.process_will_first_run.message = Erste Ausführung des Prozesses: {0}. - -gui.dialog.message.process_remote_executed.title = Prozess ausgeführt -gui.dialog.message.process_remote_executed.message = Prozess auf RapidMiner Server erfolgreich gestartet. - -gui.dialog.error.cannot_parse_date.title = Datum kann nicht geparst werden -gui.dialog.error.cannot_parse_date.message = Datum kann nicht geparst werden - -gui.dialog.error.cannot_load_attr_descr.title = Attributbeschreibungen können nicht geladen werden -gui.dialog.error.cannot_load_attr_descr.message = Attributbeschreibungen können nicht geladen werden. - -gui.dialog.error.cannot_instantiate.title = ''{0}'' kann nicht instanziiert werden -gui.dialog.error.cannot_instantiate.message = ''{0}'' kann nicht instanziiert werden. - -gui.dialog.error.cannot_load_data.title = Daten können nicht geladen werden -gui.dialog.error.cannot_load_data.message = Daten können nicht geladen werden. - -gui.dialog.error.process_failed_simple.title = Prozess fehlgeschlagen -gui.dialog.error.process_failed_simple.message = Prozess fehlgeschlagen. - -gui.dialog.error.process_failed_reason.message = Grund: - -gui.dialog.error.process_failed_user_error.title = Prozess fehlgeschlagen -gui.dialog.error.process_failed_user_error.message =

    {0}

    {1}

    - -gui.dialog.error.cannot_create_folder.title = Ordner kann nicht erstellt werden -gui.dialog.error.cannot_create_folder.message = Ordner ''{0}'' kann nicht erstellt werden. - -gui.dialog.error.cannot_refresh_folder.title = Ordner kann nicht aktualisiert werden -gui.dialog.error.cannot_refresh_folder.message = Ordner kann nicht aktualisiert werden. - -gui.dialog.error.cannot_open_in_filebrowser.title = Dateimanager kann nicht geöffnet werden -gui.dialog.error.cannot_open_in_filebrowser.message = Eintrag kann nicht im Dateimanager angezeigt werden. - -gui.dialog.error.cannot_open_in_filebrowser_io.title = Dateimanager kann nicht geöffnet werden -gui.dialog.error.cannot_open_in_filebrowser_io.message = Das Betriebssystem konnte den Ordner nicht in einem Dateimanager öffnen. - -gui.dialog.error.cannot_fetch_data_from_repository.title = Daten aus dem Repository können nicht geladen werden -gui.dialog.error.cannot_fetch_data_from_repository.message = Daten aus dem Repository können nicht geladen werden. - -gui.dialog.error.error_fetching_folder_contents_from_server.title = Fehler beim Laden des Ordnerinhalts vom Server -gui.dialog.error.error_fetching_folder_contents_from_server.message = Fehler beim Laden des Ordnerinhalts vom Server. Wenn die Fehlermeldung angibt, dass der Server die Anfrage zu oft weitersendet, liegt dies wahrscheinlich an einem fehlerhaften Benutzernamen/Passwort und einem BASIC Authentifizierungsmechanismus. - -gui.dialog.error.cannot_start_process.title = Prozess kann nicht gestartet werden -gui.dialog.error.cannot_start_process.message = Prozess kann nicht gestartet werden. - -gui.dialog.error.cannot_save_process.title = Prozess kann nicht gespeichert werden -gui.dialog.error.cannot_save_process.message = Prozess kann nicht unter ''{0}'' gespeichert werden: {1} - -gui.dialog.error.save_to_read_only_repo.title = Prozess kann nicht gespeichert werden -gui.dialog.error.save_to_read_only_repo.message = Prozess {0} kann nicht gespeichert werden. Speichern in ein schreibgeschützes Verzeichnis ist nicht erlaubt. Bitte wählen Sie einen gültigen Speicherort. -gui.dialog.error.save_to_read_only_repo.icon = folder_open_lock.png - -gui.dialog.error.cannot_access_repository.title = Repository kann nicht geöffnet werden -gui.dialog.error.cannot_access_repository.message = Der angegebene Repositoryeintrag kann nicht geöffnet werden. - -gui.dialog.error.cannot_find_repository_location.title = Nicht gefunden -gui.dialog.error.cannot_find_repository_location.message = Der Repositoryeintrag {0} existiert nicht. - -gui.dialog.error.cannot_write_data_into_file.title = Daten können nicht in der Datei gespeichert werden -gui.dialog.error.cannot_write_data_into_file.message = Daten können nicht in der Datei gespeichert werden. - -gui.dialog.error.cannot_write_log_file.title = Logdatei kann nicht geschrieben werden -gui.dialog.error.cannot_write_log_file.message = Logdatei kann nicht geschrieben werden. - -gui.dialog.error.cannot_write_history_file.title = Verlaufdatei kann nicht erstellt werden -gui.dialog.error.cannot_write_history_file.message = Verlaufdatei kann nicht erstellt werden. - -gui.dialog.error.while_changing_process.title = Fehler beim Ändern des Prozesses -gui.dialog.error.while_changing_process.message = Fehler beim Ändern des Prozesses. - -gui.dialog.error.cannot_instantiate_plotter.title = Plotter ''{0}'' kann nicht instanziiert werden -gui.dialog.error.cannot_instantiate_plotter.message = Plotter ''{0}'' kann nicht instanziiert werden. - -gui.dialog.error.cannot_re_write_data.title = Daten können nicht überschrieben werden -gui.dialog.error.cannot_re_write_data.message = Daten können nicht überschrieben werden. - -gui.dialog.error.cannot_load_tutorial_file.title = Tutoriumsdatei ''{0}'' kann nicht geöffnet werden -gui.dialog.error.cannot_load_tutorial_file.message = Tutoriumsdatei ''{0}'' kann nicht geöffnet werden. - -gui.dialog.error.error_in_paste.title = Operator kann nicht eingefügt werden -gui.dialog.error.error_in_paste.message = Operator kann nicht eingefügt werden: {0} - - -gui.dialog.error.plotting.grouping.illegal_column_type.title = Gruppierung kann nicht erstellt werden -gui.dialog.error.plotting.grouping.illegal_column_type.message = Begründung: {0} - -gui.dialog.error.plotting.general_error.title = Plot kann nicht erstellt werden -gui.dialog.error.plotting.general_error.message = Ursache\n\: {0} - - - - -#End ErrorDialog - -# BugReport -gui.action.send_bugreport.label = Bugbericht senden... -gui.action.send_bugreport.mne = s -#gui.action.send_bugreport.icon = bug_error.png -gui.action.send_bugreport.tip = Bugbericht an das RapidMiner Entwicklerteam senden. - -gui.dialog.confirm.send_bugreport.confirm.title = Sind Sie sicher? -gui.dialog.confirm.send_bugreport.confirm.message = Der aufgetretende Fehler ist möglicherweise durch die fehlerhafte Benutzung von RapidMiner aufgetreten und nicht aufgrund eines Bugs. Wollen Sie wirkliche einen Bugbericht absenden? - -gui.dialog.message.send_bugreport.import_operator_message.title = Information -gui.dialog.message.send_bugreport.import_operator_message.message = Sollte ihr Bugbericht etwas mit ihrem derzeitigen Prozess zu tun haben, fügen Sie bitte die Datendatei(en) durch 'Datei anhängen...' hinzu. Ohne die Daten für den Prozess könnte der Bug nicht reproduzierbar sein. -#gui.dialog.message.send_bugreport.import_operator_message.icon = sign_warning.png -gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.title = Bitte helfen Sie uns dabei doppelte Bugberichte zu vermeiden -gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.message = Bitte überprüfen Sie im neu geöffneten Fenster, ob einer der aufgelisteten (und somit schon registrierten) Bugs mit Ihrem übereinstimmt. Durch die Vermeidung von doppelten Bugberichten helfen Sie aktiv dabei unnötige Arbeit zu reduzieren, was dann wiederum zu schneller Bearbeitung der Bugs führt. Deswegen senden Sie Ihren Bericht bitte nur, wenn Sie sicher sind, dass der Bug noch nicht gemeldet wurde. Bugbericht trotzdem einreichen? -#gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.icon = sign_warning.png - -gui.dialog.send_bugreport.title = Bugbericht absenden -#gui.dialog.send_bugreport.icon = bug_error.png -gui.dialog.send_bugreport.message = Dieses Fenster wird Ihnen beim Erstellen des Bugberichts helfen. Es sammelt automatisch das Meiste der n\u00F6tigen Daten, um das Problem zu behandeln (z.B. die Stacktrace, den Prozess und die Systemeinstellungen). Sollte der Bug nichts mit Ihrem Prozess zu tun haben, k\u00F6nnen Sie "Prozess anh\u00E4ngen" deaktivieren. Sie k\u00F6nnen auch verhinden, dass ihre Systemeinstellungen \u00FCbertragen werden, durch Deaktivierung von "Systemeinstellungen anh\u00E4ngen", allerdings k\u00F6nnen Sie wichtige Informationen \u00FCber den Bug und somit Hilfe bei seiner L\u00F6sung enthalten. Um den endg\u00FCltigen Bugbericht zu sehen w\u00E4hlen Sie "Bericht ansehen". Sollten Sie nocht weitere wichtige Dateien hinzuf\u00FCgen wollen (z.B. Datendateien) k\u00F6nnen Sie dies mit einem Klick auf "Datei anh\u00E4ngen..." machen. Wenn Sie fertig sind klicken Sie "Senden", um den Bugbericht einzureichen. -#bis hier 1 -gui.dialog.send_bugreport_info.title = Bugbericht Übersicht -#gui.dialog.send_bugreport_info.icon = bug_error.png -gui.dialog.send_bugreport_info.message = Dies ist eine Übersicht der Daten, die an den Bugtracker gesendet werden.

    Bitte beachten Sie: Hier erscheinende Dinge werden öffentlich sichtbar sein! -gui.dialog.send_bugreport.description.text = Geben Sie eine kurze Beschreibung des Geschehenen in dieses Textfeld ein. Bitte beschreiben Sie au\u00DFerdem den Zweck ihres Prozesses, denn dieser kann gegebenenfalls nicht aus dem Prozessaufbau erschlossen werden. -gui.dialog.send_bugreport.login_e_mail.tip = Geben Sie ihre RapidMiner Bugtracker Emailadresse zum einloggen an. -gui.dialog.send_bugreport.login_password.label = Bugtracker Passwort: -gui.dialog.send_bugreport.login_password.tip = Geben Sie ihre RapidMiner Bugtracker Passwort zum einloggen an. -gui.dialog.send_bugreport.login_as_anonymous.label =Benutze anonymes Einloggen -gui.dialog.send_bugreport.login_as_anonymous.tip = Durch Auswahl dieser Option wird der Bericht anonym erstellt. -gui.dialog.send_bugreport.add_process_xml.label = Prozess anhängen -gui.dialog.send_bugreport.add_process_xml.tip = Durch Auswahl dieser Option wird dem Bericht der aktuelle Prozess beigefügt. -gui.dialog.send_bugreport.add_system_props.label = Systemeinstellungen anhängen -gui.dialog.send_bugreport.add_system_props.tip = Durch Auswahl dieser Option werden dem Bericht die Systemeinstellungen beigefügt. Diese können wichtige Informationen über den Bug und somit Hilfe bei seiner Lösung enthalten. -gui.dialog.send_bugreport.component.label = Modul -gui.dialog.send_bugreport.component.tip = Wählen Sie das zum Bug zugehörige RapidMiner Modul aus. -gui.dialog.send_bugreport.severity.label = Gewicht -gui.dialog.send_bugreport.severity.tip = Wählen Sie die Gewichtigkeite des Bugs. -gui.dialog.send_bugreport.platform.label = Plattform -gui.dialog.send_bugreport.platform.tip = Wählen Sie die von Ihnen benutze Plattform. -gui.dialog.send_bugreport.os.label = Betriebssystem -gui.dialog.send_bugreport.os.tip = Wählen Sie das von Ihnen benutze Betriebssystem. -gui.dialog.send_bugreport.summary.label = Zusammenfassung -gui.dialog.send_bugreport.summary.tip = Geben Sie eine Zusammenfassung des Fehlers ein -gui.dialog.send_bugreport.description.label = Beschreibung -gui.dialog.send_bugreport.description.tip = Geben Sie eine kurze Beschreibung des Fehlers ein und erklären Sie gegebenenfalls den Zweck ihres Prozesses. -gui.dialog.send_bugreport.submit.show_system_properties.title = Sollen die folgenden informationen im Bugbericht enthalten sein? -gui.dialog.send_bugreport.submit.show_system_properties.label = Die unten stehenden Systeminformationen können möglicherweise wichtige informationen über den Bug und Hilfe bei seiner Behebung enthalten.
    Sind Sie damit einverstanden, dass diese Informationen im Bugbericht enthalten sind? -gui.action.send_bugreport.add_file.label = Datei anhängen... -#gui.action.send_bugreport.add_file.icon = paperclip_add.png -gui.action.send_bugreport.add_file.tip = Bugbericht eine Datei anhängen. -gui.action.send_bugreport.remove_file.label = Datei abhängen -#gui.action.send_bugreport.remove_file.icon = paperclip_delete.png -gui.action.send_bugreport.remove_file.tip = Datei von der Anhangliste entfernen. -gui.action.send_bugreport.save.label = Bericht speichern -#gui.action.send_bugreport.save.icon = save.png -gui.action.send_bugreport.savet.tip = Bugbericht in einem Ziprepository speichern. -gui.action.send_bugreport.submit.label = Senden -#gui.action.send_bugreport.submit.icon = mail_bug.png -gui.action.send_bugreport.submit.tip = Bugbericht senden. -gui.action.send_bugreport.info.label = Bericht ansehen -#gui.action.send_bugreport.info.icon = document_text_view.png -gui.action.send_bugreport.info.tip = Endgültigen Bericht ansehen, der zum Bugtracker gesendet wird. - -gui.dialog.message.bugreport_successful.title = Bugbericht erfolgreich -gui.dialog.message.bugreport_successful.message = Ihr Bugbericht wurde erfolgreich gesendet. -#gui.dialog.message.bugreport_successful.icon = check.png - -gui.dialog.search_replace.title = Suchen -gui.dialog.search_replace.message = Dieses Fenster ermöglicht die Suche und Ersetzung von Zeichen. -#gui.dialog.search_replace.icon = binocular.png -gui.dialog.search_replace.search.title = Suchen -gui.dialog.search_replace.search_replace.title = Suchen und ersetzen - -###################################### -# Result Renderers and Tabs -###################################### -gui.label.collectionviewer.select_leaf.label = Bitte wählen Sie ein Blatt des Kollektionsbaums oder der Liste - -gui.action.select_columns.label = Spalte wählen -#gui.action.select_columns.icon = table_selection_column.png -gui.action.select_columns.tip = Spalten wählen, die in der Metadatenansicht gezeigt werden sollen. - -gui.action.calculate_statistics.label = Statistik berechnen -#gui.action.calculate_statistics.icon = calculator.png -gui.action.calculate_statistics.tip = Statistik berechnen (könnte dauern!). - -gui.label.resulttab.creating_display.label = Bitte warten Sie bis die Ansicht erstellt wurde. -#gui.label.resulttab.creating_display.icon = 48/hourglass.png - -gui.label.resulttab.cannot_be_restored.label = Die Inhalte dieses Tabs aus der letzten RapidMinersitzung können nicht wiederhergestellt werden. -gui.label.resulttab.cannot_be_restored_process_result.label = Die Inhalte dieses Tabs aus der letzten RapidMinersitzung können nicht wiederhergestellt werden. Bei Ausführung eines Prozesses wird Ergebnis {0} angezeigt. -gui.label.resulttab.table_cannot_be_restored.label = Die Datentabelle dieses Tabs aus der letzten RapidMinersitzung kann nicht wiederhergestellt werden. - -gui.dialog.result.close_before_run.title = Ergebnisse schließen -#gui.dialog.result.close_before_run.icon = presentation_empty.png -gui.dialog.result.close_before_run.message = Alte Ergebnisse schließen bevor der Prozess gestartet wird? - -gui.action.resulthistory.restore_process.label = Prozess wiederherstellen -gui.action.resulthistory.restore_process.mne = P -#gui.action.resulthistory.restore_process.icon = nav_undo.png -gui.action.resulthistory.restore_process.tip = Version des Prozesses wiederherstellen, der diese Ergebnisse geliefert hat. - -gui.action.resulthistory.remove.label = Aus dem Verlauf entfernen -gui.action.resulthistory.remove.mne = V -#gui.action.resulthistory.remove.icon = delete.png -gui.action.resulthistory.remove.tip = Diesen Eintrag aus dem Ergebnisverlauf entfernen. - -gui.action.resulthistory.clear_history.label = Verlauf löschen -gui.action.resulthistory.clear_history.mne = s -#gui.action.resulthistory.clear_history.icon = delete.png -gui.action.resulthistory.clear_history.tip = Den ganzen Ergebnisverlauf löschen. - -gui.action.resulthistory.restore_data.label = Aus Repository wiederherstellen -gui.action.resulthistory.restore_data.mne = w -#gui.action.resulthistory.restore_data.icon = data.png -gui.action.resulthistory.restore_data.tip = Letzte Version aus dem Repository wiederherstellen. - -gui.action.resulthistory.open_data.label = Ergebnisse wieder öffnen -gui.action.resulthistory.open_data.mne = w -#gui.action.resulthistory.open_data.icon = presentation_chart.png -gui.action.resulthistory.open_data.tip = Ergebnisse in der Ergebnisansicht erneut öffnen. - -gui.dialog.cannot_restore_history_process.title = Fehler bei der Wiederherstellung des Prozesses -gui.dialog.cannot_restore_history_process.message = Wiederherstellung des Prozesses aus dem Verlauf fehlgeschlagen. - -###################################### -### ProgressThread -###################################### - -gui.dialog.progress_dialog.title = Fortschritt -gui.dialog.progress_dialog.message = Unerledigte Aufgaben: -#gui.dialog.progress_dialog.icon = hourglass.png -gui.label.progress_dialog.current.label = Aktuelle Aufgabe: -gui.label.progress_dialog.pending.label = Unerledigte Aufgaben: - -gui.dialog.error.error_executing_background_job.title = Fehler -gui.dialog.error.error_executing_background_job.message = Fehler beim Ausführen der Aufgabe ''{0}'' im Hintergrund: {1} - -gui.progress.copy_repository_entry.label=Kopiert -gui.progress.open_file.label=Öffnet Datei -gui.progress.open_process.label=Öffnet Prozess -gui.progress.add_repository.label=Fügt Repository hinzu -gui.progress.creating_display.label=Erstellt Anzeige -gui.progress.create_folder.label=Erstellt Ordner -gui.progress.refreshing.label=Aktualisiert -gui.progress.download_from_repository.label=Lädt -gui.progress.download_md_from_repository.label=Ruft Metadaten auf -gui.progress.store_process.label=Speichert Prozess -gui.progress.validate_process.label=Validiert Prozess -gui.progress.import_data.label=Fügt Daten ein -gui.progress.auto_wiring.label=Verbindet Opreatoren automatisch -gui.progress.fetching_database_tables.label=Lädt Datenbanktabellen -gui.progress.test_database_connection.label=Überprüft Datenbankverbindung -gui.progress.calculate_statistics.label=Berechnet Statistiken -gui.progress.connect_to_repository.label=Verbindet sich mit dem Repository -gui.progress.load_csv_file.label = Öffnet CSV Datei -gui.progress.load_workbook.label = Öffnet Excel Datei -gui.progress.show_error_rows.label = Ermittelt Fehler -gui.progress.validate_value_types.label = Validiert Wertformat -gui.progress.connect_to_bugzilla.label = Verbindet sich mit BugZilla -gui.progress.send_report_to_bugzilla.label = Sendet Bugbericht an BugZilla -gui.progress.run_remote_now.label = Starte Prozess auf RapidMiner Server -gui.progress.db_clear_cache.label = Lösche Datenbank-Metadaten Cache -gui.progress.import_binary.label = Öffnet Binärdatei -gui.progress.log_in_to_updateserver.label = Anmeldung am Update Server -gui.progress.log_out_frm_updateserver.label = Abmeldung vom Update Server -gui.progress.update_result_statistics.label = Aktualisiert Statistiken -#bis hier -######################################## -# Splash Screen -######################################## -gui.splash.rm_home = Sicherstellung, dass RapidMiner-Heimatverzeichnis gesetzt ist -gui.splash.register_plugins = Plugins werden registriert -gui.splash.init_setup = Initiiere Aufbau -gui.splash.init_parameter_service = Lese Systemeeinstellungsdateien -gui.splash.init_ops = Initiiere Operatoren -gui.splash.xml_transformer = Initiiere Regeln zur XML Transformation -gui.splash.init_repository = Initiiere Datenrepository -gui.splash.load_jdbc_drivers = Lade JDBC Treiber -gui.splash.xml_serialization = Initiiere XML Serialisierung -gui.splash.xml_alias = Erzeuge Übersetzungen für XML-Serialisierung -gui.splash.gen_key = Generiere Verschlüsselung -gui.splash.init_renderers = Initiiere Renderer - -gui.splash.loading_plugin = Lade {0} Erweiterung - -gui.splash.init_i18n = Initiiere I18N -gui.splash.basic = Grundinitialisierung -gui.splash.workspace = Initialisiere Arbeitsplatz -gui.splash.plaf = Konfiguriere Benutzeroberfläche -gui.splash.history = Lade Verlauf -#gui.splash.icons = Loading Icons -gui.splash.create_frame = Erstelle Rahmen -gui.splash.gui_properties = Lade GUI Eigenschaften -gui.splash.plugin_gui = Initiiere GUI Plugin -gui.splash.show_frame = Zeige Rahmen -gui.splash.checks = Initiiere Überprüfungen -gui.splash.ready = Bereit. - -######################################## -# RapidDocBotImporter -######################################## -gui.action.rapid_doc_bot_importer_online.label = -#gui.action.rapid_doc_bot_importer_online.icon = earth_network.png -gui.action.rapid_doc_bot_importer_online.tip = Hilfetext öffnen - -gui.action.rapid_doc_bot_importer_offline.label = -#gui.action.rapid_doc_bot_importer_offline.icon = earth_network.png -gui.action.rapid_doc_bot_importer_offline.tip = Hilfetext öffnen - -gui.action.rapid_doc_bot_importer_refresh.label = -#gui.action.rapid_doc_bot_importer_refresh.icon = refresh.png -gui.action.rapid_doc_bot_importer_refresh.tip = Operator vom WiKi aktualisieren - -gui.action.rapid_doc_bot_importer_showInBrowser.label = -#gui.action.rapid_doc_bot_importer_showInBrowser.icon = window_earth.png -gui.action.rapid_doc_bot_importer_showInBrowser.tip = Hilfetext im Browser öffnen - -gui.dialog.error.rapid_doc_bot_importer_showInBrowser.title = Öffnen des Browsers fehlgeschlagen -gui.dialog.error.rapid_doc_bot_importer_showInBrowser.message = Bitte Bugbericht senden. - -gui.dialog.error.rapid_doc_bot_importer_error.title = Anzeigen des Hilfetexts fehlgeschlagen - -gui.dialog.error.failed_to_fetch_database_tables.title=Datenbankfehler -gui.dialog.error.failed_to_fetch_database_tables.message=Fehler beim Aufrufen der Datenbanktabellen für die Verbindung {0}: {1} - -######################################## -# The Password Manager -######################################## -gui.dialog.password_manager.label = Passwörter verwalten -gui.dialog.password_manager.title = Passwortverwaltung, um Ihre Passwörter zu verwalten. -gui.dialog.password_manager.message = In diesem Fenster k\u00F6nnen Sie Ihre gecacheten Benutzerreferenzen sehen. Passw\u00F6rter werden automatisch verborgen. Um sie sichtbar zu machen klicken Sie auf "Passw\u00F6rter anzeigen". Sie k\u00F6nnen Eintr\u00E4ge l\u00F6schen indem Sie sie ausw\u00E4hlen und "Zeile entfernen" dr\u00FCcken. Benutzername und Passwort k\u00F6nnen ge\u00E4ndert werden, indem Sie die Daten in der Tabelle ver\u00E4ndern. -gui.dialog.password_manager.tip = Eine Passwortverwaltung für all Ihre gespeicherten Passwörter. -#gui.dialog.password_manager.icon = key.png - -gui.action.password_manager.label = Passwörter verwalten -#gui.action.password_manager.icon = key.png - -gui.action.password_manager_showpasswords.label = Passwörter anzeigen -gui.action.password_manager_showpasswords.tip = Klicken Sie hier, um Ihre Passwörter sichtbar zu machen. -#gui.action.password_manager_showpasswords.icon = magnifying_glass.png -gui.action.password_manager_remove_row.mne = a - -gui.action.password_manager_hidepasswords.label = Passwörter verbergen -gui.action.password_manager_hidepasswords.tip = Klicken Sie hier, um Ihre Passwörter zu verbergen. -#gui.action.password_manager_hidepasswords.icon = magnifying_glass.png - -gui.action.password_manager_remove_row.label = Zeile entfernen -#gui.action.password_manager_remove_row.icon = table_selection_row_delete.png -gui.action.password_manager_remove_row.tip = Ausgewählte Zeile entfernen. - -gui.action.password_manager_save.label = Speichern -#gui.action.password_manager_save.icon = ok.png -gui.action.password_manager_save.mne = S -gui.action.password_manager_save.tip = Speichern und beenden. - -#gui.action..label = -#gui.action..mne = -#gui.action..icon = -#gui.action..tip = -#gui.action..acc = - -#gui.action..label = -#gui.action..mne = -#gui.action..icon = -#gui.action..tip = -#gui.action..acc = - -##################################################### -# RapidMiner Tours and contents of BubbleWindows -##################################################### - -gui.dialog.Tour.title = Wähle eine Tour -gui.dialog.Tour.message = Wählen Sie eine Tour durch RapidMeiner oder einer ihrer installierten Extensions. - -gui.tour.RapidMiner.icon = rapidminer.png -gui.tour.RapidMiner.description = Diese Tour führt sie durch die Grundfunktionen von RapidMiner. - -gui.dialog.confirm.new_tour_found.title = neue Tour gefunden -gui.dialog.confirm.new_tour_found.message = Sie haben eine neue RapidMiner Tour mit dem Namen {0}-Tour. Um die Tour später zu starten klicken Sie auf den Wegweiser im Info-Bildschirm oder wählen Sie den Reiter Hilfe und dann "RapidMiner Tours ..." - -#################################################### ALT - -gui.action.toggle_breakpoint.label = Haltepunkt umschalten -gui.action.toggle_breakpoint.mne = H -gui.action.toggle_breakpoint.tip = Haltepunkt an diesem Operator ein-/ ausschalten. - -gui.errortable.header.message = Fehlermeldung -gui.errortable.header.port = Port - -gui.label.processpanel.subprocess.label = Teilprozess -gui.label.processpanel.nesting.label = Schachtelungshierarchie - -######################################## -# Text for Repository Access Rights dialog -######################################## - -gui.repository.remote.accessRights_IGNORE = Ignorieren -gui.repository.remote.accessRights_GRANT = Erlauben -gui.repository.remote.accessRights_REJECT = Verbieten -gui.repository.remote.accessRightsType_READ = Lesen -gui.repository.remote.accessRightsType_WRITE = Schreiben -gui.repository.remote.accessRightsType_EXECUTE = Ausführen - -######################################## -# Specified Ok Buttons -######################################## - -gui.action.access_rights_dialog_apply.label = Anwenden -gui.action.access_rights_dialog_apply.tip = Änderungen, die durch Ändern der Zugriffsrechte gemacht wurden, anwenden. -gui.action.access_rights_dialog_apply.icon = ok.png - -gui.action.run_remote_dialog_schedule.label = Planen -gui.action.run_remote_dialog_schedule.tip = Remote-Ausführung des Prozess. -gui.action.run_remote_dialog_schedule.icon = ok.png - -gui.action.attribute_ordering_dialog_order.label = Ordnen -gui.action.attribute_ordering_dialog_order.tip = Ordnen der Attribute-Regeln. -gui.action.attribute_ordering_dialog_order.icon = ok.png - -gui.action.text_property_dialog_apply.label = Anwenden -gui.action.text_property_dialog_apply.tip = Änderungen, die durch das Ändern des Parameter-Text gemacht wurden, anwenden. -gui.action.text_property_dialog_apply.icon = ok.png - -gui.action.management_building_blocks_dialog_apply.label = Anwenden -gui.action.management_building_blocks_dialog_apply.tip = Änderungen, die durch das Löschen der Management-Blöcke gemacht wurden, anwenden. -gui.action.management_building_blocks_dialog_apply.icon = ok.png - -gui.action.expression_property_dialog_apply.label = Anwenden -gui.action.expression_property_dialog_apply.tip = Änderungen, die durch das Spezifizieren eines regulären Ausdrucks gemacht wurden, anwenden. -gui.action.expression_property_dialog_apply.icon = ok.png - -gui.action.regexp_property_dialog_apply.label = Anwenden -gui.action.regexp_property_dialog_apply.tip = Änderungen, die durch das Spezifizieren eines regulären Ausdrucks gemacht wurden, anwenden. -gui.action.regexp_property_dialog_apply.icon = ok.png - -gui.action.set_parameter_dialog_apply.label = Anwenden -gui.action.set_parameter_dialog_apply.tip = Änderungen, die durch das Setzen eines Parameters gemacht wurden, anwenden. -gui.action.set_parameter_dialog_apply.icon = ok.png - -gui.action.attributes_property_dialog_apply.label = Anwenden -gui.action.attributes_property_dialog_apply.tip = Änderungen, die durch das Auswählen von Attributen gemacht wurden, anwenden. -gui.action.attributes_property_dialog_apply.icon = ok.png - -gui.action.list_property_dialog_apply.label = Anwenden -gui.action.list_property_dialog_apply.tip = Änderungen, die durch das Hinzufügen und Löschen von Parametern gemacht wurden, anwenden. -gui.action.list_property_dialog_apply.icon = ok.png - -gui.dialog.confirm.template.install_missing_extensions.title = Template benötigt Extensions -gui.dialog.confirm.template.install_missing_extensions.message = Zusätzliche Extensions ({0}) werden für dieses Template benötigt.

    Möchten Sie diese jetzt installieren? - diff --git a/src/main/resources/com/rapidminer/resources/i18n/GUI_ja.properties b/src/main/resources/com/rapidminer/resources/i18n/GUI_ja.properties deleted file mode 100644 index b677de9f7..000000000 --- a/src/main/resources/com/rapidminer/resources/i18n/GUI_ja.properties +++ /dev/null @@ -1,2896 +0,0 @@ -############### -## Dockables -############### - -gui.dockkey.remote_process_viewer.name = \u30ea\u30e2\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9 -#gui.dockkey.remote_process_viewer.icon = server2_play.png -gui.dockkey.remote_process_viewer.tip = \u30ea\u30e2\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u95b2\u89a7\u3068\u7ba1\u7406 - -gui.dockkey.welcome.name = \u3088\u3046\u3053\u305d -gui.dockkey.welcome.icon = about.png -gui.dockkey.welcome.tip = RapidMiner\u3078\u3088\u3046\u3053\u305d - -gui.dockkey.overview.name = \u6982\u8981 -gui.dockkey.overview.icon = magnifying_glass.png -gui.dockkey.overview.tip = \u30d7\u30ed\u30bb\u30b9\u30d3\u30e5\u30fc\u306e\u6982\u8981 - -gui.dockkey.repository_browser.name = \u30ea\u30dd\u30b8\u30c8\u30ea -gui.dockkey.repository_browser.icon = data.png -gui.dockkey.repository_browser.tip = \u30c7\u30fc\u30bf\u304a\u3088\u3073\u7d50\u679c\u3092\u53c2\u7167 - -gui.dockkey.operator_tree.name = \u968e\u5c64\u69cb\u9020 -gui.dockkey.operator_tree.icon = text_tree.png -gui.dockkey.operator_tree.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u306e\u968e\u5c64\u69cb\u9020 - -gui.dockkey.error_table.name = \u554f\u984c -gui.dockkey.error_table.icon = sign_warning.png -gui.dockkey.error_table.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u3067\u306e\u554f\u984c (\u30a8\u30e9\u30fc\u304a\u3088\u3073\u8b66\u544a) - -gui.dockkey.log_viewer.name = \u30ed\u30b0 -gui.dockkey.log_viewer.icon = document_empty_time.png -gui.dockkey.log_viewer.tip = \u30b3\u30f3\u30bd\u30fc\u30eb\u306b\u30ed\u30b0\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8868\u793a - -gui.dockkey.process_panel.name = \u30d7\u30ed\u30bb\u30b9 -gui.dockkey.process_panel.icon = vector_curve_cubic.png -gui.dockkey.process_panel.tip = \u30b0\u30e9\u30d5\u30ec\u30a4\u30a2\u30a6\u30c8\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u7de8\u96c6 - -gui.dockkey.xml_editor.name = XML -gui.dockkey.xml_editor.icon = code.png -gui.dockkey.xml_editor.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092XML\u5f62\u5f0f\u3067\u8868\u793a - -gui.dockkey.comment_editor.name = \u30b3\u30e1\u30f3\u30c8 -gui.dockkey.comment_editor.icon = document_text.png -gui.dockkey.comment_editor.tip = \u73fe\u5728\u9078\u629e\u3057\u3066\u3044\u308b\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30b3\u30e1\u30f3\u30c8\u30a8\u30c7\u30a3\u30bf\u3092\u8868\u793a - -gui.dockkey.property_editor.name = \u30d1\u30e9\u30e1\u30fc\u30bf -gui.dockkey.property_editor.icon = form_edit.png -gui.dockkey.property_editor.tip = \u73fe\u5728\u9078\u629e\u3057\u3066\u3044\u308b\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u8868\u793a - -gui.dockkey.result.name = \u7d50\u679c\u6982\u8981 -gui.dockkey.result.icon = presentation_chart.png -gui.dockkey.result.tip = \u9078\u629e\u3057\u3066\u3044\u308b\u30d7\u30ed\u30bb\u30b9\u306e\u73fe\u5728\u306e\u7d50\u679c\u3092\u8868\u793a - -gui.dockkey.new_operator.name = \u30aa\u30da\u30ec\u30fc\u30bf -gui.dockkey.new_operator.icon = element_new.png -gui.dockkey.new_operator.tip = \u5229\u7528\u53ef\u80fd\u306a\u5168\u3066\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u8868\u793a - -gui.dockkey.operator_help.name = \u30d8\u30eb\u30d7 -#gui.dockkey.operator_help.icon = lightbulb_on.png -gui.dockkey.operator_help.icon = question.png -gui.dockkey.operator_help.tip = \u73fe\u5728\u9078\u629e\u3057\u3066\u3044\u308b\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30d8\u30eb\u30d7\u6587\u7ae0\u3092\u8868\u793a - -gui.dockkey.operator_documentation_browser.name = \u30d8\u30eb\u30d7 -gui.dockkey.operator_documentation_browser.icon = question.png -gui.dockkey.operator_documentation_browser.tip = \u73fe\u5728\u9078\u629e\u3057\u3066\u3044\u308b\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30d8\u30eb\u30d7\u6587\u7ae0\u3092\u8868\u793a - -gui.dockkey.system_monitor.name = \u30b7\u30b9\u30c6\u30e0\u30e2\u30cb\u30bf -gui.dockkey.system_monitor.icon = window_oscillograph.png -gui.dockkey.system_monitor.tip = \u73fe\u5728\u306e\u30e1\u30e2\u30ea\u4f7f\u7528\u60c5\u5831\u3092\u8868\u793a - -gui.dockkey.process_context.name = \u74b0\u5883 -gui.dockkey.process_context.icon = environment.png -gui.dockkey.process_context.tip = \u30d7\u30ed\u30bb\u30b9\u306e\u74b0\u5883\u8a2d\u5b9a\u3092\u7de8\u96c6 - -# Toolbars -gui.toolbar.file.tip = \u30d5\u30a1\u30a4\u30eb -gui.toolbar.edit.tip = \u7de8\u96c6 -gui.toolbar.run.tip = \u5b9f\u884c -gui.toolbar.perspectives.tip = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6 - -# Workspace actions -gui.action.workspace_design.label = \u30c7\u30b6\u30a4\u30f3 -gui.action.workspace_design.tip = \u30c7\u30b6\u30a4\u30f3\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u306b\u5207\u308a\u66ff\u3048 -gui.action.workspace_design.icon = edit.png -gui.action.workspace_design.acc = F8 -gui.action.workspace_result.label = \u7d50\u679c -gui.action.workspace_result.icon = presentation_chart.png -gui.action.workspace_result.tip = \u7d50\u679c\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u306b\u5207\u308a\u66ff\u3048 -gui.action.workspace_result.acc = F9 -gui.action.workspace_welcome.label = \u3088\u3046\u3053\u305d -gui.action.workspace_welcome.tip = \u3088\u3046\u3053\u305d\u30b9\u30af\u30ea\u30fc\u30f3\u306b\u5207\u308a\u66ff\u3048 -gui.action.workspace_welcome.icon = about.png -gui.action.workspace_user.icon = window.png -gui.action.workspace_user.tip = {0}\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u306b\u5207\u308a\u66ff\u3048 - - -############################################################ -## Actions -############################################################ - -############################ -# GENERAL PURPOSE -############################ -gui.action.simple_link_action.label = {0} -gui.action.simple_link_action.tip = {0}\u3092\u30a6\u30a7\u30d6\u30d6\u30e9\u30a6\u30b6\u3067\u958b\u304f - -gui.action.cancel.label = \u30ad\u30e3\u30f3\u30bb\u30eb -gui.action.cancel.tip = \u5909\u66f4\u3092\u4fdd\u5b58\u305b\u305a\u306b\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u9589\u3058\u308b -gui.action.cancel.acc = ESCAPE -gui.action.cancel.mne = C -gui.action.cancel.icon = delete.png - -gui.action.ok.label = Ok -gui.action.ok.tip = \u5909\u66f4\u3092\u5168\u3066\u9069\u5fdc\u3057\u3066\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u9589\u3058\u308b -gui.action.ok.icon = check.png -#gui.action.ok.acc = ENTER # no accelerator, make this the default button - -gui.action.close.label = \u9589\u3058\u308b -gui.action.close.mne = C -gui.action.close.tip = \u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u9589\u3058\u308b -gui.action.close.icon = delete.png - -gui.action.previous.label = \u524d\u306b\u79fb\u52d5 -gui.action.previous.mne = P -gui.action.previous.tip = \u524d\u306e\u30da\u30fc\u30b8\u306b\u79fb\u52d5 -gui.action.previous.icon = arrow_left.png - -gui.action.next.label = \u6b21\u306b\u79fb\u52d5 -gui.action.next.mne = N -gui.action.next.tip = \u6b21\u306e\u30da\u30fc\u30b8\u306b\u79fb\u52d5 -gui.action.next.icon = arrow_right.png - -gui.action.finish.label = \u7d42\u4e86 -gui.action.finish.mne = F -gui.action.finish.tip = \u7d42\u4e86 -gui.action.finish.icon = signal_flag_checkered.png - -gui.action.dont_ask_again.label = \u6b21\u304b\u3089\u8868\u793a\u3057\u306a\u3044 -gui.action.dont_ask_again.tip = \u6b21\u56de\u3053\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u304c\u5b9f\u884c\u3055\u308c\u308b\u5834\u5408\u306f\u8868\u793a\u3092\u884c\u308f\u306a\u3044 -gui.action.dont_ask_again.mne = a - - -############################ -# FILE CHOOSER -############################ - -gui.dialog.file_chooser.open.title = \u958b\u304f -gui.dialog.file_chooser.open.message = \u958b\u304f\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.file_chooser.open.icon = folder_open.png - -gui.dialog.file_chooser.open_directory.title = \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u9078\u629e -gui.dialog.file_chooser.open_directory.message = \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.file_chooser.open_directory.icon = folder_open.png - -gui.dialog.file_chooser.save.title = \u4fdd\u5b58 -gui.dialog.file_chooser.save.message = \u4fdd\u5b58\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u306e\u540d\u79f0\u3068\u5834\u6240\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.file_chooser.save.icon = floppy_disk.png - -gui.action.file_chooser.new_folder.label = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0 -gui.action.file_chooser.new_folder.icon = folder_open_new.png -gui.action.file_chooser.new_folder.mne = N -gui.action.file_chooser.new_folder.tip = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0\u4f5c\u6210 - -gui.label.file_chooser.bookmarks.label = \u30d6\u30c3\u30af\u30de\u30fc\u30af - -gui.action.file_chooser.add_to_bookmarks.label = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0 -gui.action.file_chooser.add_to_bookmarks.icon = star_add.png -gui.action.file_chooser.add_to_bookmarks.mne = B -gui.action.file_chooser.add_to_bookmarks.tip = \u30d5\u30a9\u30eb\u30c0\u3092\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0 - -gui.action.file_chooser.rename_bookmark.label = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u540d\u79f0\u5909\u66f4 -gui.action.file_chooser.rename_bookmark.icon = star_edit.png -gui.action.file_chooser.rename_bookmark.tip = \u9078\u629e\u3057\u305f\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306e\u540d\u79f0\u3092\u5909\u66f4 - -gui.action.file_chooser.delete_bookmark.label = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u524a\u9664 -gui.action.file_chooser.delete_bookmark.icon = star_delete.png -gui.action.file_chooser.delete_bookmark.tip = \u9078\u629e\u3057\u305f\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u524a\u9664 - -gui.action.file_chooser.refresh.label = \u66f4\u65b0 -gui.action.file_chooser.refresh.icon = folder_open_refresh.png -gui.action.file_chooser.refresh.mne = R -gui.action.file_chooser.refresh.tip = \u30d3\u30e5\u30fc\u3092\u66f4\u65b0 -gui.action.file_chooser.refresh.acc = F5 - -gui.action.file_chooser.select_all.label = \u5168\u3066\u9078\u629e -gui.action.file_chooser.select_all.icon = folder_open_checkbox_checked.png -gui.action.file_chooser.select_all.mne = A -gui.action.file_chooser.select_all.acc = control A -gui.action.file_chooser.select_all.tip = \u5168\u3066\u306e\u30a2\u30a4\u30c6\u30e0\u3092\u9078\u629e - -gui.action.file_chooser.sort_by.label = \u4e26\u3073\u5909\u3048 -gui.action.file_chooser.sort_by.icon = sort_up_down_question.png -gui.action.file_chooser.sort_by.mne = S -gui.action.file_chooser.sort_by.tip = \u3053\u306e\u30a2\u30a4\u30c6\u30e0\u3092\u4e26\u3073\u66ff\u3048\u308b\u30ad\u30fc\u3092\u9078\u629e\u3057\u307e\u3059\u3002 - -gui.menu.file_chooser.sort_by.file_name = \u30d5\u30a1\u30a4\u30eb\u540d -gui.menu.file_chooser.sort_by.file_type = \u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 -gui.menu.file_chooser.sort_by.file_size = \u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba -gui.menu.file_chooser.sort_by.last_modified = \u6700\u7d42\u66f4\u65b0\u65e5\u6642 - -gui.action.file_chooser.view.label = \u30d3\u30e5\u30fc -gui.action.file_chooser.view.icon = window_view.png -gui.action.file_chooser.view.mne = V -gui.action.file_chooser.view.tip = \u30d3\u30e5\u30fc\u30bf\u30a4\u30d7\u3092\u9078\u629e - -gui.menu.file_chooser.view.thumbnails.label = \u30b5\u30e0\u30cd\u30a4\u30eb -gui.menu.file_chooser.view.icons.label = \u30a2\u30a4\u30b3\u30f3 -gui.menu.file_chooser.view.list.label = \u30ea\u30b9\u30c8 -gui.menu.file_chooser.view.details.label = \u8a73\u7d30 - -gui.action.file_chooser.auto_arrange.label = \u81ea\u52d5\u914d\u7f6e\u30a2\u30a4\u30c6\u30e0 -#gui.action.file_chooser.auto_arrange.icon = layout.png -gui.action.file_chooser.auto_arrange.tip = \u30a2\u30a4\u30c6\u30e0\u3092\u81ea\u52d5\u7684\u306b\u914d\u7f6e - -gui.action.file_chooser.change_to_parent_directory.label = \u89aa\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u79fb\u52d5 -gui.action.file_chooser.change_to_parent_directory.icon = folder_open_up.png -gui.action.file_chooser.change_to_parent_directory.tip = \u89aa\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u79fb\u52d5 - -gui.action.file_chooser.go_back.label = \u623b\u308b -gui.action.file_chooser.go_back.icon = arrow_left.png -gui.action.file_chooser.go_back.tip = \u524d\u306b\u79fb\u52d5\u3057\u305f\u30d5\u30a9\u30eb\u30c0\u306b\u79fb\u52d5 - -gui.action.file_chooser.go_home.label = \u30db\u30fc\u30e0\u306b\u79fb\u52d5 -gui.action.file_chooser.go_home.icon = home.png -gui.action.file_chooser.go_home.tip = \u30db\u30fc\u30e0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u79fb\u52d5 - -gui.action.file_chooser.open.label = \u958b\u304f -gui.action.file_chooser.open.icon = folder_open.png -#gui.action.file_chooser.open.tip = Open directory or file. - -gui.action.file_chooser.select.label = \u9078\u629e -gui.action.file_chooser.select.icon = folder_open.png - -gui.action.file_chooser.rename.label = \u540d\u79f0\u5909\u66f4 -gui.action.file_chooser.rename.icon = folder_open_edit.png - -gui.action.file_chooser.delete.label = \u524a\u9664 -gui.action.file_chooser.delete.icon = folder_open_delete.png - -gui.dialog.input.file_chooser.new_folder.title = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0 -gui.dialog.input.file_chooser.new_folder.icon = folder_open_new.png -gui.dialog.input.file_chooser.new_folder.message = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0\u306e\u540d\u524d\u3092\u633f\u5165\u3057\u3066\u304f\u3060\u3055\u3044 - -gui.dialog.error.file_chooser.new_folder.rename.title = \u30d5\u30a9\u30eb\u30c0\u4f5c\u6210 -gui.dialog.error.file_chooser.new_folder.rename.message =\u3000\u30d5\u30a9\u30eb\u30c0\u3092{0}\u306b\u540d\u79f0\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.file_chooser.new_folder.create.title = \u30d5\u30a9\u30eb\u30c0\u4f5c\u6210 -gui.dialog.error.file_chooser.new_folder.create.message = \u30d5\u30a9\u30eb\u30c0{0}\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 - -gui.dialog.input.file_chooser.bookmark_name.title = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u4f5c\u6210 -gui.dialog.input.file_chooser.bookmark_name.icon = star_add.png -gui.dialog.input.file_chooser.bookmark_name.message = \u30d5\u30a9\u30eb\u30c0{0}\u306b\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u633f\u5165 - -gui.dialog.confirm.file_chooser.delete.title = \u524a\u9664 -gui.dialog.confirm.file_chooser.delete.icon = folder_open_delete.png -gui.dialog.confirm.file_chooser.delete.message = {0}\u3092\u524a\u9664\u3057\u307e\u3059\u304b? - -gui.dialog.error.file_chooser.delete.error.title = \u524a\u9664 -gui.dialog.error.file_chooser.delete.error.message = {0}\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.input.file_chooser.rename.title = \u540d\u79f0\u5909\u66f4 -gui.dialog.input.file_chooser.rename.icon = folder_open_edit.png -gui.dialog.input.file_chooser.rename.message = {0}\u306b\u65b0\u898f\u540d\u79f0\u3092\u633f\u5165\u3057\u307e\u3059\u3002 - -gui.dialog.error.file_chooser.rename.invalid.title = \u540d\u79f0\u5909\u66f4 -gui.dialog.error.file_chooser.rename.invalid.message = \u6709\u52b9\u306a\u540d\u79f0\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.file_chooser.rename.error.title = \u540d\u79f0\u5909\u66f4 -gui.dialog.error.file_chooser.rename.error.message = \u30d5\u30a1\u30a4\u30eb\u306e\u540d\u79f0\u5909\u66f4\u6642\u306b\u30a8\u30e9\u30fc - -gui.dialog.confirm.result.really_close.title = \u9589\u3058\u308b -gui.dialog.confirm.result.really_close.message = \u3053\u306e\u30bf\u30d6\u3092\u9589\u3058\u308b\u3068\u7d50\u679c\u304c\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u306b\u8868\u793a\u3055\u308c\u306a\u304f\u306a\u308a\u307e\u3059\u304c\u3001\u9589\u3058\u307e\u3059\u304b\uff1f - -gui.dialog.error.file_chooser.new_folder.rename.title = \u30d5\u30a9\u30eb\u30c0\u4f5c\u6210 -gui.dialog.error.file_chooser.new_folder.rename.message =\u3000\u30d5\u30a9\u30eb\u30c0\u3092{0}\u306b\u540d\u79f0\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.importwizard.filetype_not_supported.title = \u975e\u30b5\u30dd\u30fc\u30c8\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 -gui.dialog.error.importwizard.filetype_not_supported.message = {0}\u578b\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 - -gui.dialog.error.error_in_copy_repository_entry.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u30a8\u30e9\u30fc -gui.dialog.error.error_in_copy_repository_entry.message = \u30ea\u30dd\u30b8\u30c8\u30ea{0}\u306b\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc\uff1a{1} - -gui.dialog.error.error_downloading_metadata.title = \u30e1\u30bf\u30c7\u30fc\u30bf\u306e\u53d6\u5f97\u30a8\u30e9\u30fc -gui.dialog.error.error_downloading_metadata.message = {0}\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u53d6\u5f97\u30a8\u30e9\u30fc\uff1a{1} - -gui.dialog.error.malformed_repository_location.title = \u6574\u5f62\u3055\u308c\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 -gui.dialog.error.malformed_repository_location.message = \u6574\u5f62\u3055\u308c\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3: {0}. - -gui.dialog.example_visualizer_dialog.title = \u4f8b {0} -gui.dialog.example_visualizer_dialog.message = \u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u306fID{0}\u306e\u8a73\u7d30\u60c5\u5831\u3092\u8868\u793a\u3057\u307e\u3059\u3002 -gui.dialog.example_visualizer_dialog.icon = table_selection_row.png - - -############################ -# Main Menu and Toolbar -############################ - -###### FILE MENU ############# - -gui.action.menu.file.label = \u30d5\u30a1\u30a4\u30eb -gui.action.menu.file.mne = \u30d5 -gui.action.menu.file.tip = \u958b\u304f - -gui.action.new.label = \u65b0\u898f -gui.action.new.mne = N -gui.action.new.icon = document_empty_new.png -gui.action.new.tip = \u7a7a\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092\u4f5c\u6210 -gui.action.new.acc = control N - -gui.action.open.label = \u958b\u304f -gui.action.open.mne = O -gui.action.open.icon = folder_open.png -gui.action.open.tip = \u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f -gui.action.open.acc = control O - -gui.action.save.label = \u4fdd\u5b58 -gui.action.save.mne = S -gui.action.save.icon = floppy_disk.png -gui.action.save.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58 -gui.action.save.acc = control S - -gui.action.save_as.label = \u5225\u540d\u4fdd\u5b58 -gui.action.save_as.mne = a -gui.action.save_as.icon = save_as.png -gui.action.save_as.tip = \u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092\u65b0\u898f\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58 -gui.action.import_process.label = \u30a4\u30f3\u30dd\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9 -gui.action.import_process.mne = I -gui.action.import_process.icon = inbox_into.png -gui.action.import_process.tip = \u30d5\u30a1\u30a4\u30eb\u304b\u3089\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.export_process.label = \u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9 -gui.action.export_process.mne = E -gui.action.export_process.icon = inbox_out.png -gui.action.export_process.tip = \u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3092\u30d5\u30a1\u30a4\u30eb\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 - -gui.action.menu.file.import.label = \u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.menu.file.import.mne = I -gui.action.menu.file.import.icon = inbox_into.png -gui.action.menu.file.import.tip = \u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u30c7\u30fc\u30bf\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_database_table.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_database_table.icon = inbox_into.png -gui.action.import_database_table.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_excel_sheet.label = Excel\u30b7\u30fc\u30c8\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_excel_sheet.icon = inbox_into.png -gui.action.import_excel_sheet.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306bExcel\u30d5\u30a1\u30a4\u30eb\u30b7\u30fc\u30c8(*.xls)\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import.label = \u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import.icon = inbox_into.png -gui.action.import.tup = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u30c7\u30fc\u30bf\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_csv_file.label = CSV\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_csv_file.icon = inbox_into.png -gui.action.import_csv_file.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306bCSV\u30d5\u30a1\u30a4\u30eb(.csv)\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_aml_file.label = AML\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_aml_file.icon = inbox_into.png -gui.action.import_aml_file.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306bAML\u30d5\u30a1\u30a4\u30eb(.aml)\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_access_table.label = MS\u30a2\u30af\u30bb\u30b9\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_access_table.icon = inbox_into.png -gui.action.import_access_table.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306bAccess\u30d5\u30a1\u30a4\u30eb(.mdb)\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.import_blob.label = \u30d0\u30a4\u30ca\u30ea\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.import_blob.icon = inbox_into.png -gui.action.import_blob.tip = \u65e2\u5b58\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4e0d\u7279\u5b9a\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 - -gui.action.print_preview.label = \u30d7\u30ec\u30d3\u30e5 -gui.action.print_preview.mne = r -gui.action.print_preview.icon = printer_view.png -gui.action.print_preview.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3082\u3057\u304f\u306f\u7d50\u679c\u306e\u5370\u5237\u30d7\u30ec\u30d3\u30e5\u3092\u8868\u793a\uff08\u95b2\u89a7\u30e2\u30fc\u30c9\u306b\u4f9d\u5b58\uff09 - -gui.action.print.label = {0}\u3092\u5370\u5237 -gui.action.print.mne = P -gui.action.print.icon = printer.png -gui.action.print.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3082\u3057\u304f\u306f\u7d50\u679c\u3092\u5370\u5237\uff08\u95b2\u89a7\u30e2\u30fc\u30c9\u306b\u4f9d\u5b58\uff09 -gui.action.print.acc = control P - -gui.action.page_setup.label = \u30da\u30fc\u30b8\u8a2d\u5b9a -gui.action.page_setup.mne = g -gui.action.page_setup.icon = printer_checkbox_checked.png -gui.action.page_setup.tip = \u30d7\u30ea\u30f3\u30bf\u8a2d\u5b9a\u753b\u9762\u3092\u8868\u793a - -gui.action.export.label = {0}\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 -gui.action.export.mne = E -gui.action.export.icon = inbox_out.png -gui.action.export.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u3082\u3057\u304f\u306f\u7d50\u679c\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8(\u95b2\u89a7\u30e2\u30fc\u30c9\u306b\u4f9d\u5b58) - -gui.action.exit.label = \u7d42\u4e86 -gui.action.exit.mne = x -gui.action.exit.icon = door_exit.png -gui.action.exit.tip = RapidMiner\u3092\u7d42\u4e86 - -gui.action.menu.recent_files.label = \u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\u30eb -gui.action.menu.recent_files.mne = R -gui.action.menu.recent_files.icon = history2.png -gui.action.menu.recent_files.tip = \u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u30ea\u30b9\u30c8 - -###### EDIT MENU ######### - -gui.action.menu.edit.label = \u7de8\u96c6 -gui.action.menu.edit.mne = E -gui.action.menu.edit.tip = \u30d7\u30ed\u30bb\u30b9\u8a2d\u5b9a\u3092\u7de8\u96c6 - -gui.action.undo.label = \u5143\u306b\u623b\u3059 -gui.action.undo.mne = U -gui.action.undo.icon = undo.png -gui.action.undo.tip = \u6700\u5f8c\u306b\u884c\u3063\u305f\u64cd\u4f5c\u307e\u3067\u623b\u308b -gui.action.undo.acc = control Z - -gui.action.redo.label = \u3084\u308a\u76f4\u3059 -gui.action.redo.mne = R -gui.action.redo.icon = redo.png -gui.action.redo.tip = \u6700\u5f8c\u306b\u884c\u3063\u305f\u64cd\u4f5c\u307e\u3067\u3084\u308a\u76f4\u3059 - -gui.action.new_operator.label = \u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf -gui.action.new_operator.mne = N -gui.action.new_operator.icon = element_new.png -gui.action.new_operator.tip = \u30c0\u30a4\u30a2\u30ed\u30b0\u304b\u3089\u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u8ffd\u52a0 -gui.action.new_operator.acc = control I - -gui.action.new_building_block.label = \u65b0\u898f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af -gui.action.new_building_block.mne = B -gui.action.new_building_block.icon = box_open_new.png -gui.action.new_building_block.tip = \u65b0\u898f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u633f\u5165 -gui.action.new_building_block.acc = control B - -gui.action.cut.label = \u5207\u308a\u53d6\u308a -gui.action.cut.mne = t -gui.action.cut.icon = cut.png -gui.action.cut.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u5207\u308a\u53d6\u308a\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u30b3\u30d4\u30fc -gui.action.cut.acc = control X - -gui.action.copy.label = \u30b3\u30d4\u30fc -gui.action.copy.mne = C -gui.action.copy.icon = copy.png -gui.action.copy.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u306b\u30b3\u30d4\u30fc -gui.action.copy.acc = control C - -gui.action.paste.label = \u8cbc\u308a\u4ed8\u3051 -gui.action.paste.mne = P -gui.action.paste.icon = clipboard_paste.png -gui.action.paste.tip = \u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u5185\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u5f35\u308a\u4ed8\u3051 -gui.action.paste.acc = control V - -gui.action.delete.label = \u524a\u9664 -gui.action.delete.mne = D -gui.action.delete.icon = element_delete.png -gui.action.delete.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u524a\u9664 -gui.action.delete.acc = DELETE - -gui.action.operator_info.label = \u30aa\u30da\u30ec\u30fc\u30bf\u60c5\u5831\u8868\u793a -gui.action.operator_info.mne = I -gui.action.operator_info.icon = element_information.png -gui.action.operator_info.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u60c5\u5831\u3092\u8868\u793a -gui.action.operator_info.acc = F1 - -gui.action.save_building_block.label = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3068\u3057\u3066\u4fdd\u5b58 -gui.action.save_building_block.mne = S -gui.action.save_building_block.icon = box_open_add.png -gui.action.save_building_block.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u65b0\u898f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3068\u3057\u3066\u4fdd\u5b58 - -gui.action.menu.wiring.label = \u30aa\u30da\u30ec\u30fc\u30bf\u66f8\u304d\u8fbc\u307f -gui.action.menu.wiring.mne = W -gui.action.menu.wiring.icon = plug.png -gui.action.menu.wiring.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u7d50\u5408 - -gui.action.wiring.label = \u30aa\u30da\u30ec\u30fc\u30bf\u66f8\u304d\u8fbc\u307f -gui.action.wiring.icon = plug.png - -gui.action.wire.label = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u81ea\u52d5\u7d50\u5408 -gui.action.wire.mne = A -gui.action.wire.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30dd\u30fc\u30c8\u3092\u81ea\u52d5\u7d50\u5408\u3057\u904e\u53bb\u306e\u63a5\u7d9a\u3092\u4fdd\u6301 -gui.action.wire.icon = plug.png - -gui.action.wire_recursive.label = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u81ea\u52d5\u7d50\u5408 (\u518d\u5e30) -gui.action.wire_recursive.mne = W -gui.action.wire_recursive.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30dd\u30fc\u30c8\u3092\u518d\u5e30\u7684\u306b\u81ea\u52d5\u7d50\u5408\u3057\u904e\u53bb\u306e\u63a5\u7d9a\u3092\u4fdd\u6301 -gui.action.wire_recursive.icon = plug.png - -gui.action.rewire.label = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u518d\u7d50\u5408 -gui.action.rewire.mne = R -gui.action.rewire.tip = \u7d50\u5408\u89e3\u9664\u306e\u5f8c\u306b\u3001\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30dd\u30fc\u30c8\u3092\u81ea\u52d5\u7d50\u5408 -gui.action.rewire.icon = plug.png - -gui.action.rewire_recursive.label = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u518d\u7d50\u5408 (\u518d\u5e30) -gui.action.rewire_recursive.mne = i -gui.action.rewire_recursive.tip = \u7d50\u5408\u89e3\u9664\u306e\u5f8c\u306b\u3001\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30dd\u30fc\u30c8\u3092\u518d\u5e30\u7684\u306b\u81ea\u52d5\u7d50\u5408 -gui.action.rewire_recursive.icon = plug.png - - -##### RUN MENU ########### - -gui.action.menu.process.label = \u30d7\u30ed\u30bb\u30b9 -gui.action.menu.process.mne = P -gui.action.menu.process.tip = \u30d7\u30ed\u30bb\u30b9\u3092\u5909\u66f4\u3057\u5b9f\u884c - -gui.action.validate.label = \u30d7\u30ed\u30bb\u30b9\u691c\u8a3c -gui.action.validate.mne = V -gui.action.validate.icon = checks.png -gui.action.validate.tip = \u30d7\u30ed\u30bb\u30b9\u306e\u69cb\u9020\u3092\u691c\u8a3c -gui.action.validate.acc = F12 - -gui.action.validate_automatically.label = \u81ea\u52d5\u691c\u8a3c -gui.action.validate_automatically.mne = A -gui.action.validate_automatically.tip = \u30c1\u30a7\u30c3\u30af\u306b\u3088\u308a\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u306e\u66f4\u65b0\u6642\u306b\u81ea\u52d5\u3067\u30d7\u30ed\u30bb\u30b9\u306e\u69cb\u9020\u3092\u691c\u8a3c\u3002\u672a\u9078\u629e\u306b\u3088\u308a\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u81ea\u52d5\u7d50\u5408\u51e6\u7406\u304c\u5931\u6557\u3059\u308b\u3002 -gui.action.validate_automatically.icon = checkbox.png - -gui.action.run.label = \u5b9f\u884c -gui.action.run.icon = media_play.png -gui.action.run.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u5b9f\u884c\u3082\u3057\u304f\u306f\u518d\u958b -gui.action.run.mne = R -gui.action.run.acc = F11 - -gui.action.pause.label = \u4e00\u6642\u505c\u6b62 -gui.action.pause.icon = media_pause.png -gui.action.pause.tip = \u73fe\u5728\u5b9f\u884c\u3057\u3066\u3044\u308b\u30d7\u30ed\u30bb\u30b9\u3092\u4e00\u6642\u505c\u6b62 -gui.action.pause.mne = P -gui.action.pause.acc = F11 - -gui.action.stop.label = \u505c\u6b62 -gui.action.stop.mne = S -gui.action.stop.icon = media_stop.png -gui.action.stop.tip = \u73fe\u5728\u5b9f\u884c\u3057\u3066\u3044\u308b\u30d7\u30ed\u30bb\u30b9\u3092\u505c\u6b62 -gui.action.stop.acc = control pressed F11 - -gui.action.process_debug_mode.label = \u30e1\u30bf\u60c5\u5831\u3068\u5b9f\u30c7\u30fc\u30bf\u9593\u306e\u540c\u671f\u51e6\u7406 -gui.action.process_debug_mode.icon = link.png -gui.action.process_debug_mode.mne = S -gui.action.process_debug_mode.tip = \u30c1\u30a7\u30c3\u30af\u3059\u308b\u4e8b\u306b\u3088\u308a\u3001\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30dd\u30fc\u30c8\u306b\u3066\u4fdd\u6301\u3055\u308c\u3066\u3044\u308b\u30e1\u30bf\u60c5\u5831\u3092\u5b9f\u30c7\u30fc\u30bf\u306b\u3088\u308a\u66f4\u65b0 - -gui.action.run_remote.label = \u30ea\u30e2\u30fc\u30c8\u3067\u5b9f\u884c -gui.action.run_remote.mne = t -#gui.action.run_remote.icon = server2_play.png -gui.action.run_remote.tip = \u30ea\u30e2\u30fc\u30c8\u30b5\u30fc\u30d0\u306b\u3066\u30d7\u30ed\u30bb\u30b9\u3092\u5b9f\u884c -gui.action.run_remote.acc = alt pressed F11 - - -###### Tools - -gui.action.menu.tools.label = \u30c4\u30fc\u30eb -gui.action.menu.tools.mne = T -gui.action.menu.tools.tip = \u6c4e\u7528\u6a5f\u80fd - -gui.action.manage_building_blocks.label = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u7ba1\u7406 -gui.action.manage_building_blocks.mne = B -gui.action.manage_building_blocks.icon = box_open_edit.png -gui.action.manage_building_blocks.tip = \u4fdd\u5b58\u3057\u305f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u7ba1\u7406 - -gui.action.preferences.label = \u8a2d\u5b9a -gui.action.preferences.mne = P -gui.action.preferences.icon = clipboard_check_edit.png -gui.action.preferences.tip = RapidMiner\u306e\u7de8\u96c6\u53ef\u80fd\u306a\u8a2d\u5b9a\u9805\u76ee\u3092\u8868\u793a\u3059\u308b\u30c0\u30a4\u30a2\u30ed\u30b0\u8868\u793a - -gui.action.attribute_editor.label = \u5c5e\u6027\u30a8\u30c7\u30a3\u30bf -gui.action.attribute_editor.mne = A -gui.action.attribute_editor.icon = table_new.png -gui.action.attribute_editor.tip = XML\u30e1\u30bf\u30c7\u30fc\u30bf\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb(.aml)\u3092\u751f\u6210\u3059\u308b\u5c5e\u6027\u30a8\u30c7\u30a3\u30bf\u3092\u958b\u59cb - -gui.action.anova.label = ANOVA\u8a08\u7b97 -gui.action.anova.mne = C -gui.action.anova.icon = scales.png -gui.action.anova.tip = ANOVA\u8a08\u7b97\u6a5f\u3092\u958b\u59cb - -gui.action.check_for_updates.label = \u66f4\u65b0\u3092\u78ba\u8a8d -gui.action.check_for_updates.mne = U -gui.action.check_for_updates.icon = download.png -gui.action.check_for_updates.tip = RapidMiner\u306e\u66f4\u65b0\u3092\u78ba\u8a8d - -gui.action.show_database_drivers.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c9\u30e9\u30a4\u30d0\u8868\u793a -gui.action.show_database_drivers.mne = D -#gui.action.show_database_drivers.icon = data_network.png -gui.action.show_database_drivers.tip = RapidMiner\u306b\u3066\u5229\u7528\u53ef\u80fd\u306aJDBC\u30c9\u30e9\u30a4\u30d0\u30ea\u30b9\u30c8\u3092\u8868\u793a - -gui.action.manage_db_connections.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u7ba1\u7406 -gui.action.manage_db_connections.mne = C -#gui.action.manage_db_connections.icon = data_network_edit.png -gui.action.manage_db_connections.tip = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u4f5c\u6210\u3001\u7de8\u96c6 - -gui.action.attribute_wizard.label = \u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u30a6\u30a3\u30b6\u30fc\u30c9 -gui.action.attribute_wizard.mne = A -gui.action.attribute_wizard.icon = magic_wand.png -gui.action.attribute_wizard.tip = \u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb(.aml)\u4f5c\u6210\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a - -gui.action.wizard.data_import_wizard.label = \u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.action.wizard.data_import_wizard.icon = magic_wand.png -gui.action.wizard.data_import_wizard.tip = \u30a4\u30f3\u30dd\u30fc\u30c8\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u8aad\u307f\u8fbc\u307f\u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u958b\u59cb - -gui.action.wizard.validate_value_types.label = \u30c7\u30fc\u30bf\u30ea\u30ed\u30fc\u30c9 -gui.action.wizard.validate_value_types.mne = R -gui.action.wizard.validate_value_types.icon = refresh.png -gui.action.wizard.validate_value_types.tip = \u30c7\u30fc\u30bf\u306e\u30ea\u30ed\u30fc\u30c9\u304a\u3088\u3073\u5b9a\u7fa9\u3057\u3066\u3044\u306a\u3044\u5024\u30bf\u30a4\u30d7\u306e\u30bb\u30eb\u3092\u691c\u7d22 - -gui.action.wizard.abort_validate_value_types.label = \u30ea\u30ed\u30fc\u30c9\u30ad\u30e3\u30f3\u30bb\u30eb -gui.action.wizard.abort_validate_value_types.mne = r -gui.action.wizard.abort_validate_value_types.icon = media_stop.png -gui.action.wizard.abort_validate_value_types.tip = \u30ea\u30ed\u30fc\u30c9\u3092\u505c\u6b62 - -gui.action.wizard.guess_value_types.label = \u5024\u578b\u3092\u63a8\u6e2c -gui.action.wizard.guess_value_types.mne = G -gui.action.wizard.guess_value_types.icon = question_and_answer.png -gui.action.wizard.guess_value_types.tip = \u30c7\u30fc\u30bf\u30ea\u30ed\u30fc\u30c9\u304a\u3088\u3073\u5404\u5c5e\u6027\u306e\u5024\u578b\u3092\u63a8\u6e2c - -gui.action.wizard.abort_guess_value_types.label = \u63a8\u6e2c\u3092\u30ad\u30e3\u30f3\u30bb\u30eb -gui.action.wizard.abort_guess_value_types.mne = g -gui.action.wizard.abort_guess_value_types.icon = media_stop.png -gui.action.wizard.abort_guess_value_types.tip = \u5024\u578b\u63a8\u6e2c\u3092\u505c\u6b62 - -gui.action.wizard.show_error_rows.label = \u30a8\u30e9\u30fc\u306e\u307f\u8868\u793a -gui.action.wizard.show_error_rows.mne = e -gui.action.wizard.show_error_rows.icon = table_selection_row_delete.png -gui.action.wizard.show_error_rows.tip = \u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc\u3092\u542b\u3080\u884c\u306e\u307f\u3092\u8868\u793a - -gui.action.wizard.abort_show_error_rows.label = \u30a8\u30e9\u30fc\u30d5\u30a3\u30eb\u30bf\u3092\u30ad\u30e3\u30f3\u30bb\u30eb -gui.action.wizard.abort_show_error_rows.icon = delete.png -gui.action.wizard.abort_show_error_rows.tip = \u30a8\u30e9\u30fc\u884c\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3092\u505c\u6b62 - -gui.action.wizard.error_tolerant.label = \u30a8\u30e9\u30fc\u3092\u7121\u8996 -gui.action.wizard.error_tolerant.mne = I -gui.action.wizard.error_tolerant.tip = \u30c1\u30a7\u30c3\u30af\u3059\u308b\u4e8b\u306b\u3088\u308a\u30a8\u30e9\u30fc\u3092\u7121\u8996 - -gui.action.show_usage_statistics.label = \u4f7f\u7528\u7d71\u8a08\u3092\u8868\u793a -gui.action.show_usage_statistics.icon = chart_column.png -gui.action.show_usage_statistics.mne = U -gui.action.show_usage_statistics.tip = \u5404\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u4f7f\u7528\u7d71\u8a08\u3092\u8868\u793a - -gui.label.date_format.label = \u65e5\u4ed8\u30d5\u30a9\u30fc\u30de\u30c3\u30c8 -gui.label.date_format.mne = D -gui.label.date_format.tip = \u65e5\u4ed8\u89e3\u6790\u306b\u4f7f\u7528\u3059\u308b\u30d1\u30bf\u30fc\u30f3\u3092\u5b9a\u7fa9 -#################################################### -# ManageDatabaseDriversDialog -#################################################### -gui.dialog.manage_database_drivers.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c9\u30e9\u30a4\u30d0\u30fc\u7ba1\u7406 -gui.dialog.manage_database_drivers.message = \u65b0\u898f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c9\u30e9\u30a4\u30d0\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u884c\u3046\u70ba\u306bjar\u30d5\u30a1\u30a4\u30eb\u306e\u9078\u629e\u304a\u3088\u3073\u4f7f\u7528\u3059\u308b\u30c9\u30e9\u30a4\u30d0\u30af\u30e9\u30b9\u3092\u6307\u5b9a\ -JDBC\u30c9\u30e9\u30a4\u30d0\u306e\u7a2e\u985e\u306b\u3088\u3063\u3066\u306f\u3001\u8907\u6570\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u3088\u3063\u3066\u69cb\u6210\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u304c\u3042\u308b\u3002\u4f8b\uff1a\u4e00\u3064\u306e\u30c9\u30e9\u30a4\u30d0\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3057\u4e00\u3064\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30d5\u30a1\u30a4\u30eb\ -\u3053\u306e\u5834\u5408\u8907\u6570\u306ejar\u30d5\u30a1\u30a4\u30eb\u306f\u30ab\u30f3\u30de\u306b\u3088\u308a\u533a\u5207\u308a\u5b9a\u7fa9\u3059\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002\u8907\u6570\u306e\u30c9\u30e9\u30a4\u30d0\u30af\u30e9\u30b9\u3092\u5b9a\u7fa9\u3059\u308b\u5834\u5408\u3082\u30ab\u30f3\u30de\u533a\u5207\u308a\u306b\u3088\u3063\u3066\u5b9a\u7fa9\u3057\u307e\u3059\u3002\ -\u7de8\u96c6\u5f8c\u306fRapidMiner\u306e\u518d\u8d77\u52d5\u3092\u884c\u3044\u307e\u3059\u3002 -#gui.dialog.manage_database_drivers.icon = data_network_edit.png -gui.label.manage_database_drivers.name.label = \u540d\u79f0 -gui.label.manage_database_drivers.name.mne = N -gui.label.manage_database_drivers.urlprefix.label = URL prefix -gui.label.manage_database_drivers.urlprefix.mne = U -gui.label.manage_database_drivers.port.label = \u30dd\u30fc\u30c8\u63a5\u982d\u8f9e -gui.label.manage_database_drivers.port.mne = P -gui.label.manage_database_drivers.jarfile.label = Jar\u30d5\u30a1\u30a4\u30eb -gui.label.manage_database_drivers.jarfile.mne = J -gui.label.manage_database_drivers.classname.label = \u30c9\u30e9\u30a4\u30d0\u30fc\u30af\u30e9\u30b9 -gui.label.manage_database_drivers.classname.mne = D -gui.action.manage_database_drivers.jarfile.label = -gui.label.manage_database_drivers.dbseparator.label = \u30b9\u30ad\u30fc\u30de\u30bb\u30d1\u30ec\u30fc\u30bf -gui.label.manage_database_drivers.dbseparator.mne = s - -gui.action.manage_database_drivers.jarfile.icon = folder_open.png -gui.action.manage_database_drivers.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c9\u30e9\u30a4\u30d0\u7ba1\u7406 -#gui.action.manage_database_drivers.icon = data_network_edit.png -gui.action.manage_database_drivers.tip = JDBC\u30c9\u30e9\u30a4\u30d0\u306e\u65b0\u898f\u8ffd\u52a0\u3082\u3057\u304f\u306f\u7de8\u96c6 -gui.action.manage_database_drivers.mne = s - -gui.action.manage_database_drivers.add.label = \u8ffd\u52a0 -gui.action.manage_database_drivers.add.mne = A -gui.action.manage_database_drivers.add.tip = \u65b0\u898f\u30c9\u30e9\u30a4\u30d0\u3092\u8ffd\u52a0 -gui.action.manage_database_drivers.add.icon = data_connection_new.png - -gui.action.manage_database_drivers.delete.label = \u524a\u9664 -gui.action.manage_database_drivers.delete.mne = D -gui.action.manage_database_drivers.delete.tip = \u9078\u629e\u3057\u305f\u30c9\u30e9\u30a4\u30d0\u3092\u524a\u9664 -gui.action.manage_database_drivers.delete.icon = data_network_delete.png - -gui.action.manage_database_drivers.save.label = \u4fdd\u5b58 -gui.action.manage_database_drivers.save.mne = S -gui.action.manage_database_drivers.save.tip = \u30c9\u30e9\u30a4\u30d0\u306e\u7de8\u96c6\u5185\u5bb9\u3092\u4fdd\u5b58 -gui.action.manage_database_drivers.save.icon = floppy_disk.png - -gui.dialog.error.manage_database_drivers.error_saving.title = JDBC\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u4fdd\u5b58\u5931\u6557 -gui.dialog.error.manage_database_drivers.error_saving.message = JDBC\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u4fdd\u5b58\u5931\u6557: {0} - -gui.dialog.confirm.manage_database_drivers.restart.title = \u518d\u8d77\u52d5 -gui.dialog.confirm.manage_database_drivers.restart.message = \u5909\u66f4\u306e\u9069\u5fdc\u3092\u884c\u3046\u70ba\u306bRapidMiner\u306e\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b? - -###### VIEW ################ - -gui.action.menu.view.label = \u95b2\u89a7 -gui.action.menu.view.mne = V -gui.action.menu.view.tip = UI\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba - -gui.action.menu.perspectives.label = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6 -gui.action.menu.perspectives.icon = windows.png -gui.action.menu.perspectives.mne = P -gui.action.menu.perspectives.tip = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u3092\u9078\u629e - -gui.action.new_perspective.label = \u65b0\u898f\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6 -gui.action.new_perspective.icon = window_new.png -gui.action.new_perspective.mne = N -gui.action.new_perspective.tip = \u65b0\u898f\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u3092\u4f5c\u6210 - -gui.action.restore_predefined_perspective_default.label = \u30c7\u30d5\u30a9\u30eb\u30c8\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u306b\u623b\u3059 -gui.action.restore_predefined_perspective_default.mne = R -gui.action.restore_predefined_perspective_default.icon = window_ok.png -gui.action.restore_predefined_perspective_default.message = \u73fe\u5728\u306e\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u306b\u623b\u3059 - -gui.dialog.input.new_perspective.title = \u65b0\u898f\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6 -gui.dialog.input.new_perspective.icon = window_new.png -gui.dialog.input.new_perspective.message = \u65b0\u898f\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u306b\u540d\u524d\u3092\u4ed8\u3051\u308b - -gui.action.delete_perspective.label = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u524a\u9664 -gui.action.delete_perspective.mne = D -gui.action.delete_perspective.icon = window_delete.png -gui.action.delete_perspective.tip = \u3053\u306e\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u3092\u524a\u9664 - -gui.action.menu.show_view.label = \u30d3\u30e5\u30fc\u8868\u793a -gui.action.menu.show_view.icon = window_view.png -gui.action.menu.show_view.mne = S -gui.action.menu.show_view.tip = UI\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u30aa\u30f3\u30aa\u30d5\u5207\u308a\u66ff\u3048 - -gui.action.expert.label = \u30a8\u30ad\u30b9\u30d1\u30fc\u30c8\u30e2\u30fc\u30c9 -gui.action.expert.mne = E -gui.action.expert.icon = graduate.png -gui.action.expert.tip = \u30a8\u30ad\u30b9\u30d1\u30fc\u30c8\u30e2\u30fc\u30c9\u306b\u5207\u308a\u66ff\u3048 (\u5229\u7528\u53ef\u80fd\u306a\u5168\u3066\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u78ba\u8a8d\u53ef\u80fd) -gui.action.expert.acc = F4 - -gui.action.beginner.label = \u521d\u5fc3\u8005\u30e2\u30fc\u30c9 -gui.action.beginner.mne = B -gui.action.beginner.icon = user.png -gui.action.beginner.tip = \u521d\u5fc3\u8005\u30e2\u30fc\u30c9\u306b\u5207\u308a\u66ff\u3048 (\u91cd\u8981\u306a\u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u307f\u8868\u793a) -gui.action.beginner.acc = F4 - -gui.action.result_history.label = \u7d50\u679c\u5c65\u6b74 -gui.action.result_history.mne = H -gui.action.result_history.icon = history.png -gui.action.result_history.tip = \u30bb\u30c3\u30b7\u30e7\u30f3\u306b\u3066\u751f\u6210\u3055\u308c\u305f\u5168\u7d50\u679c\u3092\u542b\u3080\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u8868\u793a - -gui.action.edit_view.label = \u30d3\u30e5\u30fc\u7de8\u96c6 -gui.action.edit_view.mne = V -gui.action.edit_view.tip = \u8868\u793a\u30d3\u30e5\u30fc\u3092\u9078\u629e/\u975e\u9078\u629e - -############## HELP ################# - -gui.action.menu.help.label = \u30d8\u30eb\u30d7 -gui.action.menu.help.mne = H -gui.action.menu.help.tip = RapidMiner\u306e\u4f7f\u7528\u65b9\u6cd5\u306b\u3064\u3044\u3066\u306e\u30d8\u30eb\u30d7 - -gui.action.tutorial.label = RapidMiner\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb -gui.action.tutorial.mne = T -gui.action.tutorial.icon = book.png -gui.action.tutorial.tip = RapidMiner\u30aa\u30f3\u30e9\u30a4\u30f3\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3092\u958b\u59cb - -gui.action.about.label = RapidMiner\u306b\u3064\u3044\u3066 -gui.action.about.mne = A -gui.action.about.icon = about.png -gui.action.about.tip = RapidMiner\u306b\u3064\u3044\u3066\u306e\u60c5\u5831\u3092\u8868\u793a - -#gui.action.gui_manual.label = RapidMiner GUI Manual... -#gui.action.gui_manual.mne = G -#gui.action.gui_manual.icon = question.png -#gui.action.gui_manual.tip = Browse the RapidMiner GUI Manual. - -gui.action.help_support.label = \u30b5\u30dd\u30fc\u30c8 -gui.action.help_support.mne = S -gui.action.help_support.icon = lifebelt.png -gui.action.help_support.tip = RapidMiner\u306e\u5546\u7528\u30b5\u30dd\u30fc\u30c8\u306b\u3064\u3044\u3066 - -gui.action.help_videotutorials.label = \u30d3\u30c7\u30aa\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb -gui.action.help_videotutorials.mne = V -gui.action.help_videotutorials.icon = movie.png -gui.action.help_videotutorials.tip = Web\u4e0a\u3067RapidMiner\u30d3\u30c7\u30aa\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3092\u8996\u8074 - -gui.action.help_forum.label = \u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u30d5\u30a9\u30fc\u30e9\u30e0 -gui.action.help_forum.mne = F -gui.action.help_forum.icon = question_and_answer.png -gui.action.help_forum.tip = RapidMiner\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u30d5\u30a9\u30fc\u30e9\u30e0\u3092\u8a2a\u554f\u3057\u3066RapidMiner\u304a\u3088\u3073\u30c7\u30fc\u30bf\u30de\u30a4\u30cb\u30f3\u30b0\u306b\u95a2\u3059\u308b\u4e00\u822c\u7684\u306a\u8cea\u554f\u3001\u30c7\u30a3\u30b9\u30ab\u30c3\u30b7\u30e7\u30f3\u3092\u884c\u3048\u307e\u3059\u3002 - -gui.action.about_extension.label = {0}\u62e1\u5f35\u6a5f\u80fd\u306b\u3064\u3044\u3066 -gui.action.about_extension.icon = piece2.png -gui.action.about_extension.tip = {0}\u62e1\u5f35\u6a5f\u80fd\u306e\u60c5\u5831\u3092\u8868\u793a - -######################################## -# ExtendedJTable -######################################## -gui.action.menu.move_column_menu.label = \u30ab\u30e9\u30e0\u3092\u79fb\u52d5 -gui.action.menu.move_column_menu.icon = table_refresh.png -gui.action.menu.move_column_menu.mne = c -gui.action.menu.move_column_menu.tip = \u5217\u3092\u4ed6\u306e\u4f4d\u7f6e\u3078\u79fb\u52d5 -gui.action.move_column.label = \u5217\u3092{0}\u306e\u4f4d\u7f6e\u3078\u79fb\u52d5 -gui.action.move_column.tip = \u9078\u629e\u3057\u305f\u5217\u3092\u4ed6\u306e\u4f4d\u7f6e\u3078\u79fb\u52d5 - -######################################## -# OPERATOR CONTEXT MENU -######################################## - -gui.action.enable_operator.label = \u30aa\u30da\u30ec\u30fc\u30bf\u6709\u52b9\u5316 -gui.action.enable_operator.tip = \u5b9f\u884c\u3059\u308b\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u9078\u629e -gui.action.enable_operator.mne = E -gui.action.enable_operator.acc = control E -gui.action.enable_operator.icon = element_ok.png - -gui.action.enable_operator_multiple.label = {0}\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u6709\u52b9\u5316 -gui.action.enable_operator_multiple.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u6709\u52b9\u5316 -gui.action.enable_operator_multiple.mne = E -gui.action.enable_operator_multiple.icon = element_ok.png - -gui.action.disable_operator_multiple.label = {0}\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u7121\u52b9\u5316 -gui.action.disable_operator_multiple.tip = \u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u7121\u52b9\u5316 -gui.action.disable_operator_multiple.mne = e -gui.action.disable_operator_multiple.icon = element_ok.png - - -gui.action.make_dirty.label = \u30c0\u30fc\u30c6\u30a3\u30d5\u30e9\u30c3\u30b0 -gui.action.make_dirty.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u30c0\u30fc\u30c6\u30a3\u30d5\u30e9\u30c3\u30b0\u3092\u8a2d\u5b9a\u3002\u5229\u7528\u4f8b\uff1a\u518d\u5b9f\u884c\u3092\u884c\u3046\u30aa\u30da\u30ec\u30fc\u30bf\u7b49 -gui.action.make_dirty.mne = D -gui.action.make_dirty.icon = checkbox_unchecked.png - -gui.action.breakpoint_before.label = \u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\uff08\u524d\uff09 -gui.action.breakpoint_before.icon = breakpoint_up.png -gui.action.breakpoint_before.tip = \u73fe\u5728\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u524d\u306b\u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\u3092\u633f\u5165 - -gui.action.breakpoint_after.label = \u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\uff08\u5f8c\uff09 -gui.action.breakpoint_after.icon = breakpoint_down.png -gui.action.breakpoint_after.tip = \u73fe\u5728\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5f8c\u306b\u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\u3092\u633f\u5165 -gui.action.breakpoint_after.acc = F7 - -gui.action.breakpoint_within.label = \u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\uff08\u7bc4\u56f2\u5185\uff09 -gui.action.breakpoint_within.icon = breakpoint.png -gui.action.breakpoint_within.tip = \u73fe\u5728\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u5185\u306b\u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\u3092\u633f\u5165 - -#gui.action.add_breakpoints.label = Add breakpoints (debug mode on) -#gui.action.add_breakpoints.mne = d -#gui.action.add_breakpoints.icon = bug_ok.png -#gui.action.add_breakpoints.tip = Adds a breakpoint after each operator (debug mode on). -# -#gui.action.remove_breakpoints.label = Remove breakpoints (debug mode off) -#gui.action.remove_breakpoints.mne = R -#gui.action.remove_breakpoints.icon = bug_error.png -#gui.action.remove_breakpoints.tip = Removes all breakpoints (debug mode off) - -gui.action.toggle_all_breakpoints.label = \u5168\u3066\u306e\u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8 (\u30c7\u30d0\u30c3\u30b0\u30e2\u30fc\u30c9) -gui.action.toggle_all_breakpoints.mne = D -gui.action.toggle_all_breakpoints.icon = bug_stop.png -gui.action.toogle_all_breakpoints.tip = \u5404\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5f8c\u306b\u30d6\u30ec\u30fc\u30af\u30dd\u30a4\u30f3\u30c8\u3092\u8ffd\u52a0 - -################################################################################################ -# Other general actions -################################################################################################ -gui.action.store_in_repository.label = {0}\u3092\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4fdd\u5b58 -gui.action.store_in_repository.icon = data_floppy_disk.png -gui.action.store_in_repository.mne = S -gui.action.store_in_repository.tip = \u7d50\u679c\u3092\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4fdd\u5b58 - -gui.action.export_and_print.label = \u30a8\u30af\u30b9\u30dd\u30fc\u30c8/\u5370\u5237 -gui.action.export_and_print.mne = x -gui.action.export_and_print.tip = \u7d50\u679c\u3092\u5370\u5237\u3082\u3057\u304f\u306f\u30d5\u30a1\u30a4\u30eb\u3078\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 -gui.action.export_and_print.icon = inbox_out.png - -################################################################################################ -# COMPONENTS -################################################################################################ - -gui.action.open_file.label = \u958b\u304f -gui.action.open_file.icon = folder_open.png -gui.action.open_file.tip = \u9078\u629e\u5bfe\u8c61\u3092\u958b\u304f - -gui.action.save_file.label = \u4fdd\u5b58 -gui.action.save_file.icon = flopfloppy_disk -gui.action.save_file.tip = \u9078\u629e\u5bfe\u8c61\u3092\u4fdd\u5b58\u3059\u308b\u3002 - -#OperatorPropertyPanel -gui.label.compatibility_level.label = \u4e92\u63db\u6027\u30ec\u30d9\u30eb -gui.label.compatibility_level.mne = l -gui.label.compatibility_level.tip = \u4e92\u63db\u6027\u30ec\u30d9\u30eb\u3092\u6307\u5b9a\u3057RapidMiner\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u304a\u3088\u3073\u62e1\u5f35\u6a5f\u80fd\u3092\u7591\u4f3c\u5b9f\u884c\u3059\u308b\u304b\u3092\u6307\u5b9a\u3002\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u632f\u308b\u821e\u3044\u304c\u5909\u66f4\u3055\u308c\u305f\u5834\u5408\u3001\u904e\u53bb\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u623b\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002 - -# XMLEditor -gui.action.xml_editor.apply_changes.label = \u5909\u66f4\u3092\u9069\u5fdc -gui.action.xml_editor.apply_changes.mne = A -gui.action.xml_editor.apply_changes.tip = XML\u30b3\u30fc\u30c9\u306b\u5bfe\u3059\u308b\u5168\u3066\u306e\u5909\u66f4\u5185\u5bb9\u3092\u9069\u5fdc -gui.action.xml_editor.apply_changes.icon = check.png - -gui.action.editor.delete.label = \u524a\u9664 -gui.action.editor.delete.icon = document_text_delete.png -gui.action.editor.delete.acc = DELETE -gui.action.editor.delete.tip = \u9078\u629e\u5185\u5bb9\u3092\u524a\u9664 - -gui.action.editor.cut.label = \u5207\u308a\u53d6\u308a -gui.action.editor.cut.acc = control X -gui.action.editor.cut.icon = cut.png -gui.action.editor.cut.tip = \u9078\u629e\u5185\u5bb9\u3092\u5207\u308a\u53d6\u308a\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u79fb\u52d5 - -gui.action.editor.copy.label = \u30b3\u30d4\u30fc -gui.action.editor.copy.acc = control C -gui.action.editor.copy.icon = copy.png -gui.action.editor.copy.tip = \u9078\u629e\u5185\u5bb9\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc - -gui.action.editor.paste.label = \u8cbc\u308a\u4ed8\u3051 -gui.action.editor.paste.acc = control V -gui.action.editor.paste.icon = clipboard_paste.png -gui.action.editor.paste.tip = \u5185\u5bb9\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u304b\u3089\u8cbc\u308a\u4ed8\u3051 - -gui.action.editor.select_all.label = \u5168\u3066\u9078\u629e -gui.action.editor.select_all.acc = control A -gui.action.editor.select_all.icon = documents_preferences.png -gui.action.editor.select_all.tip = \u5168\u3066\u306e\u5185\u5bb9\u3092\u9078\u629e - -gui.action.editor.search_replace.label = \u691c\u7d22\u7f6e\u63db -gui.action.editor.search_replace.icon = binocular.png -gui.action.editor.search_replace.acc = control F -gui.action.editor.search_replace.tip = \u6587\u7ae0\u3092\u691c\u7d22\u3057\u6587\u5b57\u5217\u3092\u7f6e\u63db - -# Error table -gui.errortable.header.message.label = \u30e1\u30c3\u30bb\u30fc\u30b8 -gui.errortable.header.fixes.label = \u4fee\u6b63 -gui.errortable.header.location.label = \u4f4d\u7f6e -gui.errortable.header.message.tip = \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8 -gui.errortable.header.fixes.tip = \u3053\u306e\u30a8\u30e9\u30fc\u306b\u5bfe\u3059\u308b\u5229\u7528\u53ef\u80fd\u306a\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u306f\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u306b\u3088\u308a\u9069\u5fdc\u53ef\u80fd\u3067\u3059\u3002 -gui.errortable.header.location.tip = \u30a8\u30e9\u30fc\u306e\u767a\u751f\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u304a\u3088\u3073\u30dd\u30fc\u30c8 - -gui.action.error_table_only_current.label = \u9078\u629e\u30aa\u30da\u30ec\u30fc\u30bf\u306b\u3088\u308b\u30d5\u30a3\u30eb\u30bf -gui.action.error_table_only_current.tip = \u30c1\u30a7\u30c3\u30af\u3059\u308b\u4e8b\u306b\u3088\u308a\u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u305f\u5834\u5408\u306e\u307f\u30a8\u30e9\u30fc\u3092\u8868\u793a -gui.action.error_table_only_current.icon = funnel_checkbox_checked.png -gui.action.error_table_only_current.mne = O - -gui.errortable.no_quickfix_available.label = \u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u5229\u7528\u4e0d\u53ef -gui.errortable.no_quickfix_available.icon = question.png -gui.errortable.no_quickfix_available.tip = \u3053\u306e\u30a8\u30e9\u30fc\u306b\u5bfe\u3059\u308b\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 - -gui.errortable.choose_quickfix.label = \u5229\u7528\u53ef\u80fd\u306a{0}\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u304b\u3089\u9078\u629e -gui.errortable.choose_quickfix.icon = first_aid.png -gui.errortable.choose_quickfix.tip = \u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u958b\u3044\u3066\u3053\u306e\u30a8\u30e9\u30fc\u306b\u5bfe\u3059\u308b\u5229\u7528\u53ef\u80fd\u306a\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u9078\u629e - -gui.action.menu.quick_fixes.label = \u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9 -gui.action.menu.quick_fixes.mne = Q -gui.action.menu.quick_fixes.tip = \u30d7\u30ed\u30bb\u30b9\u8a2d\u5b9a\u306e\u554f\u984c\u306b\u5bfe\u3059\u308b\u89e3\u7b54\u3092\u8868\u793a -gui.action.menu.quick_fixes.icon = first_aid.png - -gui.action.quickfix.connect_to.icon = plug.png -gui.action.quickfix.reconnect_to.icon = plug.png -gui.action.quickfix.add_compatible.icon = element_new.png -gui.action.quickfix.disconnect.icon = plug_delete.png -gui.action.quickfix.insert_id_tagging.icon = table_selection_column_add.png -gui.action.quickfix.insert_model_applier.icon = lightbulb_on.png -gui.action.quickfix.insert_discretization.icon = objects_transform.png -gui.action.quickfix.insert_missing_value_replenishment.icon = table_new.png -gui.action.quickfix.insert_nominal_to_numerical_label.icon = objects_transform.png -gui.action.quickfix.insert_nominal_to_binominal_label.icon = objects_transform.png -gui.action.quickfix.insert_nominal_to_numerical_attributes.icon = objects_transform.png -gui.action.quickfix.set_parameter.icon = form_edit.png -gui.action.quickfix.set_parameters_using_wizard.icon = form_edit.png -gui.action.quickfix.set_parameter_list.icon = form_edit.png -gui.action.quickfix.correct_parameter_settings_by.icon = form_edit.png -gui.action.quickfix.correct_parameter_settings_list.icon = form_edit.png -gui.action.quickfix.correct_parameter_settings_boolean_enable.icon = form_edit.png -gui.action.quickfix.correct_parameter_settings_boolean_disable.icon = form_edit.png -gui.action.quickfix.correct_parameter_settings_with_wizard.icon = form_edit.png -gui.action.quickfix.replace_by_dictionary.icon = form_edit.png -gui.action.quickfix.change_attribute_role.icon = form_edit.png -gui.action.quickfix.insert_binominal_to_multiclass_learner.icon = lightbulb_off.png -gui.action.quickfix.insert_classification_by_regression_learner.icon = lightbulb_off.png - -gui.dialog.input.quickfix.replace_by_dictionary.title = \u5024\u9078\u629e -gui.dialog.input.quickfix.replace_by_dictionary.icon = form_edit.png -gui.dialog.input.quickfix.replace_by_dictionary.message = {0} - -gui.dialog.set_parameter.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u8a2d\u5b9a: {0} -gui.dialog.set_parameter.icon = form_edit.png - -gui.dialog.input.cannot_connect.title = \u63a5\u7d9a\u4e0d\u53ef -gui.dialog.input.cannot_connect.icon = plug.png -gui.dialog.input.cannot_connect.message = {0}\u3092{1}\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002: {2}\u3002\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.input.cannot_connect.reason.both_connected = \u3069\u3061\u3089\u306e\u30dd\u30fc\u30c8\u3082\u63a5\u7d9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002 -gui.dialog.input.cannot_connect.reason.source_connected = \u63a5\u7d9a\u5143\u30dd\u30fc\u30c8\u306f\u65e2\u306b{0}\u306b\u63a5\u7d9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002 -gui.dialog.input.cannot_connect.reason.dest_connected = \u63a5\u7d9a\u5148\u30dd\u30fc\u30c8\u306f\u65e2\u306b{0}\u306b\u63a5\u7d9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002 -gui.dialog.input.cannot_connect.option.disconnect_connect = \u30dd\u30fc\u30c8\u3092\u63a5\u7d9a\u89e3\u9664\u304a\u3088\u3073\u518d\u5ea6\u63a5\u7d9a -gui.dialog.input.cannot_connect.option.insert_multiplier =\u3000IO\u4e57\u6570\u3092\u633f\u5165\u3057\u307e\u3059\u3002 -gui.dialog.input.cannot_connect.option.dont_connect = \u30dd\u30fc\u30c8\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 - -# Message viewer -gui.action.clear_message_viewer.label = \u30e1\u30c3\u30bb\u30fc\u30b8\u30d3\u30e5\u30fc\u30ef\u3092\u6d88\u53bb -gui.action.clear_message_viewer.mne = M -gui.action.clear_message_viewer.icon = erase.png -gui.action.clear_message_viewer.tip = \u30e1\u30c3\u30bb\u30fc\u30b8\u30d3\u30e5\u30fc\u30ef\u5185\u306e\u5168\u3066\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u6d88\u53bb - -gui.action.save_log_file.label = \u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u4fdd\u5b58 -gui.action.save_log_file.mne = S -gui.action.save_log_file.icon = floppy_disk.png -gui.action.save_log_file.tip = \u51fa\u529b\u30ed\u30b0\u3092\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58 - -gui.action.menu.log_level.label = \u30ed\u30b0\u30ec\u30d9\u30eb\u8a2d\u5b9a -gui.action.menu.log_level.mne = l -gui.action.menu.log_level.tip = \u30ed\u30b0\u306e\u51fa\u529b\u30ec\u30d9\u30eb\u3092\u8a2d\u5b9a - -gui.action.search_log.label = \u30ed\u30b0\u30e1\u30c3\u30bb\u30fc\u30b8\u691c\u7d22 -gui.action.search_log.mne = S -gui.action.search_log.icon = binocular.png -gui.action.search_log.tip = \u30ed\u30b0\u51fa\u529b\u5185\u5bb9\u304b\u3089\u6587\u7ae0\u3092\u691c\u7d22 -gui.action.search_log.acc = control F - -gui.action.start_search.label = \u691c\u7d22 -gui.action.start_search.mne = S -gui.action.start_search.icon = binocular.png -gui.action.start_search.tip = \u691c\u7d22 - -gui.action.start_replace.label = \u7f6e\u63db/\u691c\u7d22 -gui.action.start_replace.mne = R -gui.action.start_replace.icon = replace.png -gui.action.start_replace.tip = \u691c\u7d22\u304a\u3088\u3073\u7f6e\u63db - -gui.label.search_what.label = \u691c\u7d22 -gui.label.search_what.tip = \u691c\u7d22\u5358\u8a9e\u3092\u5165\u529b - -gui.label.replace_with.label = \u7f6e\u63db -gui.label.replace_with.tip = \u7f6e\u63db\u6587\u5b57\u5217\u3092\u5165\u529b - -gui.action.case_sensitive.label = \u5927\u6587\u5b57/\u5c0f\u6587\u5b57\u3092\u533a\u5225 -gui.action.case_sensitive.tip = \u691c\u7d22\u5358\u8a9e\u304c\u5927\u6587\u5b57/\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3059\u308b\u304b\u3092\u9078\u629e - -gui.action.search_regular_expression.label = \u6b63\u898f\u8868\u73fe -gui.action.search_regular_expression.tip = \u691c\u7d22\u6587\u5b57\u5217\u304c\u6b63\u898f\u8868\u73fe\u304b\u9078\u629e - -gui.action.search_forward.label = \u4e0a\u3078 -gui.action.search_forward.tip = \u4e0a\u3078\u691c\u7d22 - -gui.action.search_backward.label = \u4e0b\u3078 -gui.action.search_backward.tip = \u4e0b\u3078\u691c\u7d22 - -# NewOperator panel -#gui.label.auto_wire_on_add.label = Automatically wire new operators -#gui.label.auto_wire_on_add.tip = If checked, newly added operators are automatically connected. -#gui.label.auto_wire_on_add.icon = 16/plug.png -gui.action.auto_wire_on_add.label = \u65b0\u898f\u8ffd\u52a0\u30aa\u30da\u30ec\u30fc\u30bf\u306b\u81ea\u52d5\u63a5\u7d9a -gui.action.auto_wire_on_add.tip = \u65b0\u898f\u8ffd\u52a0\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u81ea\u52d5\u63a5\u7d9a\u3092\u6709\u52b9\u5316/\u7121\u52b9\u5316 -gui.action.auto_wire_on_add.icon = plug_new.png -gui.action.auto_wire_inputs_on_add.label = \u5165\u529b\u30dd\u30fc\u30c8\u81ea\u52d5\u63a5\u7d9a -gui.action.auto_wire_inputs_on_add.mne = I -gui.action.auto_wire_inputs_on_add.icon = plug_new_next.png -gui.action.auto_wire_inputs_on_add.tip = \u65b0\u898f\u8ffd\u52a0\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5165\u529b\u30dd\u30fc\u30c8\u304c\u81ea\u52d5\u63a5\u7d9a\u3055\u308c\u307e\u3059\u3002 -gui.action.auto_wire_outputs_on_add.label = \u51fa\u529b\u30dd\u30fc\u30c8\u81ea\u52d5\u63a5\u7d9a -gui.action.auto_wire_outputs_on_add.mne = O -gui.action.auto_wire_outputs_on_add.icon = plug_new_previous.png -gui.action.auto_wire_outputs_on_add.tip = \u65b0\u898f\u8ffd\u52a0\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u51fa\u529b\u30dd\u30fc\u30c8\u304c\u81ea\u52d5\u63a5\u7d9a\u3055\u308c\u307e\u3059\u3002 - -gui.action.filter_deprecated.label = \u975e\u63a8\u5968\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u30d5\u30a3\u30eb\u30bf -gui.action.filter_deprecated.icon = funnel.png -gui.action.filter_deprecated.tip = \u975e\u63a8\u5968\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u975e\u8868\u793a - -gui.action.sort_by_usage.label = \u4f7f\u7528\u983b\u5ea6\u306b\u3088\u308a\u4e26\u3073\u66ff\u3048 -gui.action.sort_by_usage.icon = sort_descending.png -gui.action.sort_by_usage.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u4f7f\u7528\u983b\u5ea6\u306b\u3088\u308a\u4e26\u3073\u66ff\u3048 - -gui.field.filter_deprecated.tip = \u691c\u7d22\u5358\u8a9e\u3092\u5165\u529b\u3057\u3066\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u691c\u7d22 -gui.action.clear_filter.label = \u30d5\u30a3\u30eb\u30bf\u3092\u6d88\u53bb -gui.action.clear_filter.icon = delete.png -gui.action.clear_filter.tip = Clear the current filter. - - -gui.action.add_operator_now.label = \u30aa\u30da\u30ec\u30fc\u30bf\u8ffd\u52a0 -gui.action.add_operator_now.mne = A -gui.action.add_operator_now.tip = \u30d7\u30ed\u30bb\u30b9\u306b\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u8ffd\u52a0 -gui.action.add_operator_now.icon = element_add.png - -# ProcessRenderer -gui.action.connect_port_to_repository_location.label = \u30ea\u30dd\u30b8\u30c8\u30ea{0}\u306b\u63a5\u7d9a -gui.action.connect_port_to_repository_location.mne = C -gui.action.connect_port_to_repository_location.icon = plug.png -gui.action.connect_port_to_repository_location.tip = {0}\u3092\u30ea\u30dd\u30b8\u30c8\u30ea\u5185\u306e\u30c7\u30fc\u30bf\u30b9\u30c8\u30a2\u306b\u63a5\u7d9a -gui.action.select_all.label = \u5168\u3066\u9078\u629e -gui.action.select_all.acc = control pressed A -gui.action.select_all.tip = \u5168\u3066\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u9078\u629e - -gui.action.selection_history.label = -gui.action.selection_history.icon = clock_preferences.png -gui.action.selection_history.tip = \u73fe\u5728\u9078\u629e\u4e2d\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u9078\u629e\uff08\u623b\u3059\uff09 - -gui.action.select_backward.label = -gui.action.select_backward.icon = arrow_left.png -gui.action.select_backward.tip = \u6700\u8fd1\u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u53c2\u7167\uff08\u623b\u3059\uff09 - -gui.action.select_forward.label = -gui.action.select_forward.icon = arrow_right.png -gui.action.select_forward.tip = \u6700\u8fd1\u9078\u629e\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u9078\u629e\uff08\u524d\u3078\uff09 - -gui.action.select_parent.label = -gui.action.select_parent.icon = arrow_up.png -gui.action.select_parent.tip = \u8868\u793a\u4e2d\u306e\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9\u306e\u89aa\u30d7\u30ed\u30bb\u30b9\u3078\u79fb\u52d5 - -gui.action.menu.new_operator.label = \u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf -gui.action.menu.new_operator.icon = element_new.png -gui.action.menu.new_operator.tip = \u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf\u633f\u5165 - -gui.action.menu.replace_operator.label = \u30aa\u30da\u30ec\u30fc\u30bf\u7f6e\u63db -gui.action.menu.replace_operator.icon = element_replace.png -gui.action.menu.replace_operator.tip = \u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf\u3068\u7f6e\u63db - -gui.action.menu.operator_group.label = -gui.action.menu.operator_group.icon = folder.png -gui.action.menu.operator_group.tip = \u30b0\u30eb\u30fc\u30d7{0}\u5185\u306e\u30aa\u30da\u30ec\u30fc\u30bf -gui.action.menu.operator_group.open.icon = folder_open.png -gui.action.menu.operator_group.closed.icon = folder.png - -gui.action.menu.new_building_block.label = \u65b0\u898f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af -gui.action.menu.new_building_block.icon = box_open_new.png - -gui.action.show_execution_order.label = \u5b9f\u884c\u9806\u5e8f\u8868\u793a -gui.action.show_execution_order.icon = sort_up_down.png -gui.action.show_execution_order.mne = S -gui.action.show_execution_order.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u5b9f\u884c\u9806\u5e8f\u306e\u30ea\u30b9\u30c8\u60c5\u5831\u3092\u8868\u793a - -gui.action.bring_operator_to_front.label = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u524d\u9762\u306b\u8868\u793a -gui.action.bring_operator_to_front.icon = element_previous.png -gui.action.bring_operator_to_front.mne = B -gui.action.bring_operator_to_front.tip = \u4ed6\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u79fb\u52d5\u3092\u884c\u308f\u305a\u306b\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u5b9f\u884c\u9806\u5e8f\u306e\u958b\u59cb\u4f4d\u7f6e\u306b\u79fb\u52d5\u3002 - -gui.action.menu.execution_order.label = \u30aa\u30da\u30ec\u30fc\u30bf\u5b9f\u884c\u9806\u5e8f -gui.action.menu.execution_order.mne = O -gui.action.menu.execution_order.icon = sort_up_down.png -gui.action.menu.execution_order.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5b9f\u884c\u9806\u5e8f\u3092\u5b9a\u7fa9\u304a\u3088\u3073\u8868\u793a - -gui.action.render_execution_order.label = \u9806\u5e8f\u306b\u6cbf\u3063\u3066\u5b9f\u884c -gui.action.render_execution_order.mne = O -gui.action.render_execution_order.icon = sort_up_down_question.png -gui.action.render_execution_order.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5b9f\u884c\u9806\u5e8f\u3092\u5909\u66f4\u304a\u3088\u3073\u8868\u793a - -gui.dialog.execution_order_info.title = \u5b9f\u884c\u9806\u5e8f -gui.dialog.execution_order_info.message = \u73fe\u5728\u306e\u8a2d\u5b9a\u3067\u306e\u5b9f\u884c\u9806\u5e8f -gui.dialog.execution_order_info.icon = sort_up_down.png - -gui.action.rename_in_processrenderer.label = \u540d\u524d\u306e\u5909\u66f4 -gui.action.rename_in_processrenderer.icon = element_edit.png -gui.action.rename_in_processrenderer.mne = R -gui.action.rename_in_processrenderer.acc = F2 -gui.action.rename_in_processrenderer.tip = \u73fe\u5728\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u540d\u524d\u3092\u5909\u66f4 - -gui.dialog.input.rename_operator.title = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u540d\u524d\u3092\u5909\u66f4 -gui.dialog.input.rename_operator.icon = element_edit.png -gui.dialog.input.rename_operator.message = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.action.arrange_operators.label = \u30aa\u30da\u30ec\u30fc\u30bf\u914d\u7f6e -gui.action.arrange_operators.icon = layout.png -gui.action.arrange_operators.mne = g -gui.action.arrange_operators.tip = \u30d7\u30ed\u30bb\u30b9\u5185\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u81ea\u52d5\u3067\u914d\u7f6e - -gui.action.auto_fit.label = \u30b5\u30a4\u30ba\u3092\u5408\u308f\u305b\u308b -gui.action.auto_fit.mne = z -gui.action.auto_fit.icon = fit_to_size.png -gui.action.auto_fit.tip = \u30d7\u30ed\u30bb\u30b9\u3092\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30b5\u30a4\u30ba\u306b\u5408\u308f\u305b\u308b - -gui.action.delete_selected_connection.label = \u63a5\u7d9a\u524a\u9664 -gui.action.delete_selected_connection.icon = delete.png -gui.action.delete_selected_connection.tip = \u73fe\u5728\u9078\u629e\u3057\u3066\u3044\u308b\u63a5\u7d9a\u3092\u524a\u9664 -gui.action.delete_selected_connection.acc = DELETE - -gui.action.disconnect.label = \u30dd\u30fc\u30c8\u63a5\u7d9a\u89e3\u9664 -gui.action.disconnect.mne = D -gui.action.disconnect.tip = \u3053\u306e\u30dd\u30fc\u30c8\u63a5\u7d9a\u3092\u89e3\u9664\u3059\u308b\u3002 -gui.action.disconnect.icon = plug_delete.png - -gui.action.show_port_data.label = \u7d50\u679c{0}\u3092\u8868\u793a -gui.action.show_port_data.icon = presentation_chart.png -gui.action.show_port_data.tip = {0}\u3092\u7d50\u679c\u30d3\u30e5\u30fc\u30ef\u3067\u8868\u793a - -gui.action.add_subprocess.label = \u8ffd\u52a0 -gui.action.add_subprocess.icon = element_selection_add.png -gui.action.add_subprocess.tip = \u3053\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306b\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9\u3092\u8ffd\u52a0 -gui.action.add_subprocess.tip.after = \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9''{0}''\u306e\u5f8c\u306b\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9\u3092\u8ffd\u52a0 -gui.action.add_subprocess.tip.before = \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9''{0}''\u306e\u524d\u306b\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9\u3092\u8ffd\u52a0 - -gui.action.delete_subprocess.label = \u524a\u9664 -gui.action.delete_subprocess.icon = element_selection_delete.png -gui.action.delete_subprocess.tip = \u3053\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u304b\u3089\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9\u3092\u524a\u9664 -gui.action.delete_subprocess.tip.after = \u3053\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u304b\u3089\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9''{0}''\u3092\u524a\u9664 - -gui.action.menu.process_layout.label = \u30d7\u30ed\u30bb\u30b9\u30ec\u30a4\u30a2\u30a6\u30c8 -gui.action.menu.process_layout.icon = layout.png -gui.action.menu.process_layout.tip = \u30d7\u30ed\u30bb\u30b9\u30ec\u30a4\u30a2\u30a6\u30c8\u3092\u5909\u66f4 -gui.action.menu.process_layout.mne = L - -gui.action.specify_context.label = \u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u6307\u5b9a -gui.action.specify_context.icon = environment.png -gui.action.specify_context.tip = \u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u958b\u304d\u5165\u529b\u30d7\u30ed\u30bb\u30b9\u3001\u51fa\u529b\u30d7\u30ed\u30bb\u30b9\u304a\u3088\u3073\u30de\u30af\u30ed\u3092\u6307\u5b9a - -gui.action.define_macros.label = \u30de\u30af\u30ed\u5b9a\u7fa9 -gui.action.define_macros.icon = keyboard_key_a.png -gui.action.define_macros.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u306b\u5bfe\u3057\u30de\u30af\u30ed\u3092\u5b9a\u7fa9\u3059\u308b\u3002 - - -#RepositoryBrowser -#gui.repository.db.icon = data_network.png -#gui.repository.local.icon = hard_drive.png -#gui.repository.remote.icon = server2.png -#gui.repository.resource.icon = box_open.png -#gui.repository.enterprise.icon = hard_drive.png - -gui.action.add_repository.label = \u30ea\u30dd\u30b8\u30c8\u30ea\u8ffd\u52a0 -gui.action.add_repository.mne = A -gui.action.add_repository.icon = server_add.png -gui.action.add_repository.tip = \u65b0\u898f\u30ea\u30dd\u30b8\u30c8\u30ea\u30b5\u30fc\u30d0\u3078\u306e\u63a5\u7d9a\u3092\u8ffd\u52a0 - -gui.action.configure_repository.label = \u30ea\u30dd\u30b8\u30c8\u30ea\u8a2d\u5b9a -gui.action.configure_repository.mne = C -gui.action.configure_repository.icon = server_edit.png -gui.action.configure_repository.tip = \u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u8a2d\u5b9a\u3092\u7de8\u96c6 - -gui.action.open_repository_entry.label = \u958b\u304f -gui.action.open_repository_entry.mne = O -gui.action.open_repository_entry.icon = folder_open.png -gui.action.open_repository_entry.tip = \u30d7\u30ed\u30bb\u30b9\u3092\u958b\u304f\u304b\u30c7\u30fc\u30bf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u7d50\u679c\u30d3\u30e5\u30fc\u3067\u958b\u304f - -gui.dialog.error.error_rename.title = \u30a8\u30e9\u30fc -gui.dialog.error.error_rename.message = \u30a8\u30f3\u30c8\u30ea{0}\u306e\u540d\u524d\u3092\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc - -#gui.action.open_process_from_repository.label = Open Process -#gui.action.open_process_from_repository.mne = O -#gui.action.open_process_from_repository.icon = folder_open.png -#gui.action.open_process_from_repository.tip = Download process from the repository server and open it in RapidMiner. - -#gui.action.store_process_in_folder.label = Store Process... -#gui.action.store_process_in_folder.mne = S -#gui.action.store_process_in_folder.icon = floppy_disk.png -#gui.action.store_process_in_folder.tip = Upload current process to the remote repository. - -#gui.action.show_data_as_result.label = Open as Result -#gui.action.show_data_as_result.mne = R -#gui.action.show_data_as_result.icon = presentation_chart.png -#gui.action.show_data_as_result.tip = Download data from the repository server and show it in the result viewer. - -gui.action.repository_refresh_folder.label = \u66f4\u65b0 -gui.action.repository_refresh_folder.mne = R -gui.action.repository_refresh_folder.icon = folder_open_refresh.png -gui.action.repository_refresh_folder.tip = \u3053\u306e\u30d5\u30a9\u30eb\u30c0\u5185\u306e\u30c7\u30fc\u30bf\u3092\u66f4\u65b0 -gui.action.repository_refresh_folder.acc = F5 - -gui.action.repository_create_folder.label = \u30d5\u30a9\u30eb\u30c0\u4f5c\u6210 -gui.action.repository_create_folder.mne = C -gui.action.repository_create_folder.icon = folder_open_new.png -gui.action.repository_create_folder.tip = \u65b0\u898f\u30b5\u30d6\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210 - -gui.action.repository_store_process.label = \u30d7\u30ed\u30bb\u30b9\u4fdd\u5b58 -gui.action.repository_store_process.mne = S -gui.action.repository_store_process.icon = floppy_disk.png -gui.action.repository_store_process.tip = \u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u6307\u5b9a\u3057\u305f\u5834\u6240\u306b\u4fdd\u5b58 - -gui.action.repository_copy_location.label = \u4f4d\u7f6e\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc -gui.action.repository_copy_location.mne = C -gui.action.repository_copy_location.icon = copy.png -gui.action.repository_copy_location.tip = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc - -gui.action.repository_paste.label = \u8cbc\u308a\u4ed8\u3051 -gui.action.repository_paste.acc = control V -gui.action.repository_paste.icon = clipboard_paste.png -gui.action.repository_paste.tip = \u5185\u5bb9\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u304b\u3089\u8cbc\u308a\u4ed8\u3051\u308b - -gui.action.repository_copy.label = \u30b3\u30d4\u30fc -gui.action.repository_copy.acc = control C -gui.action.repository_copy.icon = copy.png -gui.action.repository_copy.tip = \u9078\u629e\u3057\u305f\u5185\u5bb9\u3092\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc - -gui.action.repository_delete_entry.label = \u524a\u9664 -gui.action.repository_delete_entry.mne = D -gui.action.repository_delete_entry.acc = DELETE -gui.action.repository_delete_entry.icon = folder_open_delete.png -gui.action.repository_delete_entry.tip = Delete selected entry. - -gui.action.repository_rename_entry.label = \u540d\u524d\u3092\u5909\u66f4 -gui.action.repository_rename_entry.mne = n -gui.action.repository_rename_entry.acc = F2 -gui.action.repository_rename_entry.icon = folder_open_edit.png -gui.action.repository_rename_entry.tip = \u9078\u629e\u3057\u305f\u8981\u7d20\u306e\u540d\u524d\u3092\u5909\u66f4 - -gui.dialog.message.please_create_repository.title = \u6700\u521d\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u4f5c\u6210 -gui.dialog.message.please_create_repository.message = You do not have a RapidMiner repository defined. \ - This might be because you are starting RapidMiner for the first time. In the next dialog, please \ - select a directory to install a local repository and use this repository to store all your data \ - and processes. Only for data and processes stored in the repository will you be able to use all \ - RapidMiner features, foremost the new meta data transformation rules. - -gui.dialog.repositorydialog.title = \u65b0\u898f\u30ea\u30dd\u30b8\u30c8\u30ea -gui.dialog.repositorydialog.message = \u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u5165\u529b\u3057\u30ed\u30fc\u30ab\u30eb\u3082\u3057\u304f\u306f\u30ea\u30e2\u30fc\u30c8\u306b\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u4f5c\u6210 -gui.dialog.repositorydialog.icon = server_add.png - -gui.dialog.repositoryconfigdialog.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u8a2d\u5b9a -gui.dialog.repositoryconfigdialog.message = \u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u5165\u529b\u3057\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u8a2d\u5b9a\u3059\u308b\u3002 -gui.dialog.repositoryconfigdialog.icon = server_edit.png - -gui.label.repositorydialog.url.label = \u30ea\u30dd\u30b8\u30c8\u30eaURL: -gui.label.repositorydialog.root_directory.label = \u30eb\u30fc\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea: -gui.label.repositorydialog.root_directory.mne = R -gui.label.repositorydialog.url.mne = d -gui.label.repositorydialog.alias.label = \u30a8\u30a4\u30ea\u30a2\u30b9: -gui.label.repositorydialog.alias.mne = A -gui.label.repositorydialog.user.label = \u30e6\u30fc\u30b6: -gui.label.repositorydialog.user.mne = r -gui.label.repositorydialog.password.label = \u30d1\u30b9\u30ef\u30fc\u30c9: -gui.label.repositorydialog.password.mne = P -gui.label.repositorydialog.askpassword.message = \u30ea\u30dd\u30b8\u30c8\u30ea{1}\u306b\u5bfe\u3059\u308b\u30e6\u30fc\u30b6{0}\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u5fc5\u8981\u3067\u3059\u3002 - -gui.dialog.add_repository.error = \u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.input.repository.new_folder.title = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0 -gui.dialog.input.repository.new_folder.icon = folder_open_new.png -gui.dialog.input.repository.new_folder.message = \u65b0\u898f\u30d5\u30a9\u30eb\u30c0\u306e\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.input.store_process.title = \u30d7\u30ed\u30bb\u30b9\u4fdd\u5b58 -gui.dialog.input.store_process.icon = floppy_disk.png -gui.dialog.input.store_process.message = \u3053\u306e\u30d7\u30ed\u30bb\u30b9\u306b\u5bfe\u3057\u540d\u524d\u3092\u5165\u529b - -gui.action.new_local_repositiory.label = \u65b0\u898f\u30ed\u30fc\u30ab\u30eb\u30ea\u30dd\u30b8\u30c8\u30ea -gui.action.new_local_repositiory.mne = l -gui.action.new_remote_repositiory.label = \u65b0\u898f\u30ea\u30e2\u30fc\u30c8\u30ea\u30dd\u30b8\u30c8\u30ea -gui.action.new_remote_repositiory.mne = r - -## Remote repository actions -gui.dialog.error.error_contacting_repository.title = \u30ea\u30e2\u30fc\u30c8\u30ea\u30dd\u30b8\u30c8\u30ea\u30a8\u30e9\u30fc -gui.dialog.error.error_contacting_repository.message = \u30ea\u30e2\u30fc\u30c8\u30ea\u30dd\u30b8\u30c8\u30ea{0}\u306b\u5bfe\u3057\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.action.repository.new_revision.label = \u65b0\u898f\u30d0\u30fc\u30b8\u30e7\u30f3\u958b\u59cb -gui.action.repository.new_revision.new = r -gui.action.repository.new_revision.tip = \u3053\u306e\u5185\u5bb9\u306b\u5bfe\u3059\u308b\u65b0\u898f\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u958b\u59cb - -gui.dialog.repository.edit_access_rights.title = \u30a2\u30af\u30bb\u30b9\u8a31\u53ef\u3092\u7de8\u96c6: {0} -gui.dialog.repository.edit_access_rights.message =\u5185\u5bb9{0}\u306b\u5bfe\u3059\u308b\u6a29\u9650\u3092\u7de8\u96c6 -gui.dialog.repository.edit_access_rights.icon = key.png - -gui.action.repository.edit_access_rights.label = \u30a2\u30af\u30bb\u30b9\u8a31\u53ef\u3092\u7de8\u96c6 -gui.action.repository.edit_access_rights.mne = A -gui.action.repository.edit_access_rights.icon = key.png -gui.action.repository.edit_access_rights.tip = \u3053\u306e\u5165\u529b\u306b\u5bfe\u3059\u308b\u8aad\u307f\u8fbc\u307f\u3001\u66f8\u304d\u8fbc\u307f\u3001\u5b9f\u884c\u6a29\u9650\u3092\u4fee\u6b63 - -gui.action.confirm.yes.label = \u306f\u3044 -gui.action.confirm.yes.icon = ok.png -gui.action.confirm.no.label = \u3044\u3044\u3048 -gui.action.confirm.no.icon = error.png - -gui.dialog.confirm.icon = question.png - -gui.dialog.confirm.exit.title = RapidMiner\u3092\u7d42\u4e86 -gui.dialog.confirm.exit.icon = door_exit.png -gui.dialog.confirm.exit.message = RapidMiner\u3092\u7d42\u4e86\u3057\u307e\u3059\u304b? - -gui.dialog.confirm.save.title = \u5909\u66f4\u3092\u4fdd\u5b58 -gui.dialog.confirm.save.icon = floppy_disk.png -gui.dialog.confirm.save.message = {0}\u3078\u306e\u5909\u66f4\u3092\u4fdd\u5b58\u3057\u307e\u3059\u304b? - -gui.dialog.confirm.overwrite_entry.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u5185\u5bb9\u3092\u4e0a\u66f8\u304d -gui.dialog.confirm.overwrite_entry.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite_entry.message = {0}\u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b? - -gui.dialog.confirm.overwrite_entry_different_type.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u5185\u5bb9\u3092\u4e0a\u66f8\u304d -gui.dialog.confirm.overwrite_entry_different_type.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite_entry_different_type.message = \u65b0\u3057\u3044\u5185\u5bb9\u306f{0}\u306b\u5bfe\u3057\u7570\u306a\u308b\u30bf\u30a4\u30d7\u306b\u306a\u308a\u307e\u3059\u3002\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b\uff1f - -gui.dialog.confirm.overwrite.title = \u30d5\u30a1\u30a4\u30eb\u3092\u4e0a\u66f8\u304d -gui.dialog.confirm.overwrite.icon = floppy_disk_warning.png -gui.dialog.confirm.overwrite.message = {0}\u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b ? - -gui.dialog.confirm.editor.search_replace.no_more_hits.title = \u6587\u5b57\u5217\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 -gui.dialog.confirm.editor.search_replace.no_more_hits.message = \u691c\u7d22\u6587\u5b57\u5217\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002{0}\u304b\u3089\u691c\u7d22\u3092\u3057\u307e\u3059\u304b? - -gui.dialog.message.icon = information.png - - -#RepositoryBrowserDialog -gui.action.repository_select_location.label = \u5834\u6240\u3092\u9078\u629e -gui.action.repository_select_location.icon = folder_open.png -gui.action.repository_select_location.mne = S - -gui.dialog.repository_chooser.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u30d6\u30e9\u30a6\u30b6 -gui.dialog.repository_chooser.icon = server.png -gui.dialog.repository_chooser.message = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e\u3092\u9078\u629e - -gui.label.repository_chooser.entry_name.label = \u540d\u524d -gui.label.repository_chooser.entry_name.mne = N - -gui.label.repository_chooser.location.label = \u5834\u6240 - -gui.action.repository_chooser.resolve.label = {0}\u306b\u5bfe\u3059\u308b\u76f8\u5bfe\u30d1\u30b9\u3078\u5909\u66f4 -gui.action.repository_chooser.resolve.mne = R -gui.action.repository_chooser.resolve.tip = \u9078\u629e\u30a2\u30a4\u30c6\u30e0\u3092\u76f8\u5bfe\u30d1\u30b9\u304b\u3089\u53c2\u7167 - -gui.dialog.error.repository_entry_already_exists.title = \u5b58\u5728\u3057\u307e\u3059 -gui.dialog.error.repository_entry_already_exists.message = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u5185\u5bb9''{0}''\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 - -#RunRemoteDialog -gui.dialog.runremotedialog.title = \u30d7\u30ed\u30bb\u30b9\u3092\u30ea\u30e2\u30fc\u30c8\u3067\u5b9f\u884c -#gui.dialog.runremotedialog.icon = server2_play.png -gui.dialog.runremotedialog.message = \u30d7\u30ed\u30bb\u30b9\u3092\u30b5\u30fc\u30d0\u4e0a\u3067\u5b9f\u884c\u3059\u308b\u3088\u3046\u306b\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\u5316\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u3068\u7570\u306a\u308b\u5185\u5bb9\u3067\u51e6\u7406\u3059\u308b\u3092\u884c\u3046\u5834\u5408 \ \u95a2\u9023\u30bf\u30d6\u306e\u5185\u5bb9\u306e\u7de8\u96c6\u304c\u53ef\u80fd\u3067\u3059\u3002 - -gui.tabs.runremotedialog.schedule.label = \u30b9\u30b1\u30b8\u30e5\u30fc\u30eb -gui.tabs.runremotedialog.schedule.mne = S -gui.tabs.runremotedialog.schedule.tip = \u30b5\u30fc\u30d0\u304a\u3088\u3073\u5b9f\u884c\u6642\u9593\u3092\u9078\u629e -#gui.tabs.runremotedialog.schedule.icon = server2_play.png - -gui.tabs.runremotedialog.context.label = \u30b3\u30f3\u30c6\u30ad\u30b9\u30c8 -gui.tabs.runremotedialog.context.mne = t -gui.tabs.runremotedialog.context.tip = \u30d7\u30ed\u30bb\u30b9\u5b9f\u884c\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u5b9a\u7fa9 -gui.tabs.runremotedialog.context.icon = environment.png - -gui.label.context.input.label = \u30d7\u30ed\u30bb\u30b9\u5165\u529b -gui.label.context.input.icon = 16/plug_next.png -gui.label.context.output.label = \u30d7\u30ed\u30bb\u30b9\u51fa\u529b -gui.label.context.output.icon = 16/plug_previous.png - -gui.label.macros.label = \u30de\u30af\u30ed -gui.label.macros.icon = 16/keyboard_key_a.png - -gui.action.macros.add_macro.label = \u30de\u30af\u30ed\u8ffd\u52a0 -gui.action.macros.add_macro.mne = A -gui.action.macros.add_macro.tip = \u30de\u30af\u30ed\u3092\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0 -gui.action.macros.add_macro.icon = keyboard_key_a_add.png - -gui.action.macros.delete_macro.label = \u30de\u30af\u30ed\u524a\u9664 -gui.action.macros.delete_macro.mne = D -gui.action.macros.delete_macro.tip = \u9078\u629e\u3057\u305f\u30de\u30af\u30ed\u3092\u30ea\u30b9\u30c8\u304b\u3089\u524a\u9664 -gui.action.macros.delete_macro.icon = keyboard_key_a_delete.png - -gui.label.processcontext_help.help = \u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u306b\u3066\u30d7\u30ed\u30bb\u30b9\u3092\u5b9f\u884c\u3059\u308b\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u4fee\u6b63 \\u3000\u30d7\u30ed\u30bb\u30b9\u304c\u7570\u306a\u308b\u74b0\u5883\u3067\u5b9f\u884c\u3055\u308c\u308b\u5834\u5408\u306b\u5229\u7528\u3067\u304d\u308b\u6a5f\u80fd\u3067\u3059\u3002\u4f8b\uff1a\u30b9\u30bf\u30f3\u30c9\u30a2\u30ed\u30f3\u3001\u7d44\u307f\u8fbc\u307f\u3001\u30ed\u30fc\u30ab\u30eb\u3001\u30ea\u30e2\u30fc\u30c8\u74b0\u5883\u306b\u304a\u3051\u308b\u30b5\u30fc\u30d3\u30b9\u63d0\u4f9b\u306e\u969b -gui.action.context.apply.label = \u9069\u5fdc -gui.action.context.apply.mne = A -gui.action.context.apoply.tip = \u5909\u66f4\u3092\u9069\u5fdc -gui.action.context.apply.icon = check.png - -gui.action.context.input.add_row.label = \u884c\u8ffd\u52a0 -gui.action.context.input.add_row.tip = \u65b0\u898f\u30d7\u30ed\u30bb\u30b9\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 -gui.action.context.input.add_row.icon = plug_add.png - -gui.action.context.input.delete_row.label = \u884c\u524a\u9664 -gui.action.context.input.delete_row.tip = \u9078\u629e\u3057\u305f\u30d7\u30ed\u30bb\u30b9\u30bd\u30fc\u30b9\u3092\u524a\u9664 -gui.action.context.input.delete_row.icon = plug_delete.png - -gui.action.context.output.add_row.label = \u884c\u8ffd\u52a0 -gui.action.context.output.add_row.tip = \u65b0\u898f\u30d7\u30ed\u30bb\u30b9\u3092\u8ffd\u52a0 -gui.action.context.output.add_row.icon = plug_add.png - -gui.action.context.output.delete_row.label = \u884c\u524a\u9664 -gui.action.context.output.delete_row.tip = \u9078\u629e\u3057\u305f\u30d7\u30ed\u30bb\u30b9\u3092\u524a\u9664 -gui.action.context.output.delete_row.icon = plug_delete.png - -gui.label.runremotedialog.repository.label = \u30ea\u30dd\u30b8\u30c8\u30ea -gui.label.runremotedialog.repository.mne = R -gui.label.runremotedialog.repository.icon = data.png -gui.label.runremotedialog.date.label = \u65e5\u4ed8 -gui.label.runremotedialog.date.mne = D -#gui.label.runremotedialog.date.icon = 16/clock_run.png -gui.label.runremotedialog.cronexpression.label = \u5f0f -gui.label.runremotedialog.cronexpression.mne = x -#gui.label.runremotedialog.cronexpression.icon = 16/calendar_clock.png -gui.label.runremotedialog.process_location.label = \u30d7\u30ed\u30bb\u30b9\u306e\u4f4d\u7f6e -gui.label.runremotedialog.process_location.mne = P - -gui.action.runremotedialog.now.label = \u4eca\u3059\u3050\u306b -gui.action.runremotedialog.now.mne = N -#gui.action.runremotedialog.now.icon = media_play.png -gui.action.runremotedialog.now.tip = \u4eca\u3059\u3050\u306b\u30d7\u30ed\u30bb\u30b9\u3092\u5b9f\u884c - -gui.action.runremotedialog.once.label = \u4e00\u5ea6\u306e\u307f -gui.action.runremotedialog.once.mne = O -gui.action.runremotedialog.once.tip = \u30d7\u30ed\u30bb\u30b9\u3092\u5f8c\u3067\u4e00\u5ea6\u3060\u3051\u5b9f\u884c - -gui.action.runremotedialog.cron.label = Cron\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb -gui.action.runremotedialog.cron.mne = r -gui.action.runremotedialog.cron.tip = Cron\u306e\u8a2d\u5b9a\u5185\u5bb9\u3092\u6307\u5b9a\u3057\u7e70\u308a\u8fd4\u3057\u5b9f\u884c - -gui.action.runremotedialog.cronstart.label = \u958b\u59cb -gui.action.runremotedialog.cronstart.mne = S -gui.action.runremotedialog.cronstart.tip = \u958b\u59cb\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\u3092\u6307\u5b9a - -gui.action.runremotedialog.cronend.label = \u7d42\u4e86 -gui.action.runremotedialog.cronend.mne = E -gui.action.runremotedialog.cronend.tip = \u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\u7d42\u4e86\u3092\u6307\u5b9a - -gui.action.cron_help.label = \u4f55\u3067\u3059\u304b? -gui.action.cron_help.mne = W -gui.action.cron_help.icon = question.png -gui.dialog.message.cron_long_help.title = Cron\u8868\u73fe -gui.dialog.message.cron_long_help.message = \u5168\u3066\u306e\u65e5\u4ed8\u5f62\u5f0f\u306fdd-MM-yyyy HH:mm:ss\u3067\u3059\u3002\ - Cron\u8868\u73fe\u306f6\u500b\u3082\u3057\u304f\u306f7\u500b\u306e\u30b9\u30da\u30fc\u30b9\u533a\u5207\u308a\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u3088\u3063\u3066\u69cb\u6210\u3057\u307e\u3059:
    \ -
     \u79d2 \u5206 \u6642 \u65e5 \u6708 \u66dc\u65e5 [\u5e74].
    \ - \u305d\u308c\u305e\u308c\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306f\u6570\u5024\u3067\u8868\u73fe\u3092\u884c\u3044\u3001 \u4e00\u6708\u306f1\u3001\u65e5\u66dc\u65e5\u306f1\u3068\u8a00\u3046\u69d8\u306b\u5b9a\u7fa9\u3057\u307e\u3059\u3002 \ - \u66dc\u65e5\u306f\u307e\u305f\u3001SUN-SAT \u304a\u3088\u3073 \u6708 \ - \u306f JAN-DEC\u3068\u8a00\u3046\u3088\u3046\u306b\u8868\u73fe\u3059\u308b\u4e8b\u3082\u53ef\u80fd\u3067\u3059\u3002\u5217\u6319\u578b(Enum) \u306f\u30ab\u30f3\u30de(,)\u306b\u3088\u3063\u3066 \ - \u533a\u5207\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u30cf\u30a4\u30d5\u30f3(-)\u306b\u3088\u3063\u3066\u8868\u73fe\u3055\u308c\u307e\u3059\u3002\u30a2\u30b9\u30bf\u30ea\u30b9\u30af (*)\u306f\u5168\u3066\u5408\u81f4\u3059\u308b\u5024\ - \u304a\u3088\u3073\u3001dayOfWeek\u3001dayOfMonth\u3001 \u306b\u5bfe\u3057\u7591\u554f\u7b26(?)\u3092\u8a2d\u5b9a\u3059\u308b\u4e8b\u306f "\u5024\u306e\u6307\u5b9a\u304c\u7121\u3044 \ - "\u3068\u8a00\u3046\u8868\u73fe\u306b\u306a\u308a\u307e\u3059\u3002\u5897\u52a0\u306f(/)\u306b\u3088\u3063\u3066\u8868\u73fe\u3057\u307e\u3059\u3002\u4f8b\uff1a 0/5\u3092 \ - \u5206 \u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u8a2d\u5b9a\u3059\u308b\u4e8b\u306b\u3088\u308a5\u5206\u6bce\u3092\u610f\u5473\u3057\u307e\u3059\u3002 \u65e5\u306b\u5bfe\u3057 \ - L\u3092\u6307\u5b9a\u3059\u308b\u5834\u5408\u3001\u8a72\u5f53\u6708\u306e\u6700\u7d42\u65e5\u3092\u610f\u5473\u3057\u3001W\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u3067 \ - \u3000\u55b6\u696d\u65e5\u3092\u8868\u73fe\u3057\u307e\u3059\u3002 \u66dc\u65e5\u306b\u5bfe\u3057#n\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u3067\u8a72\u5f53\u6708\u306e\u4e2d\u3067n\u756a\u76ee\u306e \ - \u65e5\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u306b\u306a\u308aL\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u3067\u6700\u7d42\u65e5\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 - -#RemoteProcessViewer, RemoteEntry, and AccessRightsDialog -gui.action.remoteprocessviewer.open.label = \u958b\u304f -gui.action.remoteprocessviewer.open.icon = folder_open.png -gui.action.remoteprocessviewer.open.mne = O -gui.action.remoteprocessviewer.open.tip = \u9078\u629e\u3057\u305f\u30d7\u30ed\u30bb\u30b9\u3082\u3057\u304f\u306fIO\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092RapidMiner\u3067\u958b\u304d\u307e\u3059 - -gui.action.remoteprocessviewer.browse.label = \u53c2\u7167 -gui.action.remoteprocessviewer.browse.icon = window_earth.png -gui.action.remoteprocessviewer.browse.mne = B -gui.action.remoteprocessviewer.browse.tip = \u9078\u629e\u3057\u305f\u30d7\u30ed\u30bb\u30b9\u3082\u3057\u304f\u306fIO\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092web\u30d6\u30e9\u30a6\u30b6\u3067\u958b\u304d\u307e\u3059 - -gui.action.remoteprocessviewer.stop.label = \u505c\u6b62 -gui.action.remoteprocessviewer.stop.icon = media_stop.png -gui.action.remoteprocessviewer.stop.mne = S -gui.action.remoteprocessviewer.stop.tip = \u9078\u629e\u3057\u305f\u30ea\u30e2\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9\u3092\u505c\u6b62 - -gui.action.remoteprocessviewer.show_log.label = \u30ed\u30b0\u8868\u793a -gui.action.remoteprocessviewer.show_log.icon = history.png -gui.action.remoteprocessviewer.show_log.mne = L -gui.action.remoteprocessviewer.show_log.tip = \u3053\u306e\u30d7\u30ed\u30bb\u30b9\u306e\u30ed\u30b0\u3092\u8868\u793a - -gui.label.remoteprocessviewer.filter.label = \u30d5\u30a3\u30eb\u30bf\u30fc -gui.label.remoteprocessviewer.filter.mne = F -gui.label.remoteprocessviewer.filter.icon = funnel.png -gui.combo.remoteprocessviewer.since_session_start = \u30bb\u30c3\u30b7\u30e7\u30f3 -gui.combo.remoteprocessviewer.for_today = \u4eca\u65e5 -gui.combo.remoteprocessviewer.all = \u5168\u3066 - -gui.action.remoterepository.administer.label = \u7ba1\u7406\u8005 (Web\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9) -gui.action.remoterepository.administer.icon = control_panel.png -gui.action.remoterepository.administer.mne = A -gui.action.remoterepository.administer.tip = Web\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9\u3092\u4f7f\u7528\u3057\u3066\u3044\u308b\u7ba1\u7406\u8005 - -gui.dialog.error.remoteprocessviewer.stop_failed.title = \u505c\u6b62\u5931\u6557 -gui.dialog.error.remoteprocessviewer.stop_failed.message = \u30ea\u30e2\u30fc\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u505c\u6b62\u306b\u5931\u6557: {0} - -gui.action.accessrights.add_row.label = \u884c\u8ffd\u52a0 -gui.action.accessrights.add_row.icon = table_selection_row_add.png -gui.action.accessrights.add_row.mne = A -gui.action.accessrights.add_row.tip = \u30c6\u30fc\u30d6\u30eb\u306b\u6a29\u9650\u3092\u8ffd\u52a0 - -gui.action.accessrights.remove_row.label = \u884c\u524a\u9664 -gui.action.accessrights.remove_row.icon = table_selection_row_delete.png -gui.action.accessrights.remove_row.mne = R -gui.action.accessrights.remove_row.tip = \u9078\u629e\u884c\u304b\u3089\u6a29\u9650\u3092\u524a\u9664 - -#DecisionRememberingConfirmDialog -gui.action.remember_decision.label = \u3053\u306e\u8a2d\u5b9a\u3092\u899a\u3048\u308b -gui.action.remember_decision.mne = R -gui.action.remember_decision.tip = \u30c1\u30a7\u30c3\u30af\u3059\u308b\u4e8b\u306b\u3088\u308a\u3001\u8a2d\u5b9a\u5185\u5bb9\u3092\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58\u3057\u307e\u3059\u3002 - -gui.action.yes.label = \u306f\u3044 -gui.action.yes.mne = Y -gui.action.yes.icon = ok.png -gui.action.yes.tip = \u78ba\u8a8d - -gui.action.no.label = No -gui.action.no.mne = N -gui.action.no.icon = error.png -gui.action.no.tip = \u62d2\u5426\u3059\u308b - -gui.dialog.show_results_on_creation.title = \u65b0\u3089\u3057\u3044\u7d50\u679c -gui.dialog.show_results_on_creation.icon = presentation_chart.png -gui.dialog.show_results_on_creation.message = \u65b0\u3057\u3044\u7d50\u679c\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u7d50\u679c\u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u306b\u5207\u308a\u66ff\u3048\u307e\u3059\u304b? - -gui.dialog.save_before_run.title = \u4fdd\u5b58 -gui.dialog.save_before_run.icon = floppy_disk.png -gui.dialog.save_before_run.message = \u958b\u59cb\u524d\u306b\u30d7\u30ed\u30bb\u30b9\u3092\u4fdd\u5b58\u3057\u307e\u3059\u304b? - -gui.dialog.save_over_with_new_version.title = \u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b? -gui.dialog.save_over_with_new_version.icon = floppy_disk.png -gui.dialog.save_over_with_new_version.message = \u66f8\u304d\u8fbc\u307f\u3092\u884c\u3046\u5185\u5bb9\u306f\u53e4\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306eRapidMiner\u3067\u4f7f\u7528\u3057\u3066\u3044\u305f\u5f62\u5f0f\u3067\u3059\u3002\u4e0a\u66f8\u304d\u3059\u308b\u524d\u306b\u30d7\u30ed\u30bb\u30b9\u304c\u6b63\u3057\u304f\u30a4\u30f3\u30dd\u30fc\u30c8\u3055\u308c\u305f\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u5b9f\u884c\u3057\u307e\u3059\u304b? - -######################################### -# Miscellaneous Dialogs -######################################### - -## UpdateDialog -gui.action.update_manager.label = RapidMiner\u3092\u66f4\u65b0 -gui.action.update_manager.icon = download.png -gui.action.update_manager.mne = U -gui.action.update_manager.tip = RapidMiner\u306e\u62e1\u5f35\u6a5f\u80fd\u3092\u66f4\u65b0\u304a\u3088\u3073\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb - -gui.dialog.error.update_error_development_build.title = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30de\u30cd\u30fc\u30b8\u30e3 -gui.dialog.error.update_error_development_build.message = \u958b\u767a\u7248\u306eRapidMiner\u306e\u5834\u5408\u3001\u66f4\u65b0\u306f\u3067\u304d\u307e\u305b\u3093 - -gui.dialog.update.title = RapidMiner\u3092\u66f4\u65b0 -gui.dialog.update.message = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u884c\u3046\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u9078\u629e\u3057\u4ee5\u4e0b\u3092\u66f4\u65b0\u3057\u307e\u3059\u3002 \u8a73\u7d30\u8a2d\u5b9a\u306b\u3066\u62e1\u5f35\u6a5f\u80fd\u3092\u30b0\u30ed\u30fc\u30d0\u30eb\u3067\u4f7f\u7528\u3059\u308b\u304b\uff08\u30c7\u30d5\u30a9\u30eb\u30c8\uff09 \\u30e6\u30fc\u30b6\u306e\u30db\u30fc\u30e0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3067\u4f7f\u7528\u3059\u308b\u304b\u3092\u9078\u629e\u3057\u307e\u3059\u3002RapidMiner\u306e\u66f4\u65b0\u6642\u306f\u5e38\u306b\u30b0\u30ed\u30fc\u30d0\u30eb\u3067\u306e\u66f4\u65b0\u306f\u5e38\u306b\u30b0\u30ed\u30fc\u30d0\u30eb\u3067\u306e\u8a2d\u5b9a\u306b\u306a\u308a\u307e\u3059\u3002\u7ba1\u7406\u8005\u6a29\u9650\u304c\u5fc5\u8981\u306a\u30b0\u30ed\u30fc\u30d0\u30eb\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306f\u66f4\u65b0\u4e2d\u306b\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002 -gui.dialog.update.icon = download.png - -gui.action.update.select.label = \u9078\u629e/\u975e\u9078\u629e -gui.action.update.select.icon = checkbox.png -gui.action.update.select.mne = S -gui.action.update.select.tip = \u73fe\u5728\u306e\u30a2\u30a4\u30c6\u30e0\u304b\u3089\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u884c\u3046\u7269\u3092\u9078\u629e\u3082\u3057\u304f\u306f\u975e\u9078\u629e\u3057\u307e\u3059 - -gui.action.update.fetch_bookmarks.label = \u30d6\u30c3\u30af\u30de\u30fc\u30af\u53d6\u5f97 -gui.action.update.fetch_bookmarks.icon = bookmark.png -gui.action.update.fetch_bookmarks.mne = B -gui.action.update.fetch_bookmarks.tip = rapidupdate.de\u4e0a\u3067\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u304b\u3089\u30d6\u30c3\u30af\u30de\u30fc\u30af\u60c5\u5831\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\u30e6\u30fc\u30b6\u540d\u304a\u3088\u3073\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002 - -gui.action.update.install.label = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb -gui.action.update.install.icon = download.png -gui.action.update.install.mne = I -gui.action.update.install.tip = \u9078\u629e\u3057\u305f\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb/\u66f4\u65b0\u3057\u307e\u3059 - -gui.dialog.error.error_during_update.title = \u66f4\u65b0\u5931\u6557 -gui.dialog.error.error_during_update.message = \u66f4\u65b0\u30b5\u30fc\u30d0\u3078\u306e\u30a2\u30af\u30bb\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\uff1a{0} - -gui.dialog.error.error_accessing_marketplace_account.title = \u30de\u30fc\u30b1\u30c3\u30c8\u30d7\u30ec\u30a4\u30b9\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.error_accessing_marketplace_account.message = \u30de\u30fc\u30b1\u30c3\u30c8\u30d7\u30ec\u30a4\u30b9\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u63a5\u7d9a\u4e2d\u306b\u30a8\u30e9\u30fc\u3002\u30d6\u30c3\u30af\u30de\u30fc\u30af\u304c\u5229\u7528\u3067\u304d\u307e\u3059\u3002\u4eca\u73fe\u5728\u30de\u30fc\u30b1\u30c3\u30c8\u30d7\u30ec\u30a4\u30b9\u306f\u30d9\u30fc\u30bf\u7248\u3068\u3057\u3066\u7a3c\u50cd\u3057\u3066\u3044\u307e\u3059\u3002\u691c\u8a3c\u76ee\u7684\u3067\u53c2\u52a0\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u3001\u8a2d\u5b9a\u304b\u3089\u30b5\u30fc\u30d0URL\u3092''http://rapidupdate.de:8180/UpdateServer''\u306b\u5909\u66f4\u3057\u307e\u3059\u3002\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8: {0} - -gui.dialog.error.failed_update_server.title = \u66f4\u65b0\u5931\u6557 -gui.dialog.error.failed_update_server.message = \u66f4\u65b0\u30b5\u30fc\u30d0{0}\u306b\u30a2\u30af\u30bb\u30b9\u51fa\u6765\u307e\u305b\u3093\u3002\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.confirm.update.complete_restart.title = \u66f4\u65b0\u5b8c\u4e86 -gui.dialog.confirm.update.complete_restart.message = -\u66f4\u65b0\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002\u66f4\u65b0\u5185\u5bb9\u3092\u53cd\u6620\u3059\u308b\u70ba\u306bRapidMiner\u3092\u518d\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u4eca\u3059\u3050\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b? - -gui.dialog.error.error_installing_update.title = \u66f4\u65b0\u5931\u6557 -gui.dialog.error.error_installing_update.message = \u66f4\u65b0\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u4e2d\u306b\u30a8\u30e9\u30fc: {0}\u30b0\u30ed\u30fc\u30d0\u30eb\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u5834\u5408RapidMiner\u3092\u7ba1\u7406\u8005\u6a29\u9650\u3067\u5b9f\u884c\u3057\u3066\u3044\u308b\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -# Currently, this is an unused feature. Don't be afraid, RapidMiner is, and will always be, open source and free. -# However, future extensions like connectors to SAP or other data sources requiring proprietary -# drivers with expensive license fees may only be available on a commercial basis, for obvious reasons :-) -gui.dialog.message.purchase_package.title = {0}\u3092\u8cfc\u5165 -gui.dialog.message.purchase_package.message = RapidMiner\u306e\u62e1\u5f35\u6a5f\u80fd{0}\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u5834\u5408"\u3053\u306e\u62e1\u5f35\u6a5f\u80fd\u3092\u6ce8\u6587"\u30ea\u30f3\u30af\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u304b\u3001www.rapidminer.com\u306b\u3042\u308b\u30b7\u30e7\u30c3\u30d7\u30b5\u30a4\u30c8\u3092\u8a2a\u554f\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.progress.check_for_updates.label = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u78ba\u8a8d\u4e2d -gui.progress.fetching_updates.label = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u53d6\u5f97\u4e2d -gui.progress.installing_updates.label = \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u4e2d - -gui.dialog.confirm.updates_exist.title = RapidMiner\u3092\u66f4\u65b0 -gui.dialog.confirm.updates_exist.icon = package_add.png -gui.dialog.confirm.updates_exist.message = RapidMiner\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u304c\u5229\u7528\u51fa\u6765\u307e\u3059\u3002\u66f4\u65b0\u30de\u30cd\u30fc\u30b8\u30e3\u3092\u958b\u304d\u307e\u3059?\u81ea\u52d5\u3067\u66f4\u65b0\u5185\u5bb9\u306e\u78ba\u8a8d\u3092\u884c\u3044\u307e\u3059\u304c\u3001\u8a2d\u5b9a\u304b\u3089\u7121\u52b9\u5316\u3059\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002 - -## ExtensionDialog -gui.dialog.manage_extensions.title = \u62e1\u5f35\u6a5f\u80fd\u7ba1\u7406 -gui.dialog.manage_extensions.message = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08\u307f\u306e\u62e1\u5f35\u6a5f\u80fd\u306e\u6709\u52b9\u5316/\u7121\u52b9\u5316\u3092\u884c\u3048\u307e\u3059\u3002\u540c\u3058\u62e1\u5f35\u6a5f\u80fd\u5185\u3067\u8907\u6570\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u5b58\u5728\u3059\u308b\u5834\u5408\u3001\u4f7f\u7528\u3059\u308b\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002\u5909\u66f4\u3092\u884c\u3046\u5834\u5408\u306fRapidMiner\u306e\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\u30b0\u30ed\u30fc\u30d0\u30eb\u62e1\u5f35\u6a5f\u80fd\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u5834\u5408\u3001RapidMiner\u3092\u8d77\u52d5\u3059\u308b\u5834\u5408\u306f\u7ba1\u7406\u8005\u7d75\u6a29\u9650\u30a2\u30ab\u30a6\u30f3\u30c8\u3067\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.manage_extensions.icon = piece2_edit.png - -gui.action.manage_extensions.label = \u62e1\u5f35\u6a5f\u80fd\u3092\u7ba1\u7406 -gui.action.manage_extensions.mne = M -gui.action.manage_extensions.icon = piece2_edit.png - -gui.action.uninstall_extension.label = -gui.action.uninstall_extension.icon = piece2_delete.png -gui.action.uninstall_extension.tip = \u3053\u306e\u62e1\u5f35\u6a5f\u80fd\u3067\u9078\u629e\u3057\u305f\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u5168\u3066\u524a\u9664 - -gui.dialog.confirm.really_uninstall_extension.title = \u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u78ba\u8a8d -gui.dialog.confirm.really_uninstall_extension.message = \u3053\u306e\u62e1\u5f35\u6a5f\u80fd{0}\u306b\u95a2\u9023\u3059\u308b\u5168\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u524a\u9664\u3055\u308c\u307e\u3059\u3002\u5b9f\u884c\u3057\u307e\u3059\u304b? - -gui.action.menu.about_extensions.label = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08\u307f\u62e1\u5f35\u6a5f\u80fd\u306b\u3064\u3044\u3066 -gui.action.menu.about_extensions.mne = E -gui.action.menu.about_extensions.icon = pieces.png - -gui.dialog.confirm.manage_extensions.restart.title = \u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002 -gui.dialog.confirm.manage_extensions.restart.message = \u5909\u66f4\u3092\u6709\u52b9\u5316\u3059\u308b\u70ba\u306bRapidMiner\u306e\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\u518d\u8d77\u52d5\u3057\u307e\u3059\u304b? - -gui.label.no_extensions_installed.label = \u62e1\u5f35\u6a5f\u80fd\u304c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30de\u30cd\u30fc\u30b8\u30e3\u3092\u4f7f\u7528\u3057\u3066\u62e1\u5f35\u6a5f\u80fd\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002 - -gui.dialog.error.error_uninstalling_extension.title = \u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u5931\u6557 -gui.dialog.error.error_uninstalling_extension.message = \u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u5931\u6557\u3002\u30b0\u30ed\u30fc\u30d0\u30eb\u3067\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u62e1\u5f35\u6a5f\u80fd\u304c\u5b58\u5728\u3057\u307e\u3059\u3002RapidMiner\u3092\u7ba1\u7406\u8005\u6a29\u9650\u3067\u5b9f\u884c\u3057\u3066\u3044\u308b\u4e8b\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -## LicenseConflictDialog - -gui.dialog.license_conflict.title = \u30e9\u30a4\u30bb\u30f3\u30b9\u9055\u53cd -gui.dialog.license_conflict.icon = error.png -gui.dialog.license_conflict.message = \u73fe\u5728\u4f7f\u7528\u4e2d\u306e\u62e1\u5f35\u6a5f\u80fd\u306f\u77db\u76fe\u3057\u305f\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002LGPL\u3067\u63d0\u4f9b\u3055\u308c\u3066\u3044\u308b\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306f\u3053\u306e\u88fd\u54c1\u3067\u306f\u5546\u7528\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.action.license_conflict_resolve_lgpl.label = \u5546\u7528\u62e1\u5f35\u6a5f\u80fd\u3092\u7121\u52b9\u5316 -gui.action.license_conflict_resolve_lgpl.mne = C -gui.action.license_conflict_resolve_comm.label = LGPL\u62e1\u5f35\u6a5f\u80fd\u3092\u7121\u52b9\u5316 -gui.action.license_conflict_resolve_comm.mne = L -gui.action.license_conflict_resolve_manually.label = \u624b\u52d5\u3067\u8a2d\u5b9a -gui.action.license_conflict_resolve_manually.mne = M - -## ConfirmLicenseDialog - -gui.dialog.confirm_license.title = \u5229\u7528\u898f\u7d04 -gui.dialog.confirm_license.message = {0}\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u70ba\u306b\u3001\u4ee5\u4e0b\u306e\u5229\u7528\u898f\u7d04\u306b\u540c\u610f\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -gui.action.accept_license.label = \u5229\u7528\u898f\u7d04\u306b\u540c\u610f\u3059\u308b\u3002 -gui.action.accept_license.mne = a -gui.action.accept_license.icon = ok.png -gui.action.accept_license.tip = \u30e9\u30a4\u30bb\u30f3\u30b9\u306b\u540c\u610f\u3057\u30d1\u30c3\u30b1\u30fc\u30b8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb -gui.action.reject_license.label = \u5229\u7528\u898f\u7d04\u306b\u540c\u610f\u3057\u306a\u3044\u3002 -gui.action.reject_license.mne = r -gui.action.reject_license.icon = delete.png -gui.action.accept_license.tip = \u30e9\u30a4\u30bb\u30f3\u30b9\u306b\u540c\u610f\u3092\u884c\u308f\u305a\u3001\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u30b9\u30ad\u30c3\u30d7\u3059\u308b\u3002 - -gui.action.skip_install.label = \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u306a\u3044 -gui.action.skip_install.mne = D -gui.action.skip_install.tip = \u3053\u306e\u62e1\u5f35\u6a5f\u80fd\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u306a\u3044\u3002 -gui.action.skip_install.icon = delete.png - -## PasswordDialog - -gui.dialog.authentication.title = \u6a29\u9650\u304c\u5fc5\u8981\u3067\u3059\u3002 -gui.dialog.authentication.icon = key.png -gui.dialog.authentication.message = \u30e6\u30fc\u30b6\u540d\u304a\u3088\u3073\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b21\u306e\u30a2\u30af\u30bb\u30b9\u306b\u5fc5\u8981\u3067\u3059\u3002{0} - -gui.label.authentication.username.label = \u30e6\u30fc\u30b6\u540d -gui.label.authentication.username.mne = U -gui.label.authentication.username.tip = {0}\u306b\u5bfe\u3059\u308b\u30e6\u30fc\u30b6\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.label.authentication.password.label = \u30d1\u30b9\u30ef\u30fc\u30c9 -gui.label.authentication.password.mne = P -gui.label.authentication.password.tip = {0}\u306b\u5bfe\u3059\u308b\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.action.authentication.remember.label = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u899a\u3048\u308b -gui.action.authentication.remember.mne = R -gui.action.authentication.remember.tip = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u899a\u3048\u308b\u3002\u3002 - -## UsageStatistics transmission / TransmissionDialog -gui.dialog.transmit_usage_statistics.title = \u5b9f\u884c\u30aa\u30da\u30ec\u30fc\u30bf\u5229\u7528\u7d71\u8a08 -gui.dialog.transmit_usage_statistics.icon = chart_column.png -gui.dialog.transmit_usage_statistics.message = RapidMiner\u958b\u767a\u30c1\u30fc\u30e0\u306f\u88fd\u54c1\u6539\u5584\u306e\u70ba\u306b\u30aa\u30da\u30ec\u30fc\u30bf\u5229\u7528\u7d71\u8a08\u306e\u9001\u4fe1\u3092\u8981\u6c42\u3057\u307e\u3059\u3002RapidMiner\u8005\u306fRapidMiner\u306e\u5229\u7528\u8005\u306e\u30d7\u30e9\u30a4\u30d0\u30b7\u30fc\u3092\u5c0a\u91cd\u3057\u307e\u3059\u3002\u500b\u4eba\u3092\u7279\u5b9a\u3067\u304d\u308b\u69d8\u306a\u60c5\u5831\u306f\u9001\u4fe1\u81f4\u3057\u307e\u305b\u3093\u3002\u9001\u4fe1\u3055\u308c\u308b\u5168\u3066\u306e\u60c5\u5831\u306f\u4ee5\u4e0b\u30c6\u30fc\u30d6\u30eb\u306b\u8a18\u8f09\u3057\u3066\u3044\u307e\u3059\u3002\u30c4\u30fc\u30eb\u30e1\u30cb\u30e5\u30fc\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u7d71\u8a08\u8868\u793a\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u4e8b\u306b\u3088\u308a\u3053\u306e\u60c5\u5831\u306f\u3044\u3064\u3067\u3082\u78ba\u8a8d\u53ef\u80fd\u3067\u3059\u3002\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u306a\u3044\u5834\u5408\u3067\u3082\u3001\u30b7\u30b9\u30c6\u30e0\u8a2d\u5b9a\u304b\u3089\u3044\u3064\u3067\u3082\u5909\u66f4\u53ef\u80fd\u3067\u3059\u3002 - -gui.action.never.label = \u4eca\u5f8c\u306f\u8868\u793a\u3057\u306a\u3044 -gui.action.never.icon = error.png -gui.action.never.mne = v -gui.action.never.tip = \u3053\u306e\u8cea\u554f\u3092\u8868\u793a\u3055\u305b\u306a\u3044\u3002 - -gui.action.always.label = \u4eca\u5f8c\u3082\u8868\u793a\u3059\u308b -gui.action.always.icon = ok.png -gui.action.always.mne = a -gui.action.always.tip = \u3053\u306e\u8cea\u554f\u3092\u4eca\u5f8c\u3082\u8868\u793a - -gui.action.no_later.label = \u5f8c\u3067\u8868\u793a\u3059\u308b -gui.action.no_later.icon = question.png -gui.action.no_later.mne = L -gui.action.no_later.tip = \u3053\u306e\u8cea\u554f\u3092\u5f8c\u3067\u8868\u793a - -gui.action.yes_later.label = Ok -gui.action.yes_later.icon = nav_refresh.png -gui.action.yes_later.mne = O -gui.action.yes_later.tip = \u3053\u306e\u8cea\u554f\u3092\u5f8c\u3067\u8868\u793a\u3059\u308b\u3002 - -gui.progress.transmit_usagestats.label = \u7d71\u8a08\u3092\u9001\u4fe1 - -## ProcessInfoScreen -gui.dialog.process_info.title = \u30d7\u30ed\u30bb\u30b9\u60c5\u5831 -gui.dialog.process_info.icon = information.png -gui.dialog.process_info.message = \u30d7\u30ed\u30bb\u30b9{0}\u306e\u60c5\u5831 - -## ToolTipDialog -gui.label.F3_for_focus.label = ''F3''\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u30d5\u30a9\u30fc\u30ab\u30b9 - -## QuickFixDialog -gui.dialog.quick_fix_dialog.title = \u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9 -gui.dialog.quick_fix_dialog.message = \u4ee5\u4e0b\u306e\u30ea\u30b9\u30c8\u304b\u3089\u9069\u5fdc\u3059\u308b\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u9078\u629e -gui.dialog.quick_fix_dialog.icon = first_aid.png - -gui.action.apply_quick_fix.label = \u9069\u5fdc -gui.action.apply_quick_fix.mne = A -gui.action.apply_quick_fix.icon = check.png -gui.action.apply_quick_fix.tip = \u9078\u629e\u3057\u305f\u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u9069\u5fdc - -gui.dialog.error.quickfix_failed.title = \u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u5931\u6557 -gui.dialog.error.quickfix_failed.message = \u30af\u30a4\u30c3\u30af\u30d5\u30a3\u30c3\u30af\u30b9\u5931\u6557: {0} - -## Anova Calculator -gui.dialog.anova_calculator.title = \u5206\u6563\u5206\u6790(ANOVA)\u8a08\u7b97 -gui.dialog.anova_calculator.message = \u5206\u6563\u5206\u6790(ANOVA)\u3092\u5b9f\u884c\u3092\u884c\u3044\u307e\u3059\u3002 -gui.dialog.anova_calculator.icon = scales.png - -gui.action.anova_calculator.clear.label = \u6d88\u53bb -gui.action.anova_calculator.clear.icon = erase.png -gui.action.anova_calculator.clear.mne = l -gui.action.anova_calculator.clear.tip = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u3092\u6d88\u53bb - -gui.action.anova_calculator.calculate.label = \u8a08\u7b97 -gui.action.anova_calculator.calculate.icon = scales.png -gui.action.anova_calculator.calculate.mne = t -gui.action.anova_calculator.calculate.tip = \u5206\u6563ANOVA\u8a08\u7b97\u3092\u5b9f\u884c - -gui.action.anova_calculator.add_row.label = \u884c\u8ffd\u52a0 -gui.action.anova_calculator.add_row.icon = table_selection_row_add.png -gui.action.anova_calculator.add_row.mne = A -gui.action.anova_calculator.add_row.tip = \u30c6\u30fc\u30d6\u30eb\u306b\u884c\u3092\u8ffd\u52a0 - -gui.action.anova_calculator.remove_row.label = \u884c\u524a\u9664 -gui.action.anova_calculator.remove_row.icon = table_selection_row_delete.png -gui.action.anova_calculator.remove_row.mne = R -gui.action.anova_calculator.remove_row.tip = \u9078\u629e\u3057\u305f\u884c\u3092\u524a\u9664 - -gui.dialog.results.anova.title = \u5206\u6563\u5206\u6790(ANOVA)\u7d50\u679c -gui.dialog.results.anova.message = \u4ee5\u4e0b\u3067\u5206\u6563\u5206\u6790(ANOVA)\u306e\u7d50\u679c\u3092\u78ba\u8a8d\u3067\u304d\u307e\u3059\u3002 - -gui.dialog.data_import_wizard.title = \u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8\u30a6\u30a3\u30b6\u30fc\u30c9 -gui.dialog.data_import_wizard.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u5229\u7528\u3057\u3066\u30c7\u30fc\u30bf\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 - -gui.dialog.data_import_wizard.icon = magic_wand.png - -## AnnotationsRenderer -gui.action.add_annotation.label = \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u8ffd\u52a0 -gui.action.add_annotation.mne = A -gui.action.add_annotation.tip = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u8ffd\u52a0 -gui.action.add_annotation.icon = table_selection_row_add.png - -gui.action.delete_annotation.label = \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u524a\u9664 -gui.action.delete_annotation.mne = D -gui.action.delete_annotation.tip = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304b\u3089\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u524a\u9664 -gui.action.delete_annotation.icon = table_selection_row_delete.png - -gui.dialog.input.select_annotation.title = \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u9078\u629e -gui.dialog.input.select_annotation.message = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u8ffd\u52a0\u3059\u308b\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u9078\u629e -gui.dialog.input.select_annotation.icon = table_selection_row_add.png - -## -gui.dialog.import_message.title = \u30a4\u30f3\u30dd\u30fc\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u51e6\u7406 -gui.dialog.import_message.icon = information.png -gui.dialog.import_message.message = \u4ee5\u4e0b\u3067\u30c7\u30fc\u30bf\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306b\u751f\u6210\u3059\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30ea\u30b9\u30c8\u3092\u78ba\u8a8d\u3067\u304d\u307e\u3059\u3002\u4ee5\u524d\u30d0\u30fc\u30b8\u30e7\u30f3\u306eRapidMiner\u304b\u3089\u73fe\u5728\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u5909\u66f4\u3057\u305f\u5834\u5408\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306b\u767a\u751f\u3057\u305f\u30a8\u30e9\u30fc\u3092\u4fee\u5fa9\u3044\u305f\u3057\u307e\u3059\u3002\u8d64\u304f\u30cf\u30a4\u30e9\u30a4\u30c8\u8868\u793a\u3055\u308c\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u4ee5\u5916\u306f\u7121\u8996\u3067\u304d\u307e\u3059\u3002 - -gui.dialog.operator_info.title = \u30aa\u30da\u30ec\u30fc\u30bf\u60c5\u5831 -gui.dialog.operator_info.icon = question.png - -gui.dialog.parameter.list.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u30ea\u30b9\u30c8\u7de8\u96c6 -gui.dialog.parameter.list.icon = notebook_edit.png - -gui.dialog.parameter.text.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u30c6\u30ad\u30b9\u30c8\u7de8\u96c6 -gui.dialog.parameter.text.icon = notebook_edit.png - -gui.dialog.parameter.sql.title = SQL\u30af\u30a8\u30ea\u69cb\u7bc9 -gui.dialog.parameter.sql.icon = code_edit.png - -gui.dialog.parameter.parameter_optimization.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u9078\u629e -gui.dialog.parameter.parameter_optimization.icon = form_edit.png - -gui.dialog.error.parameter_grid.title = \u7121\u52b9\u306a\u5024 -gui.dialog.error.parameter_grid.message = \u5165\u529b\u5024 ''{1}''\u306f\u7121\u52b9\u3067\u3059\u3002\u6570\u5024\u3082\u3057\u304f\u306f\u30de\u30af\u30ed\u306e\u307f{0}\u3068\u3057\u3066\u5165\u529b\u53ef\u80fd\u3067\u3059\u3002 - -gui.dialog.building_block.source.icon = user.png -gui.dialog.building_block.source.tip = \u30e6\u30fc\u30b6\u5b9a\u7fa9\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af - -gui.dialog.new_building_block.title = \u65b0\u898f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af - -gui.dialog.new_building_block.icon = box_open_new.png -gui.dialog.new_building_block.message = \u30d7\u30ed\u30bb\u30b9\u306b\u8ffd\u52a0\u3059\u308b\u30d6\u30ed\u30c3\u30af\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.manage_building_blocks.title = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u7ba1\u7406 -gui.dialog.manage_building_blocks.icon = box_open_edit.png -gui.dialog.manage_building_blocks.message = \u30e6\u30fc\u30b6\u306b\u3088\u308a\u5b9a\u7fa9\u3055\u308c\u305f\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u306e\u7de8\u96c6\u304c\u53ef\u80fd\u3067\u3059\u3002 -gui.action.delete_building_block.label = \u524a\u9664 -gui.action.delete_building_block.mne = D -gui.action.delete_building_block.icon = box_open_delete.png -gui.action.delete_building_block.tip = \u3053\u306e\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u524a\u9664 - -gui.dialog.save_building_block.title = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u4fdd\u5b58 -gui.dialog.save_building_block.icon = box_open_add.png -gui.dialog.save_building_block.message = \u3053\u306e\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u304a\u3088\u3073\u5b50\u8981\u7d20\u3092\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3068\u3057\u3066\u4fdd\u5b58 - -gui.label.save_building_block.name.label = \u540d\u524d -gui.label.save_building_block.name.tip = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u306e\u540d\u524d - -gui.label.save_building_block.description.label = \u660e\u7d30 -gui.label.save_building_block.description.tip = \u3053\u306e\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u306e\u660e\u7d30\u60c5\u5831 - -gui.dialog.error.save_building_block.name_used.title = \u4fdd\u5b58\u5931\u6557 -gui.dialog.error.save_building_block.name_used.message = \u540d\u524d ''{0}''\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5225\u540d\u3067\u4fdd\u5b58\u3092\u884c\u3046\u304b\u3001\u53e4\u3044\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u524a\u9664\u3057\u3066\u304b\u3089\u4fdd\u5b58\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.new_operator.title = \u65b0\u898f\u30aa\u30da\u30ec\u30fc\u30bf -gui.dialog.new_operator.icon = element_new.png -gui.dialog.new_operator.message = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u691c\u7d22\u3057\u307e\u3059\u3002 - -gui.dialog.jdbc_drivers.title = \u5229\u7528\u53ef\u80fd\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c9\u30e9\u30a4\u30d0 -#gui.dialog.jdbc_drivers.icon = data_network.png -gui.dialog.jdbc_drivers.message = \u73fe\u5728\u5229\u7528\u53ef\u80fd\u306aJDBC\u30c9\u30e9\u30a4\u30d0\u306f\u4ee5\u4e0b\u306b\u30ea\u30b9\u30c8\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u8ffd\u52a0\u3067\u30c9\u30e9\u30a4\u30d0\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3092\u884c\u3046\u5834\u5408\u306f\u3001jdbc_properties.xml\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u5909\u66f4\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8a73\u7d30\u306fRapidMiner Wiki\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -# Manage DB connections dialog -gui.dialog.manage_db_connections.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u7ba1\u7406 -#gui.dialog.manage_db_connections.icon = data_network_edit.png -gui.dialog.manage_db_connections.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u306e\u4f5c\u6210\u3001\u524a\u9664\u304c\u53ef\u80fd\u3067\u3059\u3002 - -gui.dialog.db_connection_advanced.title = \u63a5\u7d9a\u306e\u62e1\u5f35\u30d7\u30ed\u30d1\u30c6\u30a3 -#gui.dialog.db_connection_advanced.icon = data_gearwheel.png -gui.dialog.db_connection_advanced.message = \u9078\u629e\u3057\u305f\u63a5\u7d9a\u306e\u5168\u3066\u306e\u5229\u7528\u53ef\u80fd\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u4fee\u6b63\u3000\u8b66\u544a:\u4fee\u6b63\u5185\u5bb9\u3092\u628a\u63e1\u3057\u3066\u3044\u308b\u5834\u5408\u306e\u307f\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.db_connection_advanced.table.key.tooltip = \u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u540d\u79f0 -gui.dialog.db_connection_advanced.table.value.tooltip = \u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u5024 -gui.dialog.db_connection_advanced.table.override.tooltip = \u30c1\u30a7\u30c3\u30af\u7121\u3057\u306e\u5834\u5408\u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u304c\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002\u30c1\u30a7\u30c3\u30af\u3057\u305f\u5834\u5408\u306f\u6307\u5b9a\u3057\u305f\u30ab\u30b9\u30bf\u30e0\u5024\u304c\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002 - -gui.border.manage_db_connections.connections = \u5229\u7528\u53ef\u80fd\u63a5\u7d9a -gui.border.manage_db_connections.details = \u63a5\u7d9a\u8a73\u7d30 - -gui.label.manage_db_connections.name.label = \u540d\u524d -gui.label.manage_db_connections.system.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b7\u30b9\u30c6\u30e0 -gui.label.manage_db_connections.host.label = \u30db\u30b9\u30c8 -gui.label.manage_db_connections.port.label = \u30dd\u30fc\u30c8 -gui.label.manage_db_connections.database.label = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de -gui.label.manage_db_connections.user.label = \u30e6\u30fc\u30b6 -gui.label.manage_db_connections.password.label = \u30d1\u30b9\u30ef\u30fc\u30c9 -gui.label.manage_db_connections.url.label = URL - -#gui.dialog.manage_db_connections.connection_entry.icon = data_network.png -gui.dialog.manage_db_connections.connection_readonly_entry.icon = data_lock.png -gui.dialog.manage_db_connections.status.unknown.label = \u63a5\u7d9a\u30b9\u30c6\u30fc\u30bf\u30b9\u4e0d\u660e -#gui.dialog.manage_db_connections.status.unknown.icon = question.png -gui.dialog.manage_db_connections.status.ok.label = \u63a5\u7d9aok -#gui.dialog.manage_db_connections.status.ok.icon = ok.png -gui.dialog.manage_db_connections.status.error.label = \u63a5\u7d9a\u5931\u6557 -#gui.dialog.manage_db_connections.status.error.icon = error.png - -gui.action.manage_db_connections.new.label = \u65b0\u898f -gui.action.manage_db_connections.new.icon = data_connection_new.png -gui.action.manage_db_connections.new.tip = \u65b0\u898f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u4f5c\u6210 -gui.action.manage_db_connections.clone.label = \u8907\u88fd -#gui.action.manage_db_connections.clone.icon = data_copy.png -gui.action.manage_db_connections.clone.tip = \u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u8907\u88fd - -gui.action.manage_db_connections.advanced.label = \u62e1\u5f35\u8a2d\u5b9a -#gui.action.manage_db_connections.advanced.icon = data_gearwheel.png -gui.action.manage_db_connections.advanced.tip = \u62e1\u5f35\u63a5\u7d9a\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8a2d\u5b9a -gui.action.manage_db_connections.delete.label = \u524a\u9664 -#gui.action.manage_db_connections.delete.icon = data_network_delete.png -gui.action.manage_db_connections.delete.tip = \u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u524a\u9664 -gui.action.manage_db_connections.open.label = \u958b\u304f -#gui.action.manage_db_connections.open.icon = folder_open.png -gui.action.manage_db_connections.open.tip = \u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u958b\u304f - -gui.action.manage_db_connections.save.label = \u4fdd\u5b58 -gui.action.manage_db_connections.save.icon = floppy_disk.png -gui.action.manage_db_connections.save.tip = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u4fdd\u5b58 - -gui.action.manage_db_connections.test.label = \u30c6\u30b9\u30c8 -gui.action.manage_db_connections.test.icon = data_connection_unknown.png -gui.action.manage_db_connections.test.tip = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u30c6\u30b9\u30c8 - -gui.dialog.error.db_driver_not_found.title = {0} \u30c9\u30e9\u30a4\u30d0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.db_driver_not_found.message = {0}\u30c9\u30e9\u30a4\u30d0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u62e1\u5f35\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.manage_db_connections.missing.title = {0} \u304c\u5b58\u5728\u3057\u307e\u305b\u3093 -gui.dialog.error.manage_db_connections.missing.message = {0} \u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002\u30d5\u30a3\u30fc\u30eb\u30c9\u30d7\u30ed\u30d1\u30c6\u30a3\u306b\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.confirm.manage_db_connections.overwrite.title = \u63a5\u7d9a\u3092\u4e0a\u66f8\u304d -gui.dialog.confirm.manage_db_connections.overwrite.icon = data_connection_warning.png -gui.dialog.confirm.manage_db_connections.overwrite.message = \u540d\u524d{0}\u306e\u63a5\u7d9a\u306f\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b? - -gui.dialog.confirm.manage_db_connections.delete.title = \u63a5\u7d9a\u524a\u9664 -gui.dialog.confirm.manage_db_connections.delete.icon = data_connection_warning.png -gui.dialog.confirm.manage_db_connections.delete.message = \u30ea\u30b9\u30c8\u304b\u3089\u63a5\u7d9a{0}\u3092\u524a\u9664\u3057\u307e\u3059\u304b? -gui.dialog.error.db_connection_failed.title = \u63a5\u7d9a\u5931\u6557 -gui.dialog.error.db_connection_failed.message = \u30db\u30b9\u30c8''{1}'' (\u30dd\u30fc\u30c8: {2})\u3067\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9''{0}''\u3078\u63a5\u7d9a\u5931\u6557\u63a5\u7d9a\u8a2d\u5b9a\u306e\u78ba\u8a8d\u3092\u884c\u3063\u305f\u5f8c\u306b\u63a5\u7d9a\u6587\u5b57\u5217''{3}''\u3067\u518d\u691c\u8a3c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.db_connection_failed_url.title = \u63a5\u7d9a\u5931\u6557 -gui.dialog.error.db_connection_failed_url.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a''{0}''\u5931\u6557\u3002\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.db_connection_failed_simple.title = \u63a5\u7d9a\u5931\u6557 -gui.dialog.error.db_connection_failed_simple.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u5931\u6557: {0} - -gui.dialog.error.importwizard.unknown_error.title = \u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.importwizard.unknown_error.message = \u30a4\u30f3\u30dd\u30fc\u30c8\u5931\u6557\u3000\u7406\u7531: {0} - -gui.dialog.import_database_table.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.import_database_table.icon = inbox_into.png -gui.dialog.import_database_table.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u4f7f\u7528\u3057\u3066\u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 -gui.dialog.import_excel_sheet.title = Excel\u30b7\u30fc\u30c8\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.import_excel_sheet.icon = inbox_into.png -gui.dialog.import_excel_sheet.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u306f\u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057Excel\u30b7\u30fc\u30c8\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3044\u307e\u3059\u3002 -gui.dialog.import_csv_file.title = CSV\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.import_csv_file.icon = inbox_into.png -gui.dialog.import_csv_file.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3067\u306f\u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057CSV\u30d5\u30a1\u30a4\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 -gui.dialog.import_access_table.title = Access\u30c6\u30fc\u30d6\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.import_access_table.icon = inbox_into.png -gui.dialog.import_access_table.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3067\u306f\u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057Access\u30c6\u30fc\u30d6\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3044\u307e\u3059\u3002 - -gui.dialog.import_blob.title = \u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.import_blob.icon = inbox_into.png -gui.dialog.import_blob.message = \u3053\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3067\u306f\u65e2\u5b58\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057\u30d5\u30a1\u30a4\u30eb\u306e\u5185\u5bb9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 -gui.dialog.error.import_blob_failed.title = \u30a4\u30f3\u30dd\u30fc\u30c8\u5931\u6557 -gui.dialog.error.import_blob_failed.message = \u30d0\u30a4\u30ca\u30ea\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u306b\u5931\u6557: {0}. - -################################## -# DATA IMPORT WIZARDS -################################## -gui.progress.guessing_value_types.label = \u5024\u578b\u3092\u63a8\u6e2c -gui.progress.importing_data.label = \u30c7\u30fc\u30bf\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d -gui.progress.loading_data.label = \u30c7\u30fc\u30bf\u306e\u30ed\u30fc\u30c9\u4e2d -gui.action.importwizard.limited_preview.label = \u6700\u521d\u306e{0}\u884c\u306e\u307f\u30d7\u30ec\u30d3\u30e5 -gui.dialog.step.select_file.title = \u30d5\u30a1\u30a4\u30eb\u9078\u629e -gui.dialog.step.select_file.message = \u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3046\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u3060\u3055\u3044\u3002 -gui.dialog.step.specify_csv_parsing_options.title = \u89e3\u6790\u4e2d -gui.dialog.step.specify_csv_parsing_options.message = \u89e3\u6790\u5bfe\u8c61\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u5217\u306e\u5206\u5272\u65b9\u6cd5\u3092\u6307\u5b9a\u3057\u3066\u4e0b\u3055\u3044\u3002 -gui.dialog.step.value_type_selection.title = \u5024\u578b -gui.dialog.step.value_type_selection.message = \u6570\u5024\u3092\u3069\u306e\u3088\u3046\u306b\u89e3\u6790\u3059\u308b\u304b\u5b9a\u7fa9\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.step.select_attributes.title = \u5c5e\u6027\u6a29\u9650\u3001\u5024\u578b\u304a\u3088\u3073\u540d\u524d\u306e\u9078\u629e -gui.dialog.step.select_attributes.message = \u5c5e\u6027\u6a29\u9650\u3001\u5024\u578b\u3001\u540d\u524d\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\u3002\u7279\u5b9a\u306e\u5217\u3092\u542b\u3081\u306a\u3044\u5834\u5408\u306f\u975e\u9078\u629e\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u7279\u5225\u306a\u5217\u306flabel,ID,weight\u3068\u6307\u5b9a\u3057\u307e\u3059\u3002 - -gui.dialog.step.select_repository_location.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e\u3092\u9078\u629e -gui.dialog.step.select_repository_location.message = \u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.step.importwizard.excel_data_selection.title = \u30c7\u30fc\u30bf\u9078\u629e -gui.dialog.step.importwizard.excel_data_selection.message =Excel\u30d5\u30a1\u30a4\u30eb\u306f\u8907\u6570\u306e\u30b7\u30fc\u30c8\u3092\u6301\u3064\u306e\u3067\u3001RapidMiner\u306b\u5bfe\u3057\u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3046\u30b7\u30fc\u30c8\u3092\u4e00\u3064\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3046\u30bb\u30eb\u306e\u7bc4\u56f2\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002 -gui.dialog.step.importwizard.annotations.title = \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u5b9a\u7fa9 -gui.dialog.step.importwizard.annotations.message = RapidMiner\u3067\u306f\u3001\u5404\u5c5e\u6027\u306b\u5bfe\u3057\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u5b9a\u7fa9\u3059\u308b\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002\u6700\u3082\u91cd\u8981\u306a\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u306f\u5c5e\u6027\u306e\u540d\u524d\u306b\u306a\u308a\u307e\u3059\u3002\u4eee\u306b\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u5185\u306e\u884c\u306b\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u5b9a\u7fa9\u304c\u3042\u308b\u5834\u5408\u3001\u305d\u308c\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 - -gui.dialog.step.importwizard.metadata.title = \u30e1\u30bf\u30c7\u30fc\u30bf\u5b9a\u7fa9 -gui.dialog.step.importwizard.metadata.message = RapidMiner\u306f\u578b\u6307\u5b9a\u3055\u308c\u305f\u5c5e\u6027\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002\u30c7\u30fc\u30bf\u578b\u304a\u3088\u3073\u5c5e\u6027\u306e\u5b9a\u7fa9\u3092\u884c\u3046\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002RapidMiner\u306f\u5404\u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u6a29\u9650\u3092\u30ed\u30fc\u30eb\u306b\u5272\u308a\u5f53\u3066\u3066\u4f55\u306b\u4f7f\u7528\u3059\u308b\u306e\u304b\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002\u305d\u308c\u3089\u306e\u30ed\u30fc\u30eb\u306f\u3053\u3053\u3067\u5b9a\u7fa9\u3092\u884c\u3046\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002\u6700\u7d42\u7684\u306b\u5c5e\u6027\u306e\u540d\u524d\u306e\u5909\u66f4\u304a\u3088\u3073\u975e\u9078\u629e\u3092\u884c\u3046\u4e8b\u304c\u53ef\u80fd\u3067\u3059\u3002 - -gui.dialog.step.database_connection.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a -gui.dialog.step.database_connection.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.step.database_query.title = \u30af\u30a8\u30ea -gui.dialog.step.database_query.message = \u30c7\u30fc\u30bf\u30c6\u30fc\u30d6\u30eb\u3092\u4f5c\u6210\u3059\u308b\u30af\u30a8\u30ea\u3092\u69cb\u7bc9\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.label.loading_excel_sheets.label = Excel\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u3092\u8aad\u307f\u8fbc\u307f\u4e2d -gui.label.loading_excel_sheets.icon = 48/hourglass.png - -gui.dialog.build_sql_query.title = SQL\u30af\u30a8\u30ea\u30d3\u30eb\u30c0 -gui.dialog.build_sql_query.message = \u30c6\u30fc\u30d6\u30eb\u304a\u3088\u3073\u8981\u7d20\u306e\u9078\u629e\u306b\u3088\u308a\u30af\u30a8\u30ea\u3092\u69cb\u7bc9\u3057\u307e\u3059\u3002 - -gui.dialog.error.importwizard.io_error.title = \u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc -gui.dialog.error.importwizard.io_error.message = \u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306e\u30a8\u30e9\u30fc {0}: {1} - -gui.dialog.error.importwizard.error_creating_wizard.title = \u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc -gui.dialog.error.importwizard.error_creating_wizard.message = \u30a6\u30a3\u30b6\u30fc\u30c9\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f - -gui.dialog.tutorial.title = RapidMiner\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb -gui.dialog.tutorial.icon = book.png -gui.dialog.tutorial.message = RapidMiner\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u306f\u30b5\u30f3\u30d7\u30eb\u3092\u78ba\u8a8d\u3059\u308b\u4e8b\u306b\u3088\u308aRapidMiner\u306e\u5229\u7528\u65b9\u6cd5\u3092\u5b66\u7fd2\u3057\u307e\u3059\u3002\u4e0b\u306e\u30dc\u30bf\u30f3\u3092\u4f7f\u7528\u3057\u30c1\u30e5\u30fc\u30c8\u30ea\u30eb\u3092\u958b\u59cb\u3057\u307e\u3059\u3002 - -gui.dialog.check_for_updates.title = \u66f4\u65b0\u78ba\u8a8d -gui.dialog.check_for_updates.message = - -gui.dialog.message.no_updates_available.title = \u66f4\u65b0\u5185\u5bb9\u306f\u3042\u308a\u307e\u305b\u3093 -gui.dialog.message.no_updates_available.icon = download.png -gui.dialog.message.no_updates_available.message = RapidMiner\u306e\u65b0\u3057\u3044\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u7248\u306f\u3042\u308a\u307e\u305b\u3093 - -gui.dialog.message.update_available.title = \u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u5229\u7528\u53ef\u80fd -gui.dialog.message.update_available.icon = download.png -gui.dialog.message.update_available.message = RapidMiner\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u7248{0}\u304c\u5229\u7528\u53ef\u80fd\u3067\u3059\u3002http://www.rapidminer.com\u304b\u3089\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.attribute_editor.title = \u5c5e\u6027\u30a8\u30c7\u30a3\u30bf -gui.dialog.attribute_editor.icon = table_new.png -gui.action.menu.attribute_editor_file.label = \u30d5\u30a1\u30a4\u30eb -gui.action.menu.attribute_editor_file.mne = F -gui.action.menu.attribute_editor_file.tip = \u30d5\u30a1\u30a4\u30eb\u3092\u958b\u3044\u3066\u4fdd\u5b58 -gui.action.menu.attribute_editor_table.label = \u30c6\u30fc\u30d6\u30eb -gui.action.menu.attribute_editor_table.mne = T -gui.action.menu.attribute_editor_table.tip = \u30c6\u30fc\u30d6\u30eb\u30b5\u30a4\u30ba\u3092\u5909\u66f4\u3057\u3066\u578b\u3092\u63a8\u6e2c - -gui.action.attribute_editor.remove_column.label = \u5217\u524a\u9664 -gui.action.attribute_editor.remove_column.mne = C -gui.action.attribute_editor.remove_column.tip = \u73fe\u5728\u306e\u5217\u3092\u524a\u9664 -gui.action.attribute_editor.remove_column.icon = table_selection_column_delete.png - -gui.action.attribute_editor.remove_row.label = \u884c\u524a\u9664 -gui.action.attribute_editor.remove_row.mne = R -gui.action.attribute_editor.remove_row.tip = \u73fe\u5728\u306e\u884c\u3092\u524a\u9664 -gui.action.attribute_editor.remove_row.icon = table_selection_row_delete.png - -gui.action.attribute_editor.use_row_as_names.label = \u884c\u3092\u5c5e\u6027\u540d\u3068\u3057\u3066\u4f7f\u7528 -gui.action.attribute_editor.use_row_as_names.mne = N -gui.action.attribute_editor.use_row_as_names.tip = \u73fe\u5728\u306e\u884c\u3092\u5c5e\u6027\u540d\u3068\u3057\u3066\u4f7f\u7528\u3059\u308b\u3002\u4f8b\uff1aCSV\u30d5\u30a1\u30a4\u30eb -gui.action.attribute_editor.use_row_as_names.icon = table_selection_row_add.png - -gui.action.attribute_editor.guess_value_type.label = \u5024\u578b\u3092\u63a8\u6e2c -gui.action.attribute_editor.guess_value_type.mne = G -gui.action.attribute_editor.guess_value_type.tip = \u73fe\u5728\u306e\u5217\u3092\u5143\u306b\u5024\u578b\u3092\u63a8\u6e2c -gui.action.attribute_editor.guess_value_type.icon = question.png - -gui.action.attribute_editor.guess_all_value_types.label = \u5168\u3066\u306e\u5024\u578b\u3092\u63a8\u6e2c -gui.action.attribute_editor.guess_all_value_types.mne = A -gui.action.attribute_editor.guess_all_value_types.tip = \u73fe\u5728\u306e\u5217\u3092\u5143\u306b\u5024\u578b\u3092\uff08\u518d\u5ea6\uff09\u63a8\u6e2c -gui.action.attribute_editor.guess_all_value_types.icon = question.png - -gui.action.attribute_editor.open_aml_file.label = \u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f -gui.action.attribute_editor.open_aml_file.mne = O -gui.action.attribute_editor.open_aml_file.tip = \u65e2\u5b58\u306eXML\u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f(.aml) -gui.action.attribute_editor.open_aml_file.icon = code_add.png - -gui.action.attribute_editor.save_aml_file.label = \u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u3092\u4fdd\u5b58 -gui.action.attribute_editor.save_aml_file.mne = S -gui.action.attribute_editor.save_aml_file.tip = \u73fe\u5728\u306e\u5c5e\u6027\u30e1\u30bf\u30c7\u30fc\u30bf\u660e\u7d30\u3092XML\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58(.aml) -gui.action.attribute_editor.save_aml_file.icon = floppy_disk.png - -gui.action.attribute_editor.load_data.label = \u30c7\u30fc\u30bf\u8aad\u307f\u8fbc\u307f -gui.action.attribute_editor.load_data.mne = D -gui.action.attribute_editor.load_data.tip = \u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u3044\u3066\u5217\u3092\u8ffd\u52a0\u3059\u308b\u3002 -gui.action.attribute_editor.load_data.icon = data_add.png - -gui.action.attribute_editor.load_series_data.label = \u30b7\u30ea\u30fc\u30ba\u30c7\u30fc\u30bf\u3092\u30ed\u30fc\u30c9 -gui.action.attribute_editor.load_series_data.mne = e -gui.action.attribute_editor.load_series_data.tip = \u30b7\u30ea\u30fc\u30ba\u30c7\u30fc\u30bf\u3092\u958b\u3044\u3066\u5024\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002 -gui.action.attribute_editor.load_series_data.icon = window_oscillograph.png - -gui.action.attribute_editor.save_data_as.label = \u30c7\u30fc\u30bf\u3092\u5225\u540d\u4fdd\u5b58 -gui.action.attribute_editor.save_data_as.mne = v -gui.action.attribute_editor.save_data_as.tip = \u4e00\u3064\u306e\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3068\u3057\u3066\u4fdd\u5b58 -gui.action.attribute_editor.save_data_as.icon = data_floppy_disk.png - -gui.action.attribute_editor.clear.label = \u6d88\u53bb -gui.action.attribute_editor.clear.mne = C -gui.action.attribute_editor.clear.tip = \u30c6\u30fc\u30d6\u30eb\u3092\u6d88\u53bb -gui.action.attribute_editor.clear.icon = table_new.png - -gui.action.attribute_editor.close.label = \u9589\u3058\u308b -gui.action.attribute_editor.close.mne = l -gui.action.attribute_editor.close.tip = \u5c5e\u6027\u30a8\u30c7\u30a3\u30bf\u3092\u9589\u3058\u308b -gui.action.attribute_editor.close.icon = door_exit.png - -gui.dialog.file_chooser.import_process.title = \u30d7\u30ed\u30bb\u30b9\u30a4\u30f3\u30dd\u30fc\u30c8 -gui.dialog.file_chooser.import_process.icon = inbox_into.png -gui.dialog.file_chooser.import_process.message = \u30a4\u30f3\u30dd\u30fc\u30c8\u3092\u884c\u3046\u30d7\u30ed\u30bb\u30b9\u3092\u9078\u629e -gui.dialog.file_chooser.export_process.title = \u30d7\u30ed\u30bb\u30b9\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 -gui.dialog.file_chooser.export_process.icon = inbox_out.png -gui.dialog.file_chooser.export_process.message = \u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3092\u884c\u3046\u30d7\u30ed\u30bb\u30b9\u3092\u9078\u629e - -# DateFormatValueCellEditor -gui.action.dateformat.select_sample.label = \u30b5\u30f3\u30d7\u30eb\u8868\u793a -gui.action.dateformat.select_sample.icon = calendar.png -gui.action.dateformat.select_sample.tip = \u30c6\u30ad\u30b9\u30c8\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u5bfe\u3057\u30b5\u30f3\u30d7\u30eb\u306e\u5024\u3092\u30b3\u30d4\u30fc - -# AttributesPropertyDialog -gui.dialog.parameter.attributes.title = \u5c5e\u6027\u9078\u629e -gui.dialog.parameter.attributes.icon = document_text_view.png -gui.dialog.parameter.attributes.attributes.border = \u5c5e\u6027 -gui.dialog.parameter.attributes.selected_attributes.border = \u9078\u629e\u5c5e\u6027 - -# RegExpPropertyDialog -gui.dialog.parameter.regexp.title = \u6b63\u898f\u8868\u73fe\u7de8\u96c6 -gui.dialog.parameter.regexp.icon = document_text_view.png -gui.dialog.parameter.regexp.constructs.any_character = \u5168\u6587\u5b57 -gui.dialog.parameter.regexp.constructs.bracket_expression = \u62ec\u5f27\u5185\u306b\u542b\u307e\u308c\u308b\u5168\u6587\u5b57 - -gui.dialog.parameter.regexp.constructs.not_bracket_expression = \u62ec\u5f27\u5185\u306b\u542b\u307e\u308c\u306a\u3044\u5168\u6587\u5b57 -gui.dialog.parameter.regexp.constructs.capturing_group = \u30ad\u30e3\u30d7\u30c1\u30e3\u30fc\u30b0\u30eb\u30fc\u30d7 -gui.dialog.parameter.regexp.constructs.zero_one_quantifier = \u91cf\u8a18\u53f7\uff1a\u30bc\u30ed\u3082\u3057\u304f\u306f\u305d\u308c\u4ee5\u4e0a\u306e\u51e6\u7406\u8981\u7d20\u306e\u4e00\u3064 -gui.dialog.parameter.regexp.constructs.zero_more_quantifier = \u91cf\u8a18\u53f7:\u30bc\u30ed\u3082\u3057\u304f\u306f\u305d\u308c\u4ee5\u4e0a\u306e\u51e6\u7406\u8981\u7d20 -gui.dialog.parameter.regexp.constructs.one_more_quantifier = \u91cf\u8a18\u53f7\uff1a\u4e00\u3064\u3082\u3057\u304f\u306f\u305d\u308c\u4ee5\u4e0a\u306e\u51e6\u7406\u8981\u7d20 -gui.dialog.parameter.regexp.constructs.exact_quantifier = \u91cf\u8a18\u53f7\uff1an\u56de\u51e6\u7406\u3055\u308c\u308b\u8981\u7d20 -gui.dialog.parameter.regexp.constructs.min_quantifier = \u91cf\u8a18\u53f7\uff1a\u6700\u5c0f\u56de\u6570\u4ee5\u4e0a\u51e6\u7406\u3055\u308c\u308b\u8981\u7d20 -gui.dialog.parameter.regexp.constructs.min_max_quantifier = \u91cf\u8a18\u53f7\uff1a\u6700\u5c0f\u304a\u3088\u3073\u6700\u5927\u56de\u6570\u51e6\u7406\u3055\u308c\u308b\u8981\u7d20 -gui.dialog.parameter.regexp.constructs.disjunction = \u8981\u7d20\u3092\u5206\u96e2 -gui.dialog.parameter.regexp.shortcuts.arbitrary = \u8907\u6570\u306e\u4efb\u610f\u306e\u6587\u5b57 -gui.dialog.parameter.regexp.shortcuts.letter = \u5168\u6587\u5b57 -gui.dialog.parameter.regexp.shortcuts.lowercase_letter = \u5168\u3066\u306e\u5c0f\u6587\u5b57 -gui.dialog.parameter.regexp.shortcuts.uppercase_letter = \u5168\u3066\u306e\u5927\u6587\u5b57 -gui.dialog.parameter.regexp.shortcuts.digit = \u5168\u3066\u306e\u6574\u6570 -gui.dialog.parameter.regexp.shortcuts.word = \u5168\u3066\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8\u304a\u3088\u3073\u6574\u6570[a-zA-Z0-9] -gui.dialog.parameter.regexp.shortcuts.non_word = [^\\w] -gui.dialog.parameter.regexp.shortcuts.whitespace = \u30b9\u30da\u30fc\u30b9\u8a18\u53f7[ \\t\\r\\n\\v\\f] -gui.dialog.parameter.regexp.shortcuts.non_whitespace = \u975e\u30b9\u30da\u30fc\u30b9\u8a18\u53f7[^\\s] -gui.dialog.parameter.regexp.shortcuts.punctuation = \u53e5\u6fc1\u70b9 -gui.dialog.parameter.regexp.regular_expression.border = \u6b63\u898f\u8868\u73fe -gui.dialog.parameter.regexp.regular_expression.tip = \u6b63\u898f\u8868\u73fe -gui.dialog.parameter.regexp.regular_expression.constructs_table.title = \u30b3\u30f3\u30d1\u30a4\u30eb -gui.dialog.parameter.regexp.regular_expression.constructs_table.tip = \u6b63\u898f\u8868\u73fe\u3092\u30b3\u30f3\u30d1\u30a4\u30eb\u3002\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3092\u884c\u3044\u6b63\u898f\u8868\u73fe\u3092\u30b3\u30f3\u30d1\u30a4\u30eb -gui.dialog.parameter.regexp.regular_expression.constructs_table.construct_header = \u30b3\u30f3\u30d1\u30a4\u30eb -gui.dialog.parameter.regexp.regular_expression.constructs_table.description_header = \u660e\u7d30 -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.title = \u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.tip = \u6b63\u898f\u8868\u73fe\u306b\u5bfe\u3059\u308b\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3092\u3057\u3066\u6b63\u898f\u8868\u73fe\u3092\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u306b\u8ffd\u52a0 -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.shortcuts_header = \u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 -gui.dialog.parameter.regexp.regular_expression.shortcuts_table.description_header = \u660e\u7d30 -gui.dialog.parameter.regexp.item_shortcuts.border = \u30a2\u30a4\u30c6\u30e0\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 -gui.dialog.parameter.regexp.item_shortcuts.tip = \u6b63\u898f\u8868\u73fe\u3068\u3057\u3066\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u30a2\u30a4\u30c6\u30e0\u3002\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3092\u884c\u3044\u30a2\u30a4\u30c6\u30e0\u3092\u6b63\u898f\u8868\u73fe\u306b\u8ffd\u52a0 -gui.dialog.parameter.regexp.matched_items.border = \u5408\u81f4\u30a2\u30a4\u30c6\u30e0 -gui.dialog.parameter.regexp.matched_items.tip = \u6b63\u898f\u8868\u73fe\u306b\u5408\u81f4\u3057\u305f\u30a2\u30a4\u30c6\u30e0 -gui.dialog.parameter.regexp.error.label = \u6b63\u898f\u8868\u73fe\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\u6b63\u3057\u3044\u8868\u73fe\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.parameter.regexp.error.icon = error.png -gui.dialog.parameter.regexp.no_error.label = \u6b63\u898f\u8868\u73fe\u691c\u8a3c -gui.dialog.parameter.regexp.no_error.icon = ok.png - -# OperatorInfoScreen & OperatorInfoPanel panel -gui.label.input_ports.label = \u5165\u529b -#gui.label.input_ports.icon = 16/arrow_right.png -gui.label.input_ports.icon = 16/plug_next.png -gui.label.output_ports.label = \u51fa\u529b -#gui.label.output_ports.icon = 16/arrow_left.png -gui.label.output_ports.icon = 16/plug_previous.png -gui.label.inner_sources.label = \u5185\u90e8\u30bd\u30fc\u30b9 -#gui.label.inner_sources.icon = 16/arrow_left_green.png -gui.label.inner_sources.icon = 16/plug_previous.png -gui.label.inner_sinks.label = \u5185\u90e8\u30b7\u30f3\u30af -#gui.label.inner_sinks.icon = 16/arrow_right_green.png -gui.label.inner_sinks.icon = 16/plug_next.png - -gui.label.subprocesses.label = \u30b5\u30d6\u30d7\u30ed\u30bb\u30b9 -gui.label.subprocesses.icon = groups/16/meta.png - -#NewOperatorDialog -gui.label.new_op_dialog.search_text.label = \u691c\u7d22\u8a9e\u53e5: -gui.label.new_op_dialog.search_text.mne = S -gui.label.new_op_dialog.operator_group.label = \u30aa\u30da\u30ec\u30fc\u30bf\u30b0\u30eb\u30fc\u30d7: -gui.label.new_op_dialog.operator_group.mne = g -gui.label.new_op_dialog.required_input.label = \u5fc5\u9808\u5165\u529b: -gui.label.new_op_dialog.required_input.mne = i -gui.label.new_op_dialog.delivered_output.label = \u5f15\u6e21\u3057\u51fa\u529b: -gui.label.new_op_dialog.delivered_output.mne = o -gui.label.new_op_dialog.first_capability.label = 1\u756a\u76ee\u306e\u8a31\u5bb9\u91cf: -gui.label.new_op_dialog.first_capability.mne = c -gui.label.new_op_dialog.second_capability.label = 2\u756a\u76ee\u306e\u8a31\u5bb9\u91cf: -gui.label.new_op_dialog.second_capability.mne = a -gui.action.new_op_dialog.clear_search_field.label = -gui.action.new_op_dialog.clear_search_field.icon = delete.png -gui.action.new_op_dialog.clear_search_field.tip = \u691c\u7d22\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u6d88\u53bb -gui.dialog.new_op_dialog.matching_operators = \u5408\u81f4\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf -gui.dialog.new_op_dialog.operator_info = \u30aa\u30da\u30ec\u30fc\u30bf\u660e\u7d30: -gui.dialog.new_op_dialog.search_constraints = \u691c\u7d22\u5236\u7d04: - -gui.action.new_op_dialog.full_text_search.label = \u5168\u6587\u691c\u7d22 -gui.action.new_op_dialog.full_text_search.mne = F - -gui.tabs.operator_info_panel.description.label = \u660e\u7d30 -gui.tabs.operator_info_panel.description.icon = information.png -gui.tabs.operator_info_panel.description.mne = D -gui.tabs.operator_info_panel.description.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3059\u308b\u8a73\u7d30\u306a\u660e\u7d30 - -gui.tabs.operator_info_panel.capabilities.label = \u8a31\u5bb9\u7bc4\u56f2 -gui.tabs.operator_info_panel.capabilities.icon = briefcase2.png -gui.tabs.operator_info_panel.capabilities.mne = C -gui.tabs.operator_info_panel.capabilities.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u8a31\u5bb9\u7bc4\u56f2 - -gui.tabs.operator_info_panel.deprecation.label = \u975e\u63a8\u5968 -gui.tabs.operator_info_panel.deprecation.icon = sign_warning.png -gui.tabs.operator_info_panel.deprecation.mne = D -gui.tabs.operator_info_panel.deprecation.tip = \u975e\u63a8\u5968\u60c5\u5831 - -gui.tabs.operator_info_panel.ports.label = \u30dd\u30fc\u30c8 -gui.tabs.operator_info_panel.ports.icon = plug.png -gui.tabs.operator_info_panel.ports.mne = P -gui.tabs.operator_info_panel.ports.tip = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u5165\u529b\u304a\u3088\u3073\u51fa\u529b\u30dd\u30fc\u30c8 - -gui.tabs.operator_info_panel.subprocess.label = \u30b5\u30d6\u30d7\u30ed\u30bb\u30b9 ''{0}'' -gui.tabs.operator_info_panel.subprocess.icon = element_selection.png -gui.tabs.operator_info_panel.subprocess.tip = ''{0}''\u30aa\u30da\u30ec\u30fc\u30bf\u306e\u30b5\u30d6\u30d7\u30ed\u30bb\u30b9 - -#PropertyValueCellEditors -gui.action.edit_text.label = \u30c6\u30ad\u30b9\u30c8\u7de8\u96c6 -gui.action.edit_text.tip = \u30a8\u30c7\u30a3\u30bf\u5185\u3067\u30c6\u30ad\u30b9\u30c8\u3092\u7de8\u96c6 -gui.action.edit_text.icon = edit.png - -gui.action.build_sql.label = SQL\u30af\u30a8\u30ea\u69cb\u7bc9 -gui.action.build_sql.tip = SQL\u30af\u30a8\u30ea\u3092\u69cb\u7bc9\u3082\u3057\u304f\u306f\u7de8\u96c6 -gui.action.build_sql.icon = code_edit.png - -gui.action.choose_file.label = -gui.action.choose_file.tip = \u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e -gui.action.choose_file.icon = folder_open.png - -gui.action.edit_attributefile.label = -gui.action.edit_attributefile.tip = \u30a8\u30c7\u30a3\u30bf\u5185\u3067\u30c6\u30ad\u30b9\u30c8\u3092\u7de8\u96c6 - -gui.action.edit_attributefile.icon = table_edit.png - -gui.action.wizard.dataloading.label = \u30c7\u30fc\u30bf\u30ed\u30fc\u30c9\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u958b\u59cb -gui.action.wizard.dataloading.tip = \u30c7\u30fc\u30bf\u30ed\u30fc\u30c9\u3092\u884c\u3046\u70ba\u306e\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u958b\u59cb -gui.action.wizard.dataloading.icon = magic_wand.png - -gui.action.wizard.datawriting.label = \u30c7\u30fc\u30bf\u66f8\u304d\u8fbc\u307f\u30a6\u30a3\u30b6\u30fc\u30c9\u958b\u59cb -gui.action.wizard.datawriting.tip = \u30c7\u30fc\u30bf\u306e\u66f8\u304d\u8fbc\u307f\u3092\u884c\u3046\u30a6\u30a3\u30b6\u30fc\u30c9\u3092\u958b\u59cb -gui.action.wizard.datawriting.icon = magic_wand.png - -gui.action.wizard.configure.label = \u30d1\u30e9\u30e1\u30fc\u30bf\u8a2d\u5b9a\u7de8\u96c6 -gui.action.wizard.configure.tip = \u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u958b\u3044\u3066\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u7de8\u96c6 -gui.action.wizard.configure.icon = form_edit.png - -gui.action.attributes.label = \u5c5e\u6027\u9078\u629e -gui.action.attributes.tip = \u5c5e\u6027\u3092\u9078\u629e\u3059\u308b\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u958b\u304f - -gui.action.attributes.icon = document_text_view.png -gui.action.attributes.clear.label = -gui.action.attributes.clear.icon = delete.png -gui.action.attributes.clear.tip = \u691c\u7d22\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u6d88\u53bb - -gui.action.attributes.add.label = -gui.action.attributes.add.icon = add.png -gui.action.attributes.add.tip = \u9078\u629e\u53ef\u80fd\u306a\u8981\u7d20\u3092\u8ffd\u52a0 - -gui.action.attributes_select.label = -gui.action.attributes_select.tip = \u8981\u7d20\u3092\u9078\u629e -gui.action.attributes_select.icon = nav_right.png -gui.action.attributes_deselect.label = -gui.action.attributes_deselect.tip = \u8981\u7d20\u3092\u975e\u9078\u629e -gui.action.attributes_deselect.icon = nav_left.png - -gui.action.regexp.label = -gui.action.regexp.tip = \u6b63\u898f\u8868\u73fe\u3092\u7de8\u96c6\u3057\u30d7\u30ec\u30d3\u30e5 -gui.action.regexp.icon = document_text_view.png - -gui.action.list.label = \u30ea\u30b9\u30c8{0}\u3092\u7de8\u96c6 -gui.action.list.icon = notebook_edit.png - -gui.action.enumeration.label = \u5217\u6319\u578b\u30aa\u30d6\u30b8\u30a7\u30af\u30c8(Enum){0} -gui.action.enumeration.icon = notebook_edit.png - -#ListPropertyDialog -gui.action.list.add_row.label = \u5185\u5bb9\u5165\u529b -gui.action.list.add_row.mne = A -gui.action.list.add_row.tip = \u30ea\u30b9\u30c8\u306b\u5185\u5bb9\u3092\u8ffd\u52a0 -gui.action.list.add_row.icon = notebook_add.png - -gui.action.list.remove_row.label = \u5185\u5bb9\u524a\u9664 -gui.action.list.remove_row.mne = R -gui.action.list.remove_row.tip = \u9078\u629e\u3057\u305f\u5185\u5bb9\u3092\u30ea\u30b9\u30c8\u304b\u3089\u524a\u9664 -gui.action.list.remove_row.icon = notebook_delete.png - -#ExpressionPropertyDialog -gui.dialog.parameter.expression.title = \u5f0f\u3092\u7de8\u96c6 -gui.dialog.parameter.expression.icon = calculator.png - -#MatrixPropertyDialog -gui.dialog.parameter.matrix.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u30de\u30c8\u30ea\u30c3\u30af\u30b9\u3092\u7de8\u96c6 -gui.dialog.parameter.matrix.icon = table_edit.png - -gui.action.matrix.add_row.label = \u884c\u8ffd\u52a0 -gui.action.matrix.add_row.mne = A -gui.action.matrix.add_row.tip = \u884c\u3092\u30de\u30c8\u30ea\u30c3\u30af\u30b9\u306b\u8ffd\u52a0 -gui.action.matrix.add_row.icon = table_selection_row_add.png - -gui.action.matrix.remove_row.label = \u884c\u524a\u9664 -gui.action.matrix.remove_row.mne = R -gui.action.matrix.remove_row.tip = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u304b\u3089\u884c\u3092\u524a\u9664 -gui.action.matrix.remove_row.icon = table_selection_row_delete.png - -gui.action.matrix.add_column.label = \u5217\u8ffd\u52a0 -gui.action.matrix.add_column.mne = C -gui.action.matrix.add_column.tip = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u3078\u5217\u3092\u8ffd\u52a0 -gui.action.matrix.add_column.icon = table_selection_column_add.png - -gui.action.matrix.remove_column.label = \u5217\u524a\u9664 -gui.action.matrix.remove_column.mne = m -gui.action.matrix.remove_column.tip = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u304b\u3089\u5217\u3092\u524a\u9664 -gui.action.matrix.remove_column.icon = table_selection_column_delete.png - -gui.action.matrix.increase_size.label = \u30b5\u30a4\u30ba\u62e1\u5927 -gui.action.matrix.increase_size.mne = I -gui.action.matrix.increase_size.tip = \u884c\u304a\u3088\u3073\u5217\u3092\u30de\u30c8\u30ea\u30c3\u30af\u30b9\u306b\u8ffd\u52a0 - -gui.action.matrix.increase_size.icon = table_selection_row_add.png - -gui.action.matrix.decrease_size.label = \u30b5\u30a4\u30ba\u7e2e\u5c0f -gui.action.matrix.decrease_size.mne = D -gui.action.matrix.decrease_size.tip = \u884c\u304a\u3088\u3073\u5217\u3092\u30de\u30c8\u30ea\u30c3\u30af\u30b9\u304b\u3089\u524a\u9664 -gui.action.matrix.decrease_size.icon = table_selection_row_delete.png - -gui.action.matrix.edit.label = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u7de8\u96c6 -gui.action.matrix.edit.tip = \u30de\u30c8\u30ea\u30c3\u30af\u30b9\u3092\u7de8\u96c6 -gui.action.matrix.edit.icon = table_edit.png - -#ResultObjects -gui.action.save_result.label = \u4fdd\u5b58 -gui.action.save_result.mne = S -gui.action.save_result.icon = floppy_disk.png -gui.action.save_result.tip = \u7d50\u679c\u3092\u4fdd\u5b58 -gui.action.save_result.acc = ctrl S - -gui.action.save_image.label = \u753b\u50cf\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 -gui.action.save_image.tip = \u753b\u50cf\u3092\u4fdd\u5b58 -gui.action.save_image.mne = E -gui.action.save_image.icon = inbox_out.png - -gui.dialog.save_image.title = \u753b\u50cf\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 -gui.dialog.save_image.message = \u4fdd\u5b58\u5834\u6240\u304a\u3088\u3073\u5f62\u5f0f\u3092\u9078\u629e\u3057\u753b\u50cf\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u3042\u307e\u3059\u3002 -gui.dialog.save_image.icon = inbox_out.png - -gui.action.image_options.label = \u753b\u50cf\u30aa\u30d7\u30b7\u30e7\u30f3 -gui.action.image_options.tip = \u5f62\u5f0f\u3092\u6307\u5b9a\u3057\u3066\u8a2d\u5b9a -gui.action.image_options.icon = form_edit.png - -gui.dialog.image_options.title = \u753b\u50cf\u30aa\u30d7\u30b7\u30e7\u30f3 -gui.dialog.image_options.message = Configure {0}. -gui.dialog.image_options.icon = form_edit.png - - -#SettingsDialog -gui.dialog.settings.title = RapidMiner\u8a2d\u5b9a -gui.dialog.settings.icon = clipboard_check_edit.png - -gui.action.settings_apply.label = \u4fdd\u5b58 -gui.action.settings_apply.mne = S -gui.action.settings_apply.icon = floppy_disk.png -gui.action.settings_apply.tip = \u8a2d\u5b9a\u3092\u9069\u5fdc\u3057RapidMiner\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58 - -gui.action.settings_ok.label = \u9069\u5fdc -gui.action.settings_ok.icon = check.png -gui.action.settings_ok.mne = A -gui.action.settings_ok.tip = \u3053\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u306b\u8a2d\u5b9a\u3092\u9069\u5fdc - -#ErrorDialog -gui.dialog.error.title = \u30a8\u30e9\u30fc\u767a\u751f -gui.dialog.error.icon = error.png -gui.dialog.error.show_details.label = \u8a73\u7d30\u8868\u793a -gui.dialog.error.show_details.icon = document_text_view.png -gui.dialog.error.show_details.tip = \u30a8\u30e9\u30fc\u8a73\u7d30\u3092\u8868\u793a - -gui.action.show_offending_operator.label = \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u305f\u30aa\u30da\u30ec\u30fc\u30bf: {0} -gui.action.show_offending_operator.mne = o - -gui.dialog.error.entry_of_wrong_type.title = \u8aa4\u3063\u305f\u578b\u3092\u5165\u529b -gui.dialog.error.entry_of_wrong_type.message = \u9078\u629e\u30a8\u30f3\u30c8\u30ea{0}\u306f\u6b63\u3057\u3044\u578b\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.enter_email.title = \u30d5\u30a9\u30fc\u30e0\u304c\u672a\u5b8c\u6210 -gui.dialog.error.enter_email.message = E\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.enter_correct_email.title = \u672a\u5b8c\u6210\u30d5\u30a9\u30fc\u30e0 -gui.dialog.error.enter_correct_email.message = \u6709\u52b9\u306aE\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.enter_password.title = \u672a\u5b8c\u6210\u30d5\u30a9\u30fc\u30e0 -gui.dialog.error.enter_password.message = \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.enter_summary.title = \u672a\u5b8c\u6210\u30d5\u30a9\u30fc\u30e0 -gui.dialog.error.enter_summary.message = \u30a8\u30e9\u30fc\u8a73\u7d30\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.enter_descriptive_summary.title = \u672a\u5b8c\u6210\u30d5\u30a9\u30fc\u30e0 -gui.dialog.error.enter_descriptive_summary.message = \u30a8\u30e9\u30fc\u8a73\u7d30\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002(1\u5358\u8a9e\u306f\u8a73\u7d30\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002) -gui.dialog.error.enter_description.title = \u672a\u5b8c\u6210\u30d5\u30a9\u30fc\u30e0 - -gui.dialog.error.enter_description.message = \u30a8\u30e9\u30fc\u8a73\u7d30\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.bugreport_creation_failed.title = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u5931\u6557 -gui.dialog.error.bugreport_creation_failed.message = \u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_start_attr_editor.title = \u5c5e\u6027\u30a8\u30c7\u30a3\u30bf\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_start_attr_editor.message = \u5c5e\u6027\u30a8\u30c7\u30a3\u30bf\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3002: ExampleSource\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.must_contain_mean_real.title = \u30d5\u30a3\u30fc\u30eb\u30c9 'mean'\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.must_contain_mean_real.message = \u30d5\u30a3\u30fc\u30eb\u30c9 'mean'\u306fREAL\u578b\u306e\u6570\u5024\u3092\u542b\u3080\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -gui.dialog.error.must_contain_variance_real.title = \u30d5\u30a3\u30fc\u30eb\u30c9'variance'\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.must_contain_variance_real.message = \u30d5\u30a3\u30fc\u30eb\u30c9 'variance'\u306fREAL\u578b\u306e\u6570\u5024\u3092\u542b\u3080\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.must_contain_number_pos_integer.title = \u30d5\u30a3\u30fc\u30eb\u30c9'number'\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.must_contain_number_pos_integer.message = \u30d5\u30a3\u30fc\u30eb\u30c9'number'\u306f1\u4ee5\u4e0a\u306e\u6574\u6570\u5024\u304c\u5fc5\u8981\u3067\u3059\u3002 - -gui.dialog.error.sign_lvl_between_0_1.title = \u6709\u610f\u6c34\u6e96\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.sign_lvl_between_0_1.message = \u6709\u610f\u6c34\u6e96\u306f0\u304b\u30891\u307e\u3067\u306e\u5024\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.two_rows_to_calc_anova_test.title = \u5206\u6563\u5206\u6790\uff08ANOVA\uff09 -gui.dialog.error.two_rows_to_calc_anova_test.message = \u5206\u6563\u5206\u6790\uff08ANOVA\uff09\u3092\u884c\u3046\u70ba\u306b\u5c11\u306a\u304f\u3068\u30822\u3064\u4ee5\u4e0a\u306e\u884c\u3092\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.only_num_values_for_min_nr_of_items.title = \u6570\u5024\u578b\u306e\u307f\u4f7f\u7528\u53ef\u80fd\u3067\u304d\u307e\u3059\u3002 -gui.dialog.error.only_num_values_for_min_nr_of_items.message = \u30a2\u30a4\u30c6\u30e0\u306e\u6700\u5c0f\u6570\u6307\u5b9a\u306f\u6570\u5024\u306e\u307f\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 - -gui.dialog.error.enter_k_value.title = \u4e0d\u5b8c\u5168\u306a\u30d1\u30e9\u30e1\u30fc\u30bf -gui.dialog.error.enter_k_value.message = k\u306b\u5bfe\u3057\u6574\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.mandatory_parameters_missing.title = \u5fc5\u9808\u30d1\u30e9\u30e1\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.mandatory_parameters_missing.message = \u5168\u3066\u306e\u5fc5\u9808\u30d1\u30e9\u30e1\u30fc\u30bf\u306b\u5bfe\u3057\u5024\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.same_output_as_input_file.title = \u5165\u529b\u30d5\u30a1\u30a4\u30eb\u3068\u540c\u3058\u7269\u3092\u51fa\u529b\u306b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.same_output_as_input_file.message = \u5165\u529b\u30d5\u30a1\u30a4\u30eb\u3068\u540c\u3058\u7269\u3092\u51fa\u529b\u306b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002\uff1a\u4ed6\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_data_file_and_proper_settings.title = \u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u304c\u7121\u3044\u304b\u6b63\u3057\u3044\u8a2d\u5b9a\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_data_file_and_proper_settings.message = \u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u6307\u5b9a\u3057\u6b63\u3057\u3044\u8a2d\u5b9a\u3092\u884c\u3046\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - \u51e6\u7406\u3092\u4e2d\u65ad\u3059\u308b\u5834\u5408\u306f"\u30ad\u30e3\u30f3\u30bb\u30eb"\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_file_name_for_attr_desc.title = \u6307\u5b9a\u3055\u308c\u305f\u540d\u524d\u306e\u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 -gui.dialog.error.no_file_name_for_attr_desc.message = \u5c5e\u6027\u660e\u7d30\u30d5\u30a1\u30a4\u30eb\u306e\u540d\u524d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002- \u51e6\u7406\u3092\u4e2d\u65ad\u3059\u308b\u5834\u5408\u306f"\u30ad\u30e3\u30f3\u30bb\u30eb"\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_building_block_name.title = \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u540d\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_building_block_name.message = \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u540d\u524d\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_user_name.title = \u30e6\u30fc\u30b6\u540d\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_user_name.message = \u30e6\u30fc\u30b6\u540d\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_connection_data.title = \u63a5\u7d9a\u30c7\u30fc\u30bf\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_connection_data.message = \u5fc5\u8981\u306a\u63a5\u7d9a\u30c7\u30fc\u30bf\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_name_or_ip.title = \u30b5\u30fc\u30d0\u540d\u3082\u3057\u304f\u306fIP\u30a2\u30c9\u30ec\u30b9\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_name_or_ip.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b5\u30fc\u30d0\u540d\u3082\u3057\u304f\u306fIP\u30a2\u30c9\u30ec\u30b9\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_db_name.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 -gui.dialog.error.no_db_name.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.no_db_connection_and_settings.title = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u304a\u3088\u3073\u6b63\u3057\u3044\u8a2d\u5b9a\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.no_db_connection_and_settings.message = \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u304a\u3088\u3073\u6b63\u3057\u3044\u8a2d\u5b9a\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002- \u51e6\u7406\u3092\u4e2d\u65ad\u3059\u308b\u5834\u5408\u306f"\u30ad\u30e3\u30f3\u30bb\u30eb"\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.cannot_insert_operator.title = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u633f\u5165\u304c\u3067\u304d\u307e\u305b\u3093 -gui.dialog.error.cannot_insert_operator.message = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u633f\u5165\u304c\u3067\u304d\u307e\u305b\u3093\u3002: \u89aa\u8981\u7d20\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 - -gui.dialog.error.invalid_perspective_name.title = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u540d\u304c\u4e0d\u6b63\u3067\u3059\u3002 -gui.dialog.error.invalid_perspective_name.message = \u30d1\u30fc\u30b9\u30da\u30af\u30c6\u30a3\u30d6\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002: \u6b63\u3057\u3044\u540d\u524d\u3092\u6307\u5b9a\u3057\u3066\u4e0b\u3060\u3055\u3044\u3002 - -gui.dialog.error.illegal_url.title = \u7121\u52b9\u306aURL -gui.dialog.error.illegal_url.message = \u7121\u52b9\u306aURL - -gui.dialog.error.run_proc_remote.title = \u30ea\u30e2\u30fc\u30c8\u3067\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.run_proc_remote.message = \u30ea\u30e2\u30fc\u30c8\u3067\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.default_workspace.title =\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f7f\u7528 -gui.dialog.error.default_workspace.message = RapidMiner\u306f\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u5fc5\u8981\u3067\u3059\u3002\u30d5\u30a1\u30a4\u30eb\u30e1\u30cb\u30e5\u3067\u6307\u5b9a\u53ef\u80fd\u3067\u3059\u3002 - -gui.dialog.error.op_replaced_failed_connections_restored.title = \u30aa\u30da\u30ec\u30fc\u30bf\u7f6e\u63db -gui.dialog.error.op_replaced_failed_connections_restored.message = \u30aa\u30da\u30ec\u30fc\u30bf\u304c\u7f6e\u63db\u3055\u308c\u307e\u3057\u305f\u304c\u3001{0}\u63a5\u7d9a\u306f\u81ea\u52d5\u7684\u306b\u5fa9\u5143\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 - -gui.dialog.error.proc_failed_out_of_mem.title = \u51e6\u7406\u5931\u6557 -gui.dialog.error.proc_failed_out_of_mem.message = \u3053\u306e\u51e6\u7406\u306b\u5bfe\u3059\u308b\u5229\u7528\u30e1\u30e2\u30ea\u306f\u8a2d\u5b9a\u3088\u308a\u591a\u304f\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\u3053\u306e\u307e\u307e\u306e\u72b6\u614b\u3067\u4fdd\u7ba1\u3057\u5927\u91cf\u30e1\u30e2\u30ea\u3092\u642d\u8f09\u3057\u3066\u3044\u308b\u30de\u30b7\u30f3\u3092\u5229\u7528\u3059\u308b\u304b\u30b5\u30f3\u30d7\u30ea\u30f3\u30b0\u30aa\u30da\u30ec\u30fc\u30bf\u3001\u30d7\u30ed\u30bb\u30b9\u6700\u9069\u5316\u30aa\u30da\u30ec\u30fc\u30bf\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u4e0a\u3067\u5b9f\u884c\u3092\u884c\u3046\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.proc_failed_without_obv_reason.title = \u51e6\u7406\u5931\u6557 -gui.dialog.error.proc_failed_without_obv_reason.message = \u8a2d\u5b9a\u3067\u306f\u9855\u8457\u306a\u30a8\u30e9\u30fc\u304c\u78ba\u8a8d\u3067\u304d\u307e\u305b\u3093\u304c\u30ed\u30b0\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.proc_failed_errors.title = \u51e6\u7406\u5931\u6557 -gui.dialog.error.proc_failed_errors.message = \u8a2d\u5b9a\u5185\u5bb9\u306b\u30a8\u30e9\u30fc\u304c\u78ba\u8a8d\u3055\u308c\u307e\u3057\u305f\u306e\u3067\u3001\u30ed\u30b0\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u5185\u5bb9\u3068\u5408\u308f\u305b\u3066\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.op_deleted.title = \u30aa\u30da\u30ec\u30fc\u30bf\u524a\u9664 -gui.dialog.error.op_deleted.message = \u30aa\u30da\u30ec\u30fc\u30bf {0}\u306f\u30d7\u30ed\u30bb\u30b9\u304b\u3089\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 - -gui.dialog.error.som.only_nr_width.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u9593\u9055\u3044 -gui.dialog.error.som.only_nr_width.message = SOM\u6a2a\u5e45\u306f\u6570\u5024\u306e\u307f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u3059\u3002 - -gui.dialog.error.som.only_nr_height.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u9593\u9055\u3044 -gui.dialog.error.som.only_nr_height.message = SOM\u7e26\u5e45\u306f\u6570\u5024\u306e\u307f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u3059\u3002 - -gui.dialog.error.som.only_nr_radius.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u9593\u9055\u3044 -gui.dialog.error.som.only_nr_radius.message = \u7bc4\u56f2\u306f\u6570\u5024\u306e\u307f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u3059\u3002 - -gui.dialog.error.som.only_nr_rounds.title = \u30d1\u30e9\u30e1\u30fc\u30bf\u9593\u9055\u3044 -gui.dialog.error.som.only_nr_rounds.message = \u5b66\u7fd2\u56de\u6570\u306f\u6570\u5024\u306e\u307f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u3059\u3002 - -gui.dialog.error.cannot_retrieve_obj_inf.title = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8{0}\u304b\u3089\u60c5\u5831\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_retrieve_obj_inf.message = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8{0}\u304b\u3089\u60c5\u5831\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.no_visual_for_obj.title = ID{0}\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u5bfe\u3057\u3066\u30d3\u30b8\u30e5\u30a2\u30eb\u6a5f\u80fd\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.no_visual_for_obj.message = ID{0}\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u5bfe\u3057\u3066\u30d3\u30b8\u30e5\u30a2\u30eb\u6a5f\u80fd\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_es_to_file.title = \u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u5bfe\u3057\u3066ExampleSet\u3092\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_es_to_file.message = \u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u5bfe\u3057\u3066ExampleSet\u3092\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_instantiate_building_block.title =\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u51fa\u6765\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_instantiate_building_block.message =\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u51fa\u6765\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_create_building_block.title =\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_building_block.message =\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.printer_error.title = \u30d7\u30ea\u30f3\u30bf\u30a8\u30e9\u30fc -gui.dialog.error.printer_error.message = \u30d7\u30ea\u30f3\u30bf\u30a8\u30e9\u30fc - -gui.dialog.error.malformed_rep_location.title = \u6574\u5f62\u3055\u308c\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e ''{0}'' -gui.dialog.error.malformed_rep_location.message = \u6574\u5f62\u3055\u308c\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u4f4d\u7f6e ''{0}'' - -gui.dialog.error.cannot_store_obj_at_location.title = ''{0}''\u3067\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u4fdd\u5b58\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_store_obj_at_location.message = ''{0}''\u3067\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u4fdd\u5b58\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_obj_from_location.title = ''{0}''\u3067\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30ed\u30fc\u30c9\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_load_obj_from_location.message = ''{0}''\u3067\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30ed\u30fc\u30c9\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_calc_anova.title = \u5206\u6563\u5206\u6790(ANOVA)\u306e\u8a08\u7b97\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_calc_anova.message = \u5206\u6563\u5206\u6790(ANOVA)\u306e\u8a08\u7b97\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_find_url.title = ''{0}''\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_find_url.message = ''{0}''\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_calc_statistical_significance.title =\u6709\u610f\u6c34\u6e96\u3092\u8a08\u7b97\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_calc_statistical_significance.message =\u6709\u610f\u6c34\u6e96\u3092\u8a08\u7b97\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_open_browser.title = \u30d6\u30e9\u30a6\u30b6\u3092\u958b\u3051\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_open_browser.message = \u30d6\u30e9\u30a6\u30b6\u3092\u958b\u3051\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_building_block_file.title = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_building_block_file.message =\u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_save_properties.title =\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_save_properties.message =\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_instantiate_building_block.title = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u3067\u304d\u307e\u305b\u3093 -gui.dialog.error.cannot_instantiate_building_block.message = \u30d3\u30eb\u30c7\u30a3\u30f3\u30b0\u30d6\u30ed\u30c3\u30af''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u3067\u304d\u307e\u305b\u3093 - -gui.dialog.error.cannot_write_to_file.title = \u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_to_file.message = \u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_to_file_0.title = \u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_to_file_0.message = \u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_rename_entry.title = \u540d\u524d\u306e\u5909\u66f4\u5931\u6557 -gui.dialog.error.cannot_rename_entry.message = \u540d\u524d\u3092''{0}''\u304b\u3089''{1}''\u3078\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_store_process_in_repository.title = \u30d7\u30ed\u30bb\u30b9\u306e\u4fdd\u5b58\u306b\u5931\u6557 -gui.dialog.error.cannot_store_process_in_repository.message = \u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u5bfe\u3057\u3066\u30d7\u30ed\u30bb\u30b9''{0}''\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_create_operator.title = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u4f5c\u6210\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_operator.message = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u4f5c\u6210\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.error_during_logging.title = \u30ed\u30b0\u51fa\u529b\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.error_during_logging.message = \u30ed\u30b0\u51fa\u529b\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.cannot_insert_operator.title = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u633f\u5165\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_insert_operator.message = \u30aa\u30da\u30ec\u30fc\u30bf\u306e\u633f\u5165\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.es_conf_wizard_was_not_able_to_write_file.title = ExampleSource\u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9\u304b\u3089\u30c7\u30fc\u30bf\u306e\u66f8\u304d\u8fbc\u307f\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -gui.dialog.error.es_conf_wizard_was_not_able_to_write_file.message = ExampleSource\u8a2d\u5b9a\u30a6\u30a3\u30b6\u30fc\u30c9\u304b\u3089\u30c7\u30fc\u30bf\u306e\u66f8\u304d\u8fbc\u307f\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 - -gui.dialog.error.cannot_guess_value_types.title = \u5024\u578b\u3092\u63a8\u6e2c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_guess_value_types.message = \u5024\u578b\u3092\u63a8\u6e2c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_close_stream_to_data_file.title = \u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u306e\u30b9\u30c8\u30ea\u30fc\u30e0\u3092\u9589\u3058\u308c\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_close_stream_to_data_file.message = \u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u306e\u30b9\u30c8\u30ea\u30fc\u30e0\u3092\u9589\u3058\u308c\u307e\u305b\u3093\u3002 - -gui.dialog.error.while_loading.title = ''{0}''\u306e\u30ed\u30fc\u30c9\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.while_loading.message = \u4f4d\u7f6e''{0}''\u304b\u3089\u30ed\u30fc\u30c9\u4e2d\u306b\u30a8\u30e9\u30fc : {1} - -gui.dialog.error.no_data_or_process.title = \u4e0d\u6b63\u306a\u5165\u529b\u30bf\u30a4\u30d7 -gui.dialog.error.no_data_or_process.message = \u30d7\u30ed\u30bb\u30b9\u3082\u3057\u304f\u306f\u3001\u30c7\u30fc\u30bf\u5165\u529b\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.please_enter_non_empty_name.title = \u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -gui.dialog.error.please_enter_non_empty_name.message = \u30d7\u30ed\u30bb\u30b9\u306e\u4fdd\u5b58\u306e\u70ba\u306b\u540d\u524d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.while_following_link.title = \u30ea\u30f3\u30af\u306e\u30d5\u30a9\u30ed\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.while_following_link.message = \u30ea\u30f3\u30af\u306e\u30d5\u30a9\u30ed\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.cannot_create_process_embedder.title = \u30d7\u30ed\u30bb\u30b9\u30a8\u30f3\u30d9\u30c7\u30a3\u30bf\u306e\u4f5c\u6210\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_process_embedder.message = \u30d7\u30ed\u30bb\u30b9\u30a8\u30f3\u30d9\u30c7\u30a3\u30bf\u306e\u4f5c\u6210\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_create_reader_for_file.title = \u30d5\u30a1\u30a4\u30eb''{0}}''\u306e\u30ea\u30fc\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_reader_for_file.message =\u30d5\u30a1\u30a4\u30eb''{0}}''\u306e\u30ea\u30fc\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_attr_weights_from_file.title = \u30d5\u30a1\u30a4\u30eb''{0}''\u304b\u3089\u5c5e\u6027\u306e\u91cd\u307f\u4ed8\u304d\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_attr_weights_from_file.message =\u30d5\u30a1\u30a4\u30eb''{0}''\u304b\u3089\u5c5e\u6027\u306e\u91cd\u307f\u4ed8\u304d\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_attr_weights_to_file.title = \u5c5e\u6027\u306e\u91cd\u307f\u3092\u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_attr_weights_to_file.message =\u5c5e\u6027\u306e\u91cd\u307f\u3092\u30d5\u30a1\u30a4\u30eb''{0}''\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_create_repository.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_repository.message = \u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.error_connecting_to_server.title = \u30b5\u30fc\u30d0\u63a5\u7d9a\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.error_connecting_to_server.message = \u30b5\u30fc\u30d0\u63a5\u7d9a\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.cannot_parse_date.title = \u65e5\u4ed8\u3092\u8cbc\u308a\u4ed8\u3051\u3089\u308c\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_parse_date.message = \u65e5\u4ed8\u3092\u8cbc\u308a\u4ed8\u3051\u3089\u308c\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_attr_descr.title = \u5c5e\u6027\u660e\u7d30\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_load_attr_descr.message = \u5c5e\u6027\u660e\u7d30\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_instantiate.title = ''{0}''\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_instantiate.message = ''{0}''\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_data.title = \u30c7\u30fc\u30bf\u30ed\u30fc\u30c9\u304c\u51fa\u6765\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_load_data.message = \u30c7\u30fc\u30bf\u30ed\u30fc\u30c9\u304c\u51fa\u6765\u307e\u305b\u3093\u3002 - -gui.dialog.error.process_failed_simple.title = \u30d7\u30ed\u30bb\u30b9\u5931\u6557 -gui.dialog.error.process_failed_simple.message = \u30d7\u30ed\u30bb\u30b9\u5931\u6557 - -gui.dialog.error.process_failed_user_error.title = \u30d7\u30ed\u30bb\u30b9\u5931\u6557 -gui.dialog.error.process_failed_user_error.message =

    {0}

    {1} - -gui.dialog.error.cannot_create_folder.title = \u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_create_folder.message = \u30d5\u30a9\u30eb\u30c0 ''{0}''\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_refresh_folder.title = \u30d5\u30a9\u30eb\u30c0\u306e\u66f4\u65b0\u304c\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_refresh_folder.message = \u30d5\u30a9\u30eb\u30c0\u306e\u66f4\u65b0\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_fetch_data_from_repository.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u304b\u3089\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_fetch_data_from_repository.message =\u30ea\u30dd\u30b8\u30c8\u30ea\u304b\u3089\u30c7\u30fc\u30bf\u306e\u53d6\u5f97\u304c\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.error_fetching_folder_contents_from_server.title = \u30b5\u30fc\u30d0\u304b\u3089\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.error_fetching_folder_contents_from_server.message = \u30b5\u30fc\u30d0\u304b\u3089\u30d5\u30a9\u30eb\u30c0\u306e\u5185\u5bb9\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u3002\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u30b5\u30fc\u30d0\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u304a\u3088\u3073\u30ea\u30b9\u30a8\u30b9\u30c8\u6570\u904e\u591a\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u57fa\u672c\u8a8d\u8a3c\u306b\u5bfe\u3059\u308b\u30e6\u30fc\u30b6\u540d/\u30d1\u30b9\u30ef\u30fc\u30c9\u3067\u5931\u6557\u3057\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 - -gui.dialog.error.cannot_start_process.title = \u30d7\u30ed\u30bb\u30b9\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_start_process.message = \u30d7\u30ed\u30bb\u30b9\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_save_process.title = \u30d7\u30ed\u30bb\u30b9\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_save_process.message = \u30d7\u30ed\u30bb\u30b9\u3092 ''{0}''\u306b\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002: {1} - -gui.dialog.error.cannot_access_repository.title = \u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u30a2\u30af\u30bb\u30b9\u51fa\u6765\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_access_repository.message = \u6307\u5b9a\u3057\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_data_into_file.title = \u30c7\u30fc\u30bf\u3092\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_data_into_file.message = \u30c7\u30fc\u30bf\u3092\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_log_file.title = \u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_log_file.message =\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u306b\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_write_history_file.title = \u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_write_history_file.message = \u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3002 - -gui.dialog.error.while_changing_process.title = \u30d7\u30ed\u30bb\u30b9\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.error.while_changing_process.message = \u30d7\u30ed\u30bb\u30b9\u5909\u66f4\u4e2d\u306b\u30a8\u30e9\u30fc - -gui.dialog.error.cannot_find_url.title = ''{0}''\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_find_url.message = ''{0}''\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_instantiate_plotter.title = \u30d7\u30ed\u30c3\u30bf''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_instantiate_plotter.message = \u30d7\u30ed\u30c3\u30bf''{0}''\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_re_write_data.title = \u30c7\u30fc\u30bf\u3092\u518d\u66f8\u304d\u8fbc\u307f\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_re_write_data.message = \u30c7\u30fc\u30bf\u3092\u518d\u66f8\u304d\u8fbc\u307f\u3067\u304d\u307e\u305b\u3093\u3002 - -gui.dialog.error.cannot_load_tutorial_file.title = \u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u30d5\u30a1\u30a4\u30eb''{0}''\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 -gui.dialog.error.cannot_load_tutorial_file.message = \u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u30d5\u30a1\u30a4\u30eb''{0}''\u3092\u30ed\u30fc\u30c9\u51fa\u6765\u307e\u305b\u3093\u3002 - -gui.dialog.error.error_in_paste.title = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u8cbc\u308a\u4ed8\u3051\u308c\u307e\u305b\u3093\u3002 -gui.dialog.error.error_in_paste.message = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u30ac\u30ea\u4ed8\u3051\u308c\u307e\u305b\u3093\u3002: {0} - -#End ErrorDialog - -# BugReport -gui.action.send_bugreport.label = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u9001\u4fe1 -gui.action.send_bugreport.mne = S -gui.action.send_bugreport.icon = bug_error.png -gui.action.send_bugreport.tip = RapidMiner\u958b\u767a\u30c1\u30fc\u30e0\u306b\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1 - -gui.dialog.confirm.send_bugreport.confirm.title = \u3088\u308d\u3057\u3044\u3067\u3059\u304b? -gui.dialog.confirm.send_bugreport.confirm.message = \u3053\u306e\u30d0\u30b0\u306f\u5e38\u306bRapidMiner\u306e\u4f7f\u7528\u65b9\u6cd5\u306b\u8d77\u56e0\u3057\u3066\u3044\u307e\u3059\u3002 - -gui.dialog.message.send_bugreport.import_operator_message.title = \u60c5\u5831 -gui.dialog.message.send_bugreport.import_operator_message.message = \u3082\u3057\u3053\u306e\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u304c\u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u306b\u95a2\u4fc2\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u3001\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u6dfb\u4ed8\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.message.send_bugreport.import_operator_message.icon = sign_warning.png -gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.title = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306e\u91cd\u8907\u3092\u9632\u304e\u307e\u3059\u3002 -gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.message = \u30d6\u30e9\u30a6\u30b6\u3092\u958b\u3044\u3066\u540c\u69d8\u306e\u30d0\u30b0\u304c\u65e2\u306b\u5831\u544a\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002\u5f93\u3063\u3066\u3001\u5831\u544a\u3055\u308c\u3066\u3044\u306a\u3044\u30d0\u30b0\u306e\u307f\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.confirm.send_bugreport.check_browser_for_duplicates.icon = sign_warning.png - -gui.dialog.send_bugreport.title = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u9001\u4fe1 -gui.dialog.send_bugreport.icon = bug_error.png -gui.dialog.send_bugreport.message = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1\u3059\u308b\u70ba\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3002 \u5927\u534a\u306e\u5fc5\u8981\u30c7\u30fc\u30bf\u3092\u53ce\u96c6\u3057\u554f\u984c\u3092\u7cbe\u67fb\u3044\u305f\u3057\u307e\u3059\u3002(\u4f8b\uff1a\u30b9\u30bf\u30c3\u30af\u30c8\u30ec\u30fc\u30b9\u3001\u30d7\u30ed\u30bb\u30b9\u3001\u30b7\u30b9\u30c6\u30e0\u30d7\u30ed\u30d1\u30c6\u30a3)\u30d0\u30b0\u304c\u30d7\u30ed\u30bb\u30b9\u306b\u95a2\u9023\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u3001"\u30d7\u30ed\u30bb\u30b9\u6dfb\u4ed8"\u3092\u975e\u9078\u629e\u306b\u3057\u307e\u3059\u3002"\u30b7\u30b9\u30c6\u30e0\u30d7\u30ed\u30d1\u30c6\u30a3\u6dfb\u4ed8"\u3082\u540c\u69d8\u306b\u975e\u9078\u629e\u306b\u51fa\u6765\u307e\u3059\u304c\u3001\u30d0\u30b0\u89e3\u6d88\u306b\u5bfe\u3057\u91cd\u8981\u306a\u60c5\u5831\u3092\u4fdd\u6301\u3057\u3066\u3044\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306e\u6700\u65b0\u60c5\u5831\u306f"\u30ec\u30dd\u30fc\u30c8\u95b2\u89a7"\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u78ba\u8a8d\u3059\u308b\u4e8b\u304c\u3067\u304d\u307e\u3059\u3002\u8ffd\u52a0\u3067\u30d5\u30a1\u30a4\u30eb\u306e\u6dfb\u4ed8\u3092\u884c\u3046\u5834\u5408\u3001"\u30d5\u30a1\u30a4\u30eb\u6dfb\u4ed8"\u30dc\u30bf\u30f3\u3092\u62bc\u4e0b\u3057\u307e\u3059\u3002 - -gui.dialog.send_bugreport_info.title = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u6982\u8981 -gui.dialog.send_bugreport_info.icon = bug_error.png -gui.dialog.send_bugreport_info.message = \u30d0\u30b0\u30c8\u30e9\u30c3\u30ab\u30fc\u306b\u9001\u4fe1\u3059\u308b\u5185\u5bb9\u306b\u306a\u308a\u307e\u3059\u3002

    \u6ce8\u610f:\u8a18\u8f09\u5185\u5bb9\u306f\u4e00\u822c\u516c\u958b\u3055\u308c\u307e\u3059\u3002 -gui.dialog.send_bugreport.description.text = \u30c6\u30ad\u30b9\u30c8\u5165\u529b\u30a8\u30ea\u30a2\u306b\u73fe\u8c61\u306e\u660e\u7d30\u3092\u8a18\u5165\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u306a\u304a\u3001\u30d7\u30ed\u30bb\u30b9\u5b9a\u7fa9\u306e\u76ee\u7684\uff08\u51e6\u7406\u5185\u5bb9\uff09\u3082\u4f75\u8a18\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.send_bugreport.login_e_mail.label = \u30d0\u30b0\u30c8\u30e9\u30c3\u30ab\u30ed\u30b0\u30a4\u30f3: -gui.dialog.send_bugreport.login_e_mail.tip = RapidMiner\u30d0\u30b0\u30c8\u30e9\u30c3\u30ab\u30ed\u30b0\u30a4\u30f3E\u30e1\u30fc\u30eb\u3092\u5165\u529b\u3057\u307e\u3059 - -gui.dialog.send_bugreport.login_password.label = \u30d0\u30b0\u30c8\u30e9\u30c3\u30ab\u30d1\u30b9\u30ef\u30fc\u30c9: -gui.dialog.send_bugreport.login_password.tip = RapidMiner\u30d0\u30b0\u30c8\u30e9\u30c3\u30ab\u30ed\u30b0\u30a4\u30f3\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u307e\u3059\u3002 -gui.dialog.send_bugreport.login_as_anonymous.label = \u533f\u540d\u30ed\u30b0\u30a4\u30f3\u3092\u4f7f\u7528 -gui.dialog.send_bugreport.login_as_anonymous.tip = \u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u6709\u52b9\u5316\u3059\u308b\u4e8b\u306b\u3088\u308a\u3001\u533f\u540d\u3067\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1\u3057\u307e\u3059\u3002 -gui.dialog.send_bugreport.add_process_xml.label = \u30d7\u30ed\u30bb\u30b9\u6dfb\u4ed8 -gui.dialog.send_bugreport.add_process_xml.tip = \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u4e8b\u306b\u3088\u308a\u73fe\u5728\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306b\u6dfb\u4ed8\u3057\u307e\u3059\u3002 - -gui.dialog.send_bugreport.add_system_props.label = \u30b7\u30b9\u30c6\u30e0\u30d7\u30ed\u30d1\u30c6\u30a3\u6dfb\u4ed8 -gui.dialog.send_bugreport.add_system_props.tip = \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u6307\u5b9a\u3059\u308b\u4e8b\u306b\u3088\u308a\u3001\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306b\u30b7\u30b9\u30c6\u30e0\u30d7\u30ed\u30d1\u30c6\u30a3\u304c\u6dfb\u4ed8\u3055\u308c\u307e\u3059\u3002 -gui.dialog.send_bugreport.component.label = \u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8 -gui.dialog.send_bugreport.component.tip = \u3053\u306e\u30d0\u30b0\u306b\u95a2\u9023\u3059\u308bRapidMiner\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u9078\u629e -gui.dialog.send_bugreport.severity.label = \u91cd\u8981\u5ea6 -gui.dialog.send_bugreport.severity.tip = \u30d0\u30b0\u306e\u91cd\u8981\u5ea6\u3092\u9078\u629e -gui.dialog.send_bugreport.platform.label = \u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0 -gui.dialog.send_bugreport.platform.tip = \u4f7f\u7528\u3057\u3066\u3044\u308b\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u3092\u9078\u629e -gui.dialog.send_bugreport.os.label = OS -gui.dialog.send_bugreport.os.tip = \u4f7f\u7528\u3057\u3066\u3044\u308b\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u3092\u9078\u629e -gui.dialog.send_bugreport.summary.label = \u30b5\u30de\u30ea -gui.dialog.send_bugreport.summary.tip = \u30a8\u30e9\u30fc\u30b5\u30de\u30ea\u3092\u5165\u529b\u3057\u307e\u3059\u3002 -gui.dialog.send_bugreport.description.label = \u660e\u7d30 -gui.dialog.send_bugreport.description.tip = \u30d7\u30ed\u30bb\u30b9\u306e\u6982\u8981\u3092\u3092\u5165\u529b -gui.dialog.send_bugreport.submit.show_system_properties.title = \u4ee5\u4e0b\u306e\u60c5\u5831\u3092\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306b\u542b\u3081\u307e\u3059\u304b? -gui.dialog.send_bugreport.submit.show_system_properties.label = \u4ee5\u4e0b\u306b\u8868\u793a\u3057\u3066\u3044\u308b\u30b7\u30b9\u30c6\u30e0\u60c5\u5831\u306f\u30d0\u30b0\u306b\u5bfe\u3057\u3066\u6709\u529b\u306a\u60c5\u5831\u306e\u53ef\u80fd\u6027\u304c\u9ad8\u3044\u3067\u3059\u3002
    \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306b\u4ee5\u4e0b\u60c5\u5831\u3092\u542b\u3081\u307e\u3059\u304b? -gui.action.send_bugreport.add_file.label = \u30d5\u30a1\u30a4\u30eb\u6dfb\u4ed8 -gui.action.send_bugreport.add_file.icon = paperclip_add.png -gui.action.send_bugreport.add_file.tip = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u6dfb\u4ed8 -gui.action.send_bugreport.remove_file.label = \u6dfb\u4ed8\u3092\u524a\u9664 -gui.action.send_bugreport.remove_file.icon = paperclip_delete.png -gui.action.send_bugreport.remove_file.tip = \u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u30ea\u30b9\u30c8\u304b\u3089\u524a\u9664 - - - -gui.action.send_bugreport.save.label = \u30ec\u30dd\u30fc\u30c8\u4fdd\u5b58 -gui.action.send_bugreport.save.icon = save.png -gui.action.send_bugreport.savet.tip = ZIP\u66f8\u5eab\u306b\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u4fdd\u5b58 -gui.action.send_bugreport.submit.label = \u9001\u4fe1 -gui.action.send_bugreport.submit.icon = mail_bug.png -gui.action.send_bugreport.submit.tip = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1 -gui.action.send_bugreport.info.label = \u30ec\u30dd\u30fc\u30c8\u95b2\u89a7 -gui.action.send_bugreport.info.icon = document_text_view.png -gui.action.send_bugreport.info.tip = \u6700\u65b0\u7248\u306e\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u78ba\u8a8d\u3059\u308b\u3002 - -gui.dialog.message.bugreport_successful.title = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u6210\u529f -gui.dialog.message.bugreport_successful.message = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u306f\u6b63\u5e38\u306b\u51e6\u7406\u3055\u308c\u307e\u3057\u305f\u3002 -gui.dialog.message.bugreport_successful.icon = check.png - -gui.dialog.search_replace.title = \u691c\u7d22 -gui.dialog.search_replace.message = \u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3067\u6587\u5b57\u5217\u306e\u691c\u7d22\u304a\u3088\u3073\u7f6e\u63db\u3092\u3044\u305f\u3057\u307e\u3059\u3002 - -gui.dialog.search_replace.icon = binocular.png -gui.dialog.search_replace.search.title = \u691c\u7d22 -gui.dialog.search_replace.search_replace.title = \u691c\u7d22\u304a\u3088\u3073\u7f6e\u63db - -###################################### -# Result Renderers and Tabs -###################################### -gui.label.collectionviewer.select_leaf.label = \u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u30c4\u30ea\u30fc\u3082\u3057\u304f\u306f\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.action.select_columns.label = \u5217\u9078\u629e -gui.action.select_columns.icon = table_selection_column.png -gui.action.select_columns.tip = \u30e1\u30bf\u30c7\u30fc\u30bf\u30d3\u30e5\u30fc\u30ef\u3067\u8868\u793a\u3059\u308b\u5217\u3092\u9078\u629e - -gui.action.calculate_statistics.label = \u7d71\u8a08\u3092\u8a08\u7b97 -gui.action.calculate_statistics.icon = calculator.png -gui.action.calculate_statistics.tip = \u7d71\u8a08\u3092\u8a08\u7b97\uff08\u6642\u9593\u304c\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\uff09 - -gui.label.resulttab.creating_display.label = \u8868\u793a\u5185\u5bb9\u3092\u751f\u6210\u4e2d\u306b\u3064\u304d\u66ab\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002 -gui.label.resulttab.creating_display.icon = 48/hourglass.png - -gui.label.resulttab.cannot_be_restored.label = \u524d\u56de\u306eRapidMiner\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u72b6\u614b\u306b\u623b\u305b\u307e\u305b\u3093\u3002 -gui.label.resulttab.cannot_be_restored_process_result.label = \u524d\u56de\u306eRapidMiner\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u72b6\u614b\u306b\u623b\u305b\u307e\u305b\u3093\u3002 -gui.label.resulttab.table_cannot_be_restored.label = \u524d\u56de\u306eRapidMiner\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u72b6\u614b\u306b\u623b\u305b\u307e\u305b\u3093\u3002 - -gui.dialog.result.close_before_run.title = \u7d50\u679c\u3092\u9589\u3058\u308b -gui.dialog.result.close_before_run.icon = presentation_empty.png -gui.dialog.result.close_before_run.message = \u30d7\u30ed\u30bb\u30b9\u306e\u958b\u59cb\u524d\u306b\u904e\u53bb\u306e\u7d50\u679c\u3092\u9589\u3058\u307e\u3059\u304b\uff1f - -gui.action.resulthistory.restore_process.label = \u30ea\u30b9\u30c8\u30a2\u30d7\u30ed\u30bb\u30b9 -gui.action.resulthistory.restore_process.mne = P -gui.action.resulthistory.restore_process.icon = nav_undo.png -gui.action.resulthistory.restore_process.tip = \u3053\u306e\u7d50\u679c\u3092\u751f\u6210\u3057\u305f\u30d7\u30ed\u30bb\u30b9\u3092\u30ea\u30b9\u30c8\u30a2 - -gui.action.resulthistory.remove.label = \u5c65\u6b74\u524a\u9664 -gui.action.resulthistory.remove.mne = R -gui.action.resulthistory.remove.icon = delete.png -gui.action.resulthistory.remove.tip = \u7d50\u679c\u5c65\u6b74\u304b\u3089\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u3092\u524a\u9664 - -gui.action.resulthistory.clear_history.label = \u5c65\u6b74\u6d88\u53bb -gui.action.resulthistory.clear_history.mne = C -gui.action.resulthistory.clear_history.icon = delete.png -gui.action.resulthistory.clear_history.tip = \u7d50\u679c\u5c65\u6b74\u3092\u5b8c\u5168\u306b\u6d88\u53bb - -gui.action.resulthistory.restore_data.label = \u30ea\u30dd\u30b8\u30c8\u30ea\u304b\u3089\u30ea\u30b9\u30c8\u30a2 -gui.action.resulthistory.restore_data.mne = R -gui.action.resulthistory.restore_data.icon = data.png -gui.action.resulthistory.restore_data.tip = \u6700\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30ea\u30dd\u30b8\u30c8\u30ea\u304b\u3089\u30ea\u30b9\u30c8\u30a2 - -gui.action.resulthistory.open_data.label = \u7d50\u679c\u3092\u518d\u5ea6\u958b\u304f -gui.action.resulthistory.open_data.mne = O -gui.action.resulthistory.open_data.icon = presentation_chart.png -gui.action.resulthistory.open_data.tip = \u7d50\u679c\u30d3\u30e5\u306b\u3066\u7d50\u679c\u3092\u518d\u5ea6\u958b\u304f - -gui.dialog.cannot_restore_history_process.title = \u30d7\u30ed\u30bb\u30b9\u306e\u518d\u4e26\u3073\u66ff\u3048\u4e2d\u306b\u30a8\u30e9\u30fc -gui.dialog.cannot_restore_history_process.message = \u5c65\u6b74\u304b\u3089\u30d7\u30ed\u30bb\u30b9\u306e\u30ea\u30b9\u30c8\u30a2\u306b\u5931\u6557 - -###################################### -### ProgressThread -###################################### - -gui.dialog.progress_dialog.title = \u9032\u884c\u4e2d -gui.dialog.progress_dialog.message = \u4fdd\u7559\u4e2d\u306e\u30bf\u30b9\u30af: -gui.dialog.progress_dialog.icon = hourglass.png -gui.label.progress_dialog.current.label = \u73fe\u5728\u306e\u30bf\u30b9\u30af: -gui.label.progress_dialog.pending.label = \u4fdd\u7559\u4e2d\u306e\u30bf\u30b9\u30af: - -gui.dialog.error.error_executing_background_job.title = \u30a8\u30e9\u30fc -gui.dialog.error.error_executing_background_job.message = \u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u30b8\u30e7\u30d6''{0}''\u306e\u5b9f\u884c\u30a8\u30e9\u30fc : {1} - -gui.progress.copy_repository_entry.label=\u30b3\u30d4\u30fc\u4e2d -gui.progress.open_file.label=\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u3044\u3066\u3044\u307e\u3059\u3002 -gui.progress.open_process.label=\u958b\u3044\u3066\u3044\u308b\u30d7\u30ed\u30bb\u30b9 -gui.progress.add_repository.label=\u30ea\u30dd\u30b8\u30c8\u30ea\u8ffd\u52a0\u4e2d -gui.progress.creating_display.label=\u8868\u793a\u3092\u4f5c\u6210\u4e2d -gui.progress.create_folder.label=\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u4e2d -gui.progress.refreshing.label=\u66f4\u65b0\u4e2d -gui.progress.download_from_repository.label=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u4e2d -gui.progress.download_md_from_repository.label=\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u4e2d -gui.progress.store_process.label=\u30d7\u30ed\u30bb\u30b9\u3092\u4e26\u3073\u66ff\u3048\u4e2d -gui.progress.validate_process.label=\u30d7\u30ed\u30bb\u30b9\u3092\u691c\u8a3c\u4e2d -gui.progress.import_data.label=\u30c7\u30fc\u30bf\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d -gui.progress.auto_wiring.label=\u81ea\u52d5\u7d50\u5408\u30d7\u30ed\u30bb\u30b9 -gui.progress.fetching_database_tables.label=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u306e\u53d6\u5f97\u4e2d -gui.progress.test_database_connection.label=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u306e\u30c6\u30b9\u30c8\u4e2d -gui.progress.calculate_statistics.label=\u7d71\u8a08\u6570\u3092\u8a08\u7b97\u4e2d -gui.progress.connect_to_repository.label=\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u63a5\u7d9a\u4e2d -gui.progress.load_csv_file.label = cvs\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u4e2d -gui.progress.load_workbook.label = Excel\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u4e2d -gui.progress.show_error_rows.label = \u30a8\u30e9\u30fc\u3092\u7279\u5b9a\u4e2d -gui.progress.validate_value_types.label = \u5024\u578b\u3092\u691c\u8a3c -gui.progress.connect_to_bugzilla.label = Bugilla\u306b\u63a5\u7d9a\u4e2d -gui.progress.send_report_to_bugzilla.label = BugZilla\u306b\u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1\u4e2d - -######################################## -# Splash Screen -######################################## -gui.splash.rm_home = RapidMiner\u30db\u30fc\u30e0\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u4e2d -gui.splash.register_plugins = \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u767b\u9332\u4e2d -gui.splash.init_setup = \u8a2d\u5b9a\u3092\u521d\u671f\u5316\u4e2d -gui.splash.init_parameter_service = \u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d -gui.splash.init_ops = \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u521d\u671f\u5316\u4e2d -gui.splash.xml_transformer = XML\u5909\u63db\u30eb\u30fc\u30eb -gui.splash.init_repository = \u30c7\u30fc\u30bf\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u521d\u671f\u5316\u4e2d -gui.splash.load_jdbc_drivers = JDBC\u30c9\u30e9\u30a4\u30d0\u3092\u30ed\u30fc\u30c9\u4e2d -gui.splash.xml_serialization = XML\u30b7\u30ea\u30a2\u30eb\u5316\u3092\u521d\u671f\u5316\u4e2d -gui.splash.xml_alias = XML\u30b7\u30ea\u30a2\u30eb\u5316\u306e\u30a8\u30a4\u30ea\u30a2\u30b9\u3092\u5b9a\u7fa9\u4e2d -gui.splash.gen_key = \u6697\u53f7\u5316\u30ad\u30fc\u3092\u751f\u6210\u4e2d -gui.splash.init_renderers = \u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3092\u521d\u671f\u5316\u4e2d -gui.splash.loading_plugin = {0} \u62e1\u5f35\u6a5f\u80fd\u3092\u30ed\u30fc\u30c9\u4e2d - -gui.splash.init_i18n = \u591a\u8a00\u8a9e\u5316\u8a2d\u5b9a\uff08I18N\uff09\u3092\u521d\u671f\u5316\u4e2d -gui.splash.basic = \u57fa\u672c\u7684\u306a\u521d\u671f\u5316 -gui.splash.workspace = \u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u521d\u671f\u5316 -gui.splash.plaf = \u30eb\u30c3\u30af\u30a2\u30f3\u30c9\u30d5\u30a3\u30fc\u30eb\u3092\u8a2d\u5b9a\u4e2d -gui.splash.history = \u5c65\u6b74\u3092\u30ed\u30fc\u30c9\u4e2d -gui.splash.icons = \u30a2\u30a4\u30b3\u30f3\u3092\u30ed\u30fc\u30c9\u4e2d -gui.splash.create_frame = \u30d5\u30ec\u30fc\u30e0\u3092\u4f5c\u6210\u4e2d -gui.splash.gui_properties = GUI\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u30ed\u30fc\u30c9\u4e2d -gui.splash.plugin_gui = GUI\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u521d\u671f\u5316 -gui.splash.show_frame = \u30d5\u30ec\u30fc\u30e0\u3092\u8868\u793a\u4e2d -gui.splash.checks = \u78ba\u8a8d\u4e8b\u9805\u3092\u521d\u671f\u5316\u4e2d -gui.splash.ready = \u6e96\u5099\u5b8c\u4e86 - -######################################## -# RapidDocBotImporter -######################################## -gui.action.rapid_doc_bot_importer_online.label = -gui.action.rapid_doc_bot_importer_online.icon = earth_network.png -gui.action.rapid_doc_bot_importer_online.tip = \u30d8\u30eb\u30d7\u6587\u7ae0\u3092\u30ed\u30fc\u30c9 - -gui.action.rapid_doc_bot_importer_offline.label = -gui.action.rapid_doc_bot_importer_offline.icon = earth_network.png -gui.action.rapid_doc_bot_importer_offline.tip = \u30d8\u30eb\u30d7\u6587\u7ae0\u3092\u30ed\u30fc\u30c9 - -gui.action.rapid_doc_bot_importer_refresh.label = -gui.action.rapid_doc_bot_importer_refresh.icon = refresh.png -gui.action.rapid_doc_bot_importer_refresh.tip = Wiki\u304b\u3089\u30aa\u30da\u30ec\u30fc\u30bf\u3092\u66f4\u65b0 - -gui.action.rapid_doc_bot_importer_showInBrowser.label = -gui.action.rapid_doc_bot_importer_showInBrowser.icon = window_earth.png -gui.action.rapid_doc_bot_importer_showInBrowser.tip = \u30d6\u30e9\u30a6\u30b6\u306b\u30d8\u30eb\u30d7\u6587\u7ae0\u3092\u30ed\u30fc\u30c9 - -gui.dialog.error.rapid_doc_bot_importer_showInBrowser.title = \u30d6\u30e9\u30a6\u30b6\u3092\u958b\u304f\u4e8b\u306b\u5931\u6557 -gui.dialog.error.rapid_doc_bot_importer_showInBrowser.message =

    {0}\u3092\u958b\u304f\u4e8b\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002

    \u30d6\u30e9\u30a6\u30b6\u3092\u624b\u52d5\u3067\u958b\u3044\u3066\u304f\u3060\u3055\u3044\u3002

    - -gui.dialog.error.rapid_doc_bot_importer_error.title = \u30d8\u30eb\u30d7\u6587\u7ae0\u306e\u8868\u793a\u5931\u6557 -gui.dialog.error.rapid_doc_bot_importer_showInBrowser.message = \u30d0\u30b0\u30ec\u30dd\u30fc\u30c8\u3092\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - -gui.dialog.error.failed_to_fetch_database_tables.title=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc -gui.dialog.error.failed_to_fetch_database_tables.message=\u63a5\u7d9a{0}\u3092\u4f7f\u7528\u3057\u3066\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u60c5\u5831\u53d6\u5f97\u30a8\u30e9\u30fc: {1} - -#gui.action..label = -#gui.action..mne = -#gui.action..icon = -#gui.action..tip = -#gui.action..acc = - -#gui.action..label = -#gui.action..mne = -#gui.action..icon = -#gui.action..tip = -#gui.action..acc = diff --git a/src/main/resources/com/rapidminer/resources/i18n/LogMessages.properties b/src/main/resources/com/rapidminer/resources/i18n/LogMessages.properties index 325d16092..712e8f484 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/LogMessages.properties +++ b/src/main/resources/com/rapidminer/resources/i18n/LogMessages.properties @@ -3,6 +3,8 @@ com.rapidminer.gui.RapidMinerGUI.start_version=Launching RapidMiner {0}, platfor com.rapidminer.tools.I18N.set_locale_to=Set locale to {0}. com.rapidminer.tools.I18N.using_default_locale=No locale set. Taking default system locale {0}. com.rapidminer.tools.I18N.missing_key=Missing I18N key: {0} +com.rapidminer.tools.I18N.add_language_failed=Registration of language "{0}" failed. RapidMiner might not be initialized. +com.rapidminer.tools.I18N.add_language_wrong_format=Registration of language "{0}" failed. Not a valid IETF BCP 47 language tag. com.rapidminer.gui.flow.ProcessRenderer.loading_operator_group_colors_error=Cannot load operator group colors. com.rapidminer.gui.flow.ProcessRenderer.loading_io_object_colors_error=Cannot load io object colors for plugin {0} com.rapidminer.gui.tools.SwingTools.loading_operator_group_colors_error=Cannot load operator group colors. @@ -167,6 +169,8 @@ com.rapidminer.operator.ports.impl.AbstractPorts.port_extender_did_not_extend=Po com.rapidminer.operator.ports.impl.AbstractPorts.ports_created=Port was created. Ports are now: {0} com.rapidminer.operator.ports.impl.AbstractPorts.extending_error=Cannot extend {0}: {1} com.rapidminer.tools.documentation.ExampleProcess.parsing_example_process_error=Cannot parse example process: {0} +com.rapidminer.tools.documentation.ExampleProcess.invalid_index=Invalid tutorial process index {1} for operator {0} +com.rapidminer.tools.documentation.ExampleProcess.operator_not_found=Couldn't find operator {0} com.rapidminer.tools.documentation.ExampleProcess.creating_example_process_error=Example process could not be created. com.rapidminer.tools.documentation.ExampleProcess.parsing_xml_error=Error parsing xml! Example process could not be created. com.rapidminer.tools.documentation.ExampleProcess.reading_file_error=Error reading file! Example process could not be created. @@ -230,6 +234,7 @@ com.rapidminer.RapidMiner.reading_process_file=Reading process file {0}. com.rapidminer.RapidMiner.reading_process_definition_file_error=Cannot read process definition file {0}! com.rapidminer.RapidMiner.generating_encryption_key_error=Cannot generate encryption key: {0} com.rapidminer.RapidMiner.reading_global_version_file_error=Cannot read global version file of last used version. +com.rapidminer.RapidMiner.parsing_global_version_file_error=Cannot parse last used version of global version file. com.rapidminer.RapidMiner.closing_stream_error=Cannot close stream to file {0} com.rapidminer.RapidMiner.writing_current_version_error=Cannot write current version into property file. com.rapidminer.RapidMiner.performing_upgrade=Performing upgrade {0} to version {1} @@ -323,7 +328,7 @@ com.rapidminer.tools.documentation.XMLOperatorDocBundle.looking_up_operator_docu com.rapidminer.tools.documentation.XMLOperatorDocBundle.loading_operator_documentation=Loading operator documentation from {0} com.rapidminer.tools.documentation.XMLOperatorDocBundle.creating_xml_parser_error=Cannot create XML parser: {0} com.rapidminer.tools.documentation.XMLOperatorDocBundle.missing_operator_help=Operator help is missing tag. Using as : {0} -com.rapidminer.tools.documentation.XMLOperatorDocBundle.malformed_operator_documentation=Malformed operoator documentation: {0} +com.rapidminer.tools.documentation.XMLOperatorDocBundle.malformed_operator_documentation=Malformed operator documentation: {0} com.rapidminer.tools.documentation.XMLOperatorDocBundle.loaded_documentation=Loaded documentation for {0} operators and {1} groups. com.rapidminer.gui.dialog.OperatorInfoPanel.creating_operator_error=Cannot create operator: {0} com.rapidminer.io.process.rules.AbstractConditionedParseRule.unknown_condition=Unknown condition: {0} @@ -380,6 +385,7 @@ com.rapidminer.tools.MailSenderSMTP.creating_mail_session_error=Unable to create com.rapidminer.tools.MailUtilities.sent_mail_to_adress_with_subject=Sent mail to {0} with subject {1} com.rapidminer.FileProcessLocation.saved_process_definition_file=Saved process definition file at {0}. com.rapidminer.RepositoryProcessLocation.saved_process_definition=Saved process definition at {0}. +com.rapidminer.repository.remote.RemoteIOObjectEntry.meta_data_error=Could not transfer MetaData to server. com.rapidminer.repository.remote.RemoteIOObjectEntry.begin_reply_server=BEGIN Reply of server: com.rapidminer.repository.remote.RemoteIOObjectEntry.end_reply_server=END Reply of server. com.rapidminer.io.process.XMLTools.xml_transformer_does_not_support_identation=XML transformer does not support indentation: {0} @@ -556,8 +562,8 @@ com.rapidminer.gui.processeditor.XMLEditor.failed_to_parse_process=Invalid proce com.rapidminer.gui.properties.RegexpPropertyDialog.bad_location=Unexpected error: Bad location in document. -com.rapidminer.gui.properties.SettingsItems.remove_item_error = Could not remove item. -com.rapidminer.gui.properties.SettingsItems.parse_xml_error = Could not parse XML settings file: {0}. Cause: {1} +com.rapidminer.gui.properties.AbstractSettingsItemProvider.remove_item_error = Could not remove item. +com.rapidminer.gui.properties.AbstractSettingsItemProvider.parse_xml_error = Could not parse XML settings file: {0}. Cause: {1} com.rapidminer.gui.properties.SettingsItem.no_i18n_description_error = Could not find i18n for description of preference parameter: {0} com.rapidminer.gui.properties.SettingsItem.no_i18n_title_error = Could not find i18n for title of preference parameter: {0} com.rapidminer.gui.properties.SettingsTabs.no_parameter_in_xml = Preference XML does not contain parameter ''{0}''. Parameter will be attached. @@ -714,9 +720,9 @@ com.rapidminer.operator.GroupedModel.couldnt_create_operator=An error occurred w com.rapidminer.operator.learner.meta.StackingModel.couldnt_create_operator=An error occurred while trying to calculate the progress of the application of StackingModel. com.rapidminer.operator.learner.meta.BayBoostModel.couldnt_create_operator=An error occurred while trying to calculate the progress of the application of BoyBoostModel. -com.rapidminer.concurrency.concurrency_context.parse_success=Parsed SCC setting of {0}. -com.rapidminer.concurrency.concurrency_context.parse_failure=Failed to parse SCC setting of {0}. -com.rapidminer.concurrency.concurrency_context.pool_creation=Updated SCC to size {0}. +com.rapidminer.concurrency.concurrency_context.parse_success=Parsed {1} setting of {0}. +com.rapidminer.concurrency.concurrency_context.parse_failure=Failed to parse {1} setting of {0}. +com.rapidminer.concurrency.concurrency_context.pool_creation=Updated {1} to size {0}. com.rapidminer.tools.usagestats.CtaDao.init.failure = CTA database instantiation failed. com.rapidminer.tools.usagestats.CtaDataSource.database.currupted = The CTA DB file is corrupted. @@ -754,7 +760,7 @@ com.rapidminer.gui.tools.BrowserPopup.result.interupted = Interrupted while wait com.rapidminer.global_search.searchindexer.setup_failed = Failed to set up Global Search. Search disabled! com.rapidminer.global_search.searchindexer.setup_self_fix_start = Cannot prepare Global Search index directory. Trying to fix the problem. com.rapidminer.global_search.searchindexer.setup_self_fix_success = Successfully fixed Global Search index directory. Search enabled! -com.rapidminer.global_search.searchindexer.setup_self_fix_failed = Failed to fix index folder for Global Search. +com.rapidminer.global_search.searchindexer.setup_self_fix_failed = Failed to fix index folder for Global Search. Most likely cause: You are running multiple Studios at the same time. com.rapidminer.global_search.searchindexer.add_failed = Failed to add search documents for category {0}: {1}! com.rapidminer.global_search.searchindexer.update_failed = Failed to update search documents for category {0}: {1}! com.rapidminer.global_search.searchindexer.remove_failed = Failed to remove search documents for category {0}: {1}! @@ -789,6 +795,7 @@ com.rapidminer.repository.global_search.RepositorySearchManager.error.initial_in com.rapidminer.gui.processeditor.global_search.OperatorSearchManager.error.no_key = Cannot insert operator, key was null! com.rapidminer.gui.processeditor.global_search.OperatorSearchManager.error.operator_browse_error = Cannot preview operator, creation failed: {0}! com.rapidminer.gui.processeditor.global_search.OperatorSearchManager.error.operator_creation_error = Cannot insert operator, creation failed: {0}! +com.rapidminer.gui.processeditor.global_search.OperatorSearchManager.error.output_metadata_transform_failed = Global Search cannot detect port output class for operator {0}. Ignoring. com.rapidminer.gui.actions.search.ActionsGlobalSearchManager.error.index_action.name_null = Failed to index action {0}, name was null! com.rapidminer.gui.actions.search.ActionsGlobalSearchManager.error.index_action.serialization_failed = Failed to index action {0}, storing action failed! @@ -861,3 +868,13 @@ com.rapidminer.sample_repository.register.success = Registered ''{0}'' as sample com.rapidminer.sample_repository.unregister_error.other_extension = Cannot unregister ''{0}'' from sample folder. Was registered by different extension. com.rapidminer.sample_repository.unregister.success = Unregistered ''{0}'' from sample folder. +com.rapidminer.tools.update.internal.MigrationManager.starting = Executing migration step ''{0}'' +com.rapidminer.tools.update.internal.MigrationManager.success = Executed migration step ''{0}'' successfully! +com.rapidminer.tools.update.internal.MigrationManager.failure = Migration failed for step ''{0}'' + +com.rapidminer.gui.PerspectiveController.restore_default = Restoring {0} view default. + +com.rapidminer.gui.import.could_not_create_dateformat = Could not create SimpleDateFormat instance +com.rapidminer.gui.import.could_not_read_from_dataset = Could not read data from dataset + +com.rapidminer.tools.FontTools.system_font_loading.failed = Could not load system fonts. \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/i18n/OperatorsCoreDocumentation.xml b/src/main/resources/com/rapidminer/resources/i18n/OperatorsCoreDocumentation.xml index 467d7af09..c6c8522c7 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/OperatorsCoreDocumentation.xml +++ b/src/main/resources/com/rapidminer/resources/i18n/OperatorsCoreDocumentation.xml @@ -1281,7 +1281,7 @@ log_to_weights
    - Pivot + Pivot (Deprecated) Transforms an example set by grouping multiple examples of single units to single examples. <p>Transforms an example set by grouping multiple examples @@ -3195,6 +3195,7 @@ Cross-table Crosstable Distinct + Percentile diff --git a/src/main/resources/com/rapidminer/resources/i18n/Settings.properties b/src/main/resources/com/rapidminer/resources/i18n/Settings.properties index 47b4eb642..7dac7fb32 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/Settings.properties +++ b/src/main/resources/com/rapidminer/resources/i18n/Settings.properties @@ -46,12 +46,14 @@ rapidminer.preferences.subgroup.general.encoding.title = Encoding rapidminer.preferences.subgroup.general.error.handling.title = Error handling rapidminer.preferences.subgroup.general.locale.title = Locale rapidminer.preferences.subgroup.general.numbers.title = Number format +rapidminer.preferences.subgroup.general.parallel.title = Parallel execution rapidminer.preferences.subgroup.update.updates.title = Updates rapidminer.preferences.subgroup.update.beta_program.title = Beta Program rapidminer.preferences.subgroup.tools.mail.title = Mail rapidminer.preferences.subgroup.tools.smtp.title = SMTP +rapidminer.preferences.subgroup.tools.sendmail.title = Sendmail rapidminer.preferences.subgroup.gui.general.title = General rapidminer.preferences.subgroup.gui.plotter.title = Charts @@ -70,7 +72,7 @@ rapidminer.preferences.subgroup.system.network.title = Network ############################## rapidminer.general.locale.language.title = Language -rapidminer.general.locale.language.description = The displayed language +rapidminer.general.locale.language.description = The displayed language. Restart required to take effect. rapidminer.general.randomseed.title = Random seed rapidminer.general.randomseed.description = The default seed (Set this to -1 to generate random seeds). @@ -90,11 +92,14 @@ rapidminer.general.debugmode.description = Run RapidMiner in debug mode (Print e rapidminer.general.timezone.title = Time zone rapidminer.general.timezone.description = The default time zone used for displaying date and time information (default: 'SYSTEM' uses the underlying system encoding, 'UCT', 'GMT' or 'CET' are other common options). -rapidminer.general.number_of_threads.title = Number of parallel worker threads -rapidminer.general.number_of_threads.description = The maximum number of parallel worker threads (which do the actual number-crunching) that a RapidMiner operator is allowed to use. We recommend keeping it at its default of '0' - that way, operators use the recommended number of threads for the system, usually #CPU cores - 1. Say you have 4 CPU cores and keep the default, then operators that have multi-core support can split their work into batches and run 3 (4 cores - 1) of those batches at the same time. When changing the default, it should never exceed 2 times the number of CPU cores though, otherwise operators may become significantly slower due to additional management overhead. Note: Increasing this setting above your license's logical processors limit has no effect. +rapidminer.general.number_of_threads.title = Worker threads for active process +rapidminer.general.number_of_threads.description = The maximum number of parallel worker threads (which do the actual number-crunching) that a RapidMiner operator is allowed to use for the currently opened process. We recommend keeping it at its default of '0' - that way, operators use the recommended number of threads for the system, usually #CPU cores - 1. Say you have 4 CPU cores and keep the default, then operators that have multi-core support can split their work into batches and run 3 (4 cores - 1) of those batches at the same time. When changing the default, it should never exceed 2 times the number of CPU cores though, otherwise operators may become significantly slower due to additional management overhead. Note: Increasing this setting above your license's logical processors limit has no effect. -rapidminer.general.number_of_processes.title = Number of parallel processes -rapidminer.general.number_of_processes.description = The maximum number of background processes, which are allowed to run at the same time (default: '0' uses the recommended number for your system). +rapidminer.general.number_of_threads_background.title = Worker threads for background execution +rapidminer.general.number_of_threads_background.description = The maximum number of parallel worker threads (which do the actual number-crunching) that a RapidMiner operator is allowed to use for background execution. We recommend keeping it at its default of '0' - that way, operators use the recommended number of threads for the system, usually #CPU cores - 1. Say you have 4 CPU cores and keep the default, then operators that have multi-core support can split their work into batches and run 3 (4 cores - 1) of those batches at the same time. When changing the default, it should never exceed 2 times the number of CPU cores though, otherwise operators may become significantly slower due to additional management overhead. Note: Increasing this setting above your license's logical processors limit has no effect. + +rapidminer.general.number_of_processes.title = Concurrently running background processes +rapidminer.general.number_of_processes.description = The maximum number of background processes, which are allowed to run at the same time (default: '0' uses the recommended number for your system). rapidminer.general.encoding.title = Encoding rapidminer.general.encoding.description = The default encoding used for file operations (default: 'SYSTEM' uses the underlying system encoding, 'UTF-8' or 'ISO-8859-1' are other common options). @@ -163,8 +168,11 @@ rapidminer.gui.evaluate_meta_data_for_sql_queries.description = Fetch SQL meta d rapidminer.gui.hide_getting_started_tab.title = Hide "Learn" tab from welcome dialog rapidminer.gui.hide_getting_started_tab.description = Hide the "Learn" tab on start-up of RapidMiner. The tab can still be accessed using the menu Help -> Tutorials. -rapidminer.gui.disconnect_on_disable.title = Bridge connection if operator is removed -rapidminer.gui.disconnect_on_disable.description = Should operators be disconnected upon disabling or deleting them? +rapidminer.gui.disable_op_conn_behavior.title = Connections of a disabled operator should be +rapidminer.gui.disable_op_conn_behavior.description = Should connections be removed, bridged or kept upon disabling the operator? + +rapidminer.gui.delete_op_conn_behavior.title = Connections of a removed operator should be +rapidminer.gui.delete_op_conn_behavior.description = Should connections be removed or bridged upon deleting the operator? rapidminer.gui.transfer_usagestats.title = Transfer usage statistics rapidminer.gui.transfer_usagestats.description = Allow RapidMiner Studio to transfer operator usage statistics? diff --git a/src/main/resources/com/rapidminer/resources/i18n/UserErrorMessages.properties b/src/main/resources/com/rapidminer/resources/i18n/UserErrorMessages.properties index 936ffb7cc..c90dd7318 100644 --- a/src/main/resources/com/rapidminer/resources/i18n/UserErrorMessages.properties +++ b/src/main/resources/com/rapidminer/resources/i18n/UserErrorMessages.properties @@ -866,7 +866,7 @@ error.aggregation.aggregation_attribute_not_present.long = Please check whether error.aggregation.illegal_function_name.name = Unknown aggregation function error.aggregation.illegal_function_name.short = You tried to create an aggregation function with the name {0} that does not exist. -error.aggregation.illegal_function_name.long = The aggregation operator offers two parameters, the default aggregation function and the list of aggregation attributes with the respective function. You have to select an existing function to avoid this problem. +error.aggregation.illegal_function_name.long = The aggregation operator offers two parameters, the default aggregation function and the list of aggregation attributes with the respective function. You have to select an existing function to avoid this problem. error.nominal_to_numerical.illegal_comparison_group.name = Illegal comparison group error.nominal_to_numerical.illegal_comparison_group.short = No comparison group has been set for attribute {0}, or it has an invalid value. Value is "{1}" @@ -1218,4 +1218,16 @@ error.inapplicable_bregman_divergence.range.long = Proceed with the 'Squared Euc error.operator_blacklisted.name = Operator is prohibited error.operator_blacklisted.short = The usage of this operator has been prohibited by your system administrator. -error.operator_blacklisted.long = Please contact your administrator for more information. \ No newline at end of file +error.operator_blacklisted.long = Please contact your administrator for more information. + +error.aggregation.percentile.outofbounds.name = Aggregate percentile error +error.aggregation.percentile.outofbounds.short = Percentile values must be greater than 0 and lower than or equal to 100. +error.aggregation.percentile.outofbounds.long = Input was {0}. + +error.aggregation.percentile.notparsable.name = Percentile value not parsable +error.aggregation.percentile.notparsable.short = Percentile value could not be read, expected ''{0}''. +error.aggregation.percentile.notparsable.long = Input was ''{1}''. + +error.aggregation.percentile.numberformat.name = Percentile number not parsable +error.aggregation.percentile.numberformat.short = Percentile value could not be read. +error.aggregation.percentile.numberformat.long = Expecting an integer or a floating point value but found ''{0}''. \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/i18n/language_definitions.txt b/src/main/resources/com/rapidminer/resources/i18n/language_definitions.txt deleted file mode 100644 index df5c73f14..000000000 --- a/src/main/resources/com/rapidminer/resources/i18n/language_definitions.txt +++ /dev/null @@ -1,4 +0,0 @@ -# iso639-1 codes -# see http://www.loc.gov/standards/iso639-2/php/English_list.php -en -ja diff --git a/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/22_Transactional2Basket.rmp b/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/22_Transactional2Basket.rmp index 8cdf2faa9..dc9113c49 100644 --- a/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/22_Transactional2Basket.rmp +++ b/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/22_Transactional2Basket.rmp @@ -1,10 +1,10 @@ - + - + @@ -12,28 +12,19 @@ - + - + - + - - - - - - - - - - + @@ -47,11 +38,11 @@ - - + + + - @@ -59,75 +50,53 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - + + - + - - - - - - - + + + + + + - - - + + + - + \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/24_CreationOfIndexAndPivoting.rmp b/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/24_CreationOfIndexAndPivoting.rmp index 590a11226..bab46f7f9 100644 --- a/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/24_CreationOfIndexAndPivoting.rmp +++ b/src/main/resources/com/rapidminer/resources/samples/processes/02_Preprocessing/24_CreationOfIndexAndPivoting.rmp @@ -1,10 +1,10 @@ - + - + @@ -12,7 +12,7 @@ - + @@ -23,8 +23,9 @@ + - + @@ -39,7 +40,7 @@ - + @@ -59,7 +60,7 @@ - + @@ -87,29 +88,29 @@ - + - + - + - + - + @@ -118,31 +119,31 @@ - + - + - + - + - + @@ -167,17 +168,17 @@ - + + - - - - - - - + + + + + + @@ -186,11 +187,11 @@ - - + + - + \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/settings.xml b/src/main/resources/com/rapidminer/resources/settings.xml index 4a036bdec..9c40a030d 100644 --- a/src/main/resources/com/rapidminer/resources/settings.xml +++ b/src/main/resources/com/rapidminer/resources/settings.xml @@ -17,8 +17,12 @@
    + + + + + - @@ -42,11 +46,13 @@ - + + + @@ -111,7 +117,8 @@ - + + diff --git a/src/main/resources/com/rapidminer/resources/template/src/direct_marketing/Direct Marketing.rmp b/src/main/resources/com/rapidminer/resources/template/src/direct_marketing/Direct Marketing.rmp index 4cb4af373..9974af5e3 100644 --- a/src/main/resources/com/rapidminer/resources/template/src/direct_marketing/Direct Marketing.rmp +++ b/src/main/resources/com/rapidminer/resources/template/src/direct_marketing/Direct Marketing.rmp @@ -1,5 +1,4 @@ - - + @@ -15,6 +14,12 @@ + + + + + + @@ -22,7 +27,16 @@ + + + + + + + + + @@ -30,13 +44,22 @@ + - + + + + + + + - + + + @@ -46,10 +69,33 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -67,7 +113,12 @@ + + + + + Specify the costs of missing a potential respondent vs. the costs of including somebody into the campaign. @@ -80,6 +131,7 @@ + diff --git a/src/main/resources/com/rapidminer/resources/template/src/market_basket_analysis/Market basket analysis.rmp b/src/main/resources/com/rapidminer/resources/template/src/market_basket_analysis/Market basket analysis.rmp index 2c7553afe..fbde6972b 100644 --- a/src/main/resources/com/rapidminer/resources/template/src/market_basket_analysis/Market basket analysis.rmp +++ b/src/main/resources/com/rapidminer/resources/template/src/market_basket_analysis/Market basket analysis.rmp @@ -1,11 +1,10 @@ - - + - + @@ -13,10 +12,10 @@ - + - + @@ -32,85 +31,44 @@ - + - + - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + - - - - + + - + @@ -118,11 +76,8 @@ - - - - - + + @@ -133,10 +88,10 @@ MARKET BASKET ANALYSIS<br>Model associations between products by determining sets of items frequently purchased together and building association rules to derive recommendations. Step 1:<br/>Load transaction data containing a transaction id, a product id and a quantifier. The data denotes how many times a certain product has been purchased as part of a transactions. - <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> Step 2:<br>Edit, transform &amp; load (ETL) - Aggregate transaction data to account for multiple occurrences of the same product in a transaction. Pivot the data so that each transaction is represented by a row. Transform purchase amounts to binary &quot;product purchased yes/no &quot; indicators.<br> + <br> <br> <br> <br> <br> <br> <br> <br> <br> Step 2:<br>Edit, transform &amp; load (ETL) - Aggregate transaction data via concatenation so that the products in a transaction are in one entry, separated by the pipe symbol.<br> Step 3:<br/>Using FP-Growth, determine frequent item sets. A frequent item sets denotes that the items (products) in the set have been purchased together frequently, i.e. in a certain ratio of transactions. This ratio is given by the support of the item set. <br> <br> <br> <br> <br> <br> Step 4:<br/>Create association rules which can be used for product recommendations depending on the confidences of the rules.<br> Outputs: association rules, frequent item set<br> - + \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/template/src/predictive_maintenance/Predictive Maintenance.rmp b/src/main/resources/com/rapidminer/resources/template/src/predictive_maintenance/Predictive Maintenance.rmp index b0012a940..edbe8a730 100644 --- a/src/main/resources/com/rapidminer/resources/template/src/predictive_maintenance/Predictive Maintenance.rmp +++ b/src/main/resources/com/rapidminer/resources/template/src/predictive_maintenance/Predictive Maintenance.rmp @@ -1,4 +1,4 @@ - + @@ -17,89 +17,81 @@ - + + - + - - + + - + - - + + - + - + - + - - + + - - + + - - + + - + - - - - - - - - - - - - + + + - + @@ -107,12 +99,21 @@ - - + + + + + + + - - + + + + + + @@ -132,11 +133,11 @@ - + - + @@ -159,9 +160,9 @@ - - - + + + @@ -171,10 +172,10 @@ - + - + @@ -184,7 +185,7 @@ - + @@ -193,8 +194,8 @@ - - + + @@ -218,11 +219,11 @@ - + - + @@ -237,7 +238,7 @@ - + @@ -258,18 +259,18 @@ - - + + - + - + - + @@ -293,9 +294,9 @@ - + - + @@ -315,4 +316,4 @@ Outputs: influence factors, k-NN optimization log, failure predictions - + \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/steps.xml b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/steps.xml index df7ba7e39..7ece5c4e9 100644 --- a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/steps.xml +++ b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/steps.xml @@ -1,23 +1,20 @@ - + In this tutorial, you will learn about another common data blending technique, namely the Pivoting - of data. You might be familiar with the concept of Pivoting from BI tools or Excel: - rotate the data from a long table format (one attribute with a lot of examples) into a wide table format (lots of attributes with a single example). - This transformation is especially useful after an aggregation since - the - aggregated information is always stored in a long format. Machine learning models, however, - need - the data to be stored in - a wide column format so you will encounter this preprocessing step - frequently - before you start with the actual modeling. + of data. You might be familiar with the concept of Pivoting from BI tools or Excel: + rotate the data from a long table format (one attribute with a lot of examples) into a wide table format + (lots of attributes with a single example). This transformation is especially useful to aggregate + information along two or more dimensions as a step to prepare the data for machine learning. Machine + learning models need the data to be stored in a wide table format so you will encounter this preprocessing + step frequently before you start with the actual modeling. + - + - Let’s start by creating a table that shows how many passengers were in each class, broken down by gender. + Let’s create a table that shows how many passengers were in each class, broken down by gender. @@ -30,20 +27,24 @@ Add the operator - Aggregate + Pivot and connect it. In its Parameters, - select - Passenger Class - and + add Sex - as + to the group by attributes. + + Select + Passenger Class + as + column grouping attribute. + Also use Passenger Class @@ -56,72 +57,14 @@ - The result will be a table with three columns: - Passenger Class, - Sex, and the count for each of - those combinations. The first row is - First, - Female - with a count of - 144, the second row is - First, - Male - with a count of - 179 - and so on. All combinations of the passenger class and the gender - are represented as rows which is - why we call this a - long - table format. - - - - - - Let’s transform the long table format into a wide format that will make the number of males and females in each class a bit clearer. - - - - - Search - for the operator - Pivot, - add it, - and - connect it - to - Aggregate. - - - Select - the operator to see its - Parameters. - Use - Sex - as the - group attribute. - - - Use - Passenger Class - as - index attribute. - - - - - The resulting data set has four columns and two rows. Each row represents one of the values from the Sex column - (the group attributes parameter). The three different - values of the - index attribute - ( - passenger class - ) become the three new columns. The actual values in the table are representing the - counts - from the aggregation for the combination of the group (gender) with the index value (or - subgroup), which is the passenger class in our case. For example, we will get 144 females who - booked first - class. + The resulting data table has four columns and two rows. Each row represents one of the values from the + Sex + column, (the group by attributes parameter). + The three different values of the column grouping attribute ( + Passenger Class) become the three new columns. The actual values in the table are + representing the counts of each combination of groups in the rows, i.e. the gender, and the groups in the + columns, which is the passenger class in our case. For example, we will get 144 females who + booked first class. @@ -179,8 +122,8 @@ Since the round brackets have a special meaning here, we need to quote the brackets in the name itself with a backslash. Finally, we can use the capturing groups in the replace by parameter with the dollar sign and the number identifying the group. $1 is for - the content of the first group, which always happens to be "Passenger Class", and $2 is - for identifying the second group. Those are the three different classes "First", "Second", and "Third". + the content of the first group, which always happens to be "Passenger Class", and $2 is + for identifying the second group. Those are the three different classes "First", "Second", and "Third". @@ -197,15 +140,14 @@ - You rotated an aggregated data set from a long to a wide table format - good job! Pivot can be difficult to configure sometimes. - Just keep in mind that the groups parameter will end up in the rows with one row per group while the values of the index attribute - parameter will define the new columns. + You rotated an aggregated data set in wide table format - good job! Pivot can be difficult to + configure sometimes. + Just keep in mind that the group by attributes parameter parameter will define the groups in + the rows with one row per group while the values of the column grouping attribute parameter will define the + new columns. + - - Add a breakpoint after "Aggregate". Run the process and check out the long table format. How many rows does it have? - Resume the process and compare the long format to wide format. Don't forget to remove the breakpoint if you no longer need it. - Can you change the process so that the column names will be changed to "First Passenger Class", "Second Passenger Class", and "Third Passenger Class"? @@ -214,16 +156,23 @@ Can you also change them to just say "First Class", "Second Class", and "Third Class"? - Change the Pivot so that the gender is transformed into new columns and the class is defining three groups of data. - How many columns and rows are you getting now? + Change the Pivot so that the gender is transformed into new columns and the passenger class is defining + three groups of data. How many columns and rows are you getting now? + + + Try to adapt the renaming so that it just uses the gender as column names after the new pivoting. - Try to adapt the renaming so that it just uses the gender as column names after the new Pivoting. + Now, remove the Rename by Replacing operator and remove the column grouping attribute from Pivot. Set + Sex and Passenger Class as group by attributes and use Passenger Class with count as the aggregation + attribute. Run the process and inspect the result. In how far is it different from the first result you + obtained through Pivot? - Don't worry if you had trouble with challenges 2, 3, or 5. Regular expressions can be difficult at first but + Don't worry if you had trouble with challenges 2, 3, or 5. Regular expressions can be difficult at first, + but they are definitely worth learning. Maybe a book can help you or you will find a lot of training resources online . diff --git a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial.properties b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial.properties index eba4351fd..4a03f6df2 100644 --- a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial.properties +++ b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial.properties @@ -1,2 +1,2 @@ tutorial.name=Pivoting and Renaming -tutorial.description=Learn how you can rotate a long table into a wide format; then use advanced attribute renaming \ No newline at end of file +tutorial.description=Learn how you can aggregate data along multiple dimensions and pivot; then use advanced attribute renaming \ No newline at end of file diff --git a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial3.blob b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial3.blob index 57fd82387..03037fadd 100644 Binary files a/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial3.blob and b/src/main/resources/com/rapidminer/resources/tutorial/src/Data Handling/03/tutorial3.blob differ diff --git a/src/test/java/com/rapidminer/core/license/ProductLinkRegistryTest.java b/src/test/java/com/rapidminer/core/license/ProductLinkRegistryTest.java new file mode 100644 index 000000000..2ac1438d2 --- /dev/null +++ b/src/test/java/com/rapidminer/core/license/ProductLinkRegistryTest.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2001-2018 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.core.license; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.rapidminer.license.StudioLicenseConstants; + + +/** + * Test for ProductLinkRegistry + * + * @author Jonas Wilms-Pfau + * @since 9.1.0 + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ProductLinkRegistryTest { + + private static final String UNREGISTERED = "unregistered"; + private static final String EXT1 = "ext1"; + private static final String STUDIO = StudioLicenseConstants.PRODUCT_ID; + + private static final String EXT1_URL = "http://www.example.com/ext1"; + private static final String STUDIO_URL = "http://www.example.com/studio"; + + @Test + public void a_unRegisteredTest() { + Assert.assertEquals(ProductLinkRegistry.PURCHASE.get(UNREGISTERED, STUDIO_URL), STUDIO_URL); + } + + @Test + public void b_nullTest() { + Assert.assertEquals(ProductLinkRegistry.PURCHASE.get(null, STUDIO_URL), STUDIO_URL); + } + + @Test + public void c_registerTest() { + ProductLinkRegistry.PURCHASE.register(EXT1, STUDIO_URL); + ProductLinkRegistry.PURCHASE.register(EXT1, EXT1_URL); + Assert.assertEquals(ProductLinkRegistry.PURCHASE.get(EXT1, STUDIO_URL), EXT1_URL); + } + + @Test + public void d_studioTest() { + ProductLinkRegistry.PURCHASE.register(EXT1, EXT1_URL); + Assert.assertEquals(ProductLinkRegistry.PURCHASE.get(STUDIO, STUDIO_URL), STUDIO_URL); + } + + @Test(expected = NullPointerException.class) + public void e_registerNullProductId() { + ProductLinkRegistry.PURCHASE.register(null, STUDIO_URL); + } + + @Test(expected = NullPointerException.class) + public void f_registerNullLink() { + ProductLinkRegistry.PURCHASE.register(EXT1, null); + } + + @Test(expected = IllegalArgumentException.class) + public void g_registerInvalidLink() { + ProductLinkRegistry.PURCHASE.register(EXT1, EXT1); + } + + @Test(expected = UnsupportedOperationException.class) + public void h_registerStudio() { + ProductLinkRegistry.PURCHASE.register(STUDIO, STUDIO_URL); + } +} diff --git a/src/test/java/com/rapidminer/gui/properties/SettingsDialogTestField.java b/src/test/java/com/rapidminer/gui/properties/SettingsDialogTestField.java new file mode 100644 index 000000000..13c2905b9 --- /dev/null +++ b/src/test/java/com/rapidminer/gui/properties/SettingsDialogTestField.java @@ -0,0 +1,192 @@ +/** + * Copyright (C) 2001-2018 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.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import com.rapidminer.gui.RapidMinerGUI; +import com.rapidminer.gui.properties.SettingsItem.Type; +import com.rapidminer.gui.tools.ResourceAction; +import com.rapidminer.gui.tools.SwingTools; +import com.rapidminer.operator.Operator; +import com.rapidminer.parameter.ParameterHandler; +import com.rapidminer.parameter.ParameterType; +import com.rapidminer.parameter.ParameterTypeString; +import com.rapidminer.parameter.ParameterTypeStringCategory; +import com.rapidminer.parameter.ParameterTypeSuggestion; +import com.rapidminer.parameter.SimpleListBasedParameterHandler; +import com.rapidminer.parameter.SuggestionProvider; +import com.rapidminer.parameter.conditions.EqualStringCondition; +import com.rapidminer.tools.ParameterService; +import com.rapidminer.tools.ProgressListener; + + +/** + * Quick testing possibility for the updated {@link SettingsDialog}. Runs the dialog and shows two tabs. + * There is a hidden parameter that should not be shown and a drop down parameter with 5 values in the first sub group + * on the first tab. The first two values trigger two different parameters in the second sub group on the first tab. + * Values 3 and 4 trigger parameters on the second tab. + * + * @author Jan Czogalla + * @since 9.1 + */ +public class SettingsDialogTestField { + + private static final String[] GROUPS = prefixedNumberedValues(2, "group_"); + private static final String[] SUBGROUPS = prefixedNumberedValues(4, "subgroup_"); + private static final String[] PARAMETERS = prefixedNumberedValues(7, "param_"); + + private static final Map KEY_TO_GROUP_KEY = new HashMap<>(); + private static final Map KEY_TO_TYPE = new HashMap<>(); + private static final Map KEY_TO_PARAM_TYPE = new HashMap<>(); + private static ParameterHandler handler; + + public static void main(String[] args) { + initRMProps(); + init(); + ParameterHandler handler = prepareHandler(); + SettingsItemProvider provider = prepareProvider(handler); + SwingTools.invokeLater(() -> new SettingsDialog(handler, provider, null).setVisible(true)); + } + + private static void initRMProps() { + ParameterService.init(); + ParameterService.setParameterValue(RapidMinerGUI.PROPERTY_FONT_CONFIG, "Standard fonts"); + } + + private static void init() { + for (String group : GROUPS) { + KEY_TO_TYPE.put(group, Type.GROUP); + } + for (int i = 0; i < SUBGROUPS.length; i++) { + String subgroup = SUBGROUPS[i]; + KEY_TO_TYPE.put(subgroup, Type.SUB_GROUP); + KEY_TO_GROUP_KEY.put(subgroup, GROUPS[i/2]); + } + for (int i = 0; i < PARAMETERS.length; i++) { + String parameter = PARAMETERS[i]; + KEY_TO_GROUP_KEY.put(parameter, SUBGROUPS[i/2]); + } + String[] conditionValues = prefixedNumberedValues(5, "value_"); + ParameterTypeStringCategory category = new ParameterTypeStringCategory(PARAMETERS[0], "", conditionValues, conditionValues[4]); + category.setEditable(false); + KEY_TO_PARAM_TYPE.put(PARAMETERS[0], category); + ParameterTypeString hiddenParameter = new ParameterTypeString(PARAMETERS[1], "", "hidden parameter"); + hiddenParameter.setHidden(true); + KEY_TO_PARAM_TYPE.put(PARAMETERS[1], hiddenParameter); + for (int i = 0; i < conditionValues.length - 1; i++) { + String conditionValue = conditionValues[i]; + ParameterType parameter = new ParameterTypeString(PARAMETERS[i + 2], "", "visible for " + conditionValue); + parameter.registerDependencyCondition(new EqualStringCondition(null, PARAMETERS[0], false, conditionValue)); + KEY_TO_PARAM_TYPE.put(parameter.getKey(), parameter); + } + ParameterTypeSuggestion suggestions = new ParameterTypeSuggestion(PARAMETERS[6], "", new SuggestionProvider() { + @Override + public List getSuggestions(Operator op, ProgressListener pl) { + return KEY_TO_PARAM_TYPE.values().stream().filter(pt -> !pt.isHidden()).map(ParameterType::getKey).collect(Collectors.toList()); + } + + @Override + public ResourceAction getAction() { + return null; + } + }); + KEY_TO_PARAM_TYPE.put(PARAMETERS[6], suggestions); + } + + private static ParameterHandler prepareHandler() { + ArrayList parameterTypes = new ArrayList<>(KEY_TO_PARAM_TYPE.values()); + SimpleListBasedParameterHandler handler = new SimpleListBasedParameterHandler() { + @Override + public List getParameterTypes() { + return parameterTypes; + } + }; + parameterTypes.stream().flatMap(pt -> pt.getConditions().stream()).forEach(pc -> pc.setParameterHandler(handler)); + return handler; + } + + private static SettingsItemProvider prepareProvider(ParameterHandler handler) { + SettingsItemProvider provider = new AbstractSettingsItemProvider() { + @Override + protected URI getGroupDefinitions() throws URISyntaxException { + // not used + return null; + } + + + @Override + public String getValue(String key) { + return handler.getParameters().getParameterOrNull(key); + } + + @Override + public SettingsItem createAndAddItem(String key, Type type) { + SettingsItem parent = null; + + // If type is parameter, choose or create the related group + String groupKey = KEY_TO_GROUP_KEY.get(key); + if (type != Type.GROUP) { + if (!containsKey(groupKey)) { + parent = createAndAddItem(groupKey, KEY_TO_TYPE.get(groupKey)); + } else { + parent = get(groupKey); + } + } + + // Create new SettingsItem + SettingsItem settingsItem = new SettingsItem(groupKey, key, parent, type); + + // Add to SettingsItems + put(key, settingsItem); + + return settingsItem; + } + + @Override + public boolean isGroupingLoaded() { + return false; + } + + @Override + public void applyValues(ParameterHandler parameterHandler) { + // noop + } + + @Override + public void saveSettings() { + // noop + } + }; + KEY_TO_GROUP_KEY.keySet().stream().filter(k -> !KEY_TO_TYPE.containsKey(k)).forEach(k -> provider.createAndAddItem(k, Type.PARAMETER)); + return provider; + } + + private static String[] prefixedNumberedValues(int max, String prefix) { + return IntStream.rangeClosed(1, max).mapToObj(i -> prefix + i).toArray(String[]::new); + } + +} \ No newline at end of file diff --git a/src/test/java/com/rapidminer/operator/nio/DateFormatGuesserTest.java b/src/test/java/com/rapidminer/operator/nio/DateFormatGuesserTest.java new file mode 100644 index 000000000..24ab88921 --- /dev/null +++ b/src/test/java/com/rapidminer/operator/nio/DateFormatGuesserTest.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2001-2018 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.operator.nio; + +import static com.rapidminer.parameter.ParameterTypeDateFormat.DATE_FORMAT_DD_DOT_MM_DOT_YYYY; +import static com.rapidminer.parameter.ParameterTypeDateFormat.DATE_FORMAT_MM_DD_YYYY; +import static com.rapidminer.parameter.ParameterTypeDateFormat.DATE_TIME_FORMAT_MM_DD_YYYY_H_MM_A; +import static com.rapidminer.parameter.ParameterTypeDateFormat.TIME_FORMAT_H_MM_A; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + +/** + * Tests for the {@link DateFormatGuesser}. + * + * @author Jan Czogalla + * @since 9.1 + */ +public class DateFormatGuesserTest { + + private static final String[] DATE_FORMATS = {DATE_FORMAT_MM_DD_YYYY, DATE_FORMAT_DD_DOT_MM_DOT_YYYY, DATE_TIME_FORMAT_MM_DD_YYYY_H_MM_A, TIME_FORMAT_H_MM_A}; + // date format examples for MM/dd/yyyy, dd.MM.yyyy, MM/dd/yyyy hh:mm a, hh:mm a + private static final String[] FORMATTED_DATES = {"08/20/1999", "20.08.1999", "08/20/1999 08:15 AM", "08:15 AM"}; + private static final int ROW_COUNT = 100; + private static final double DATE_COLUMN_CONFIDENCE = 0.5; + + @Test + public void testSingleAttributeWithOnlyUnmatched() { + DateFormatGuesser guesser = new DateFormatGuesser(1, null, null); + String[] unmatched = {"Test"}; + for (int i = 0; i < ROW_COUNT; i++) { + guesser.count(unmatched); + } + Map results = guesser.getResults(DATE_COLUMN_CONFIDENCE); + for (String dateFormat : DATE_FORMATS) { + Assert.assertTrue(unmatched[0] + " did match " + dateFormat + ", but should not", Double.isNaN(results.get(dateFormat))); + } + } + + @Test + public void testSingleAttributeWithOneDateType() { + for (int i = 0; i < DATE_FORMATS.length; i++) { + Map map = testSingleAttribute(new int[]{i}, ROW_COUNT); + Assert.assertTrue("Formats did not match: " + DATE_FORMATS[i] + " " + FORMATTED_DATES[i], + map.get(DATE_FORMATS[i]) > 0); + } + } + + @Test + public void testSingleAttributeWithMultipleDateTypes() { + for (int i = 1; i < DATE_FORMATS.length; i++) { + for (int j = 0; j < i; j++) { + Map map = testSingleAttribute(new int[]{j, i}, ROW_COUNT); + Assert.assertTrue("Formats did not match: " + DATE_FORMATS[j] + " " + FORMATTED_DATES[j], + map.get(DATE_FORMATS[j]) > 0); + Assert.assertTrue("Formats did not match: " + DATE_FORMATS[i] + " " + FORMATTED_DATES[i], + map.get(DATE_FORMATS[i]) > 0); + } + } + } + + @Test + public void testMultipleAttributesWithSeparateDateTypes() { + DateFormatGuesser guesser = testMultipleAttributes(new int[][]{{0}, {1}, {2}, {3}}, ROW_COUNT, 4); + for (int i = 0; i < DATE_FORMATS.length; i++) { + Assert.assertTrue("Date format not present in this column: " + i, + guesser.getDateAttributes(DATE_FORMATS[i], .9).contains(i)); + } + } + + private Map testSingleAttribute(int[] indices, int rows) { + return testMultipleAttributes(new int[][]{indices}, rows, 1).getResults(DATE_COLUMN_CONFIDENCE); + } + + private DateFormatGuesser testMultipleAttributes(int[][] indices, int rows, int columns) { + DateFormatGuesser guesser = new DateFormatGuesser(columns, null, null); + for (int i = 0; i < rows; i++) { + String[] rowValues = new String[columns]; + for (int j = 0; j < columns; j++) { + int rowIndex = i % indices[j].length; + rowValues[j] = FORMATTED_DATES[indices[j][rowIndex]]; + } + guesser.count(rowValues); + } + return guesser; + } +} \ No newline at end of file diff --git a/src/test/java/com/rapidminer/operator/tools/SerializationToStreamTest.java b/src/test/java/com/rapidminer/operator/tools/SerializationToStreamTest.java new file mode 100644 index 000000000..69095c13d --- /dev/null +++ b/src/test/java/com/rapidminer/operator/tools/SerializationToStreamTest.java @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2001-2018 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.operator.tools; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.Future; + +import org.junit.Before; +import org.junit.Test; + +import com.rapidminer.RapidMiner; +import com.rapidminer.adaption.belt.IOTable; +import com.rapidminer.belt.BeltConverter; +import com.rapidminer.core.concurrency.ConcurrencyContext; +import com.rapidminer.core.concurrency.ExecutionStoppedException; +import com.rapidminer.example.Attribute; +import com.rapidminer.example.ExampleSet; +import com.rapidminer.example.table.AttributeFactory; +import com.rapidminer.example.utils.ExampleSets; +import com.rapidminer.test_utils.RapidAssert; +import com.rapidminer.tools.Ontology; + + +/** + * Tests the the {@link IOObjectSerializer} w.r.t. {@link ExampleSet}s and {@link IOTable}s which are both streamed via + * {@link ExampleSetToStream}. + * + * @author Gisa Meier + */ +public class SerializationToStreamTest { + + private ExampleSet testSet; + + @Before + public void setup() { + Attribute numeric = AttributeFactory.createAttribute("numeric", Ontology.NUMERICAL); + Attribute real = AttributeFactory.createAttribute("real", Ontology.REAL); + Attribute integer = AttributeFactory.createAttribute("integer", Ontology.INTEGER); + Attribute dateTime = AttributeFactory.createAttribute("date_time", Ontology.DATE_TIME); + Attribute date = AttributeFactory.createAttribute("date", Ontology.DATE); + Attribute time = AttributeFactory.createAttribute("time", Ontology.TIME); + Attribute nominal = AttributeFactory.createAttribute("nominal", Ontology.NOMINAL); + Attribute string = AttributeFactory.createAttribute("string", Ontology.STRING); + Attribute polynominal = AttributeFactory.createAttribute("polynominal", Ontology.POLYNOMINAL); + Attribute binominal = AttributeFactory.createAttribute("binominal", Ontology.BINOMINAL); + Attribute path = AttributeFactory.createAttribute("path", Ontology.FILE_PATH); + List attributes = + Arrays.asList(numeric, real, integer, dateTime, date, time, nominal, string, polynominal, binominal, + path); + for (int i = 0; i < 5; i++) { + nominal.getMapping().mapString("nominalValue" + i); + } + for (int i = 0; i < 14; i++) { + string.getMapping().mapString("veryVeryLongStringValue" + i); + } + for (int i = 0; i < 6; i++) { + polynominal.getMapping().mapString("polyValue" + i); + } + for (int i = 0; i < 2; i++) { + binominal.getMapping().mapString("binominalValue" + i); + } + for (int i = 0; i < 3; i++) { + path.getMapping().mapString("//folder/sufolder/subsubfolder/file" + i); + } + Random random = new Random(); + testSet = ExampleSets.from(attributes).withBlankSize(100) + .withColumnFiller(numeric, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextDouble()) + .withColumnFiller(real, i -> random.nextDouble() > 0.7 ? Double.NaN : 42 + random.nextDouble()) + .withColumnFiller(integer, + i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(100)) + .withColumnFiller(dateTime, i -> random.nextDouble() > 0.7 ? Double.NaN : (i % 3 == 0 ? -1 : 1) + * 1515410698d + random.nextInt(1000)) + .withColumnFiller(date, i -> random.nextDouble() > 0.7 ? Double.NaN : (i % 3 == 0 ? -1 : 1) * + 230169600000d + random.nextInt(100) * 1000d * 60 * 60 * 24) + .withColumnFiller(time, i -> random.nextDouble() > 0.7 ? Double.NaN : + (i % 3 == 0 ? -1 : 1) * Math.floor(Math.random() * 60 * 60 * 24 * 1000)) + .withColumnFiller(nominal, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(5)) + .withColumnFiller(string, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(4)) + .withColumnFiller(polynominal, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(6)) + .withColumnFiller(binominal, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(2)) + .withColumnFiller(path, i -> random.nextDouble() > 0.7 ? Double.NaN : random.nextInt(3)) + .build(); + + RapidMiner.initAsserters(); + } + + + @Test + public void testExampleSet() throws IOException { + ExampleSet set = testSet; + ExampleSet backAndForth = (ExampleSet) readFromArray(writeToArray(set)); + RapidAssert.assertEquals("ExampleSets are not equal", set, backAndForth); + } + + @Test + public void testTable() throws IOException { + ExampleSet set = testSet; + IOTable table = BeltConverter.convert(set, CONTEXT); + + ExampleSet backAndForth = (ExampleSet) readFromArray(writeToArray(table)); + RapidAssert.assertEquals("ExampleSets are not equal", set, backAndForth); + } + + @Test + public void testTableWithOutDatetime() throws IOException { + ExampleSet set = (ExampleSet) testSet.clone(); + set.getAttributes().remove(set.getAttributes().get("date_time")); + set.getAttributes().remove(set.getAttributes().get("time")); + set.getAttributes().remove(set.getAttributes().get("date")); + IOTable table = BeltConverter.convert(set, CONTEXT); + + ExampleSet backAndForth = (ExampleSet) readFromArray(writeToArray(table)); + RapidAssert.assertEquals("ExampleSets are not equal", set, backAndForth); + } + + private byte[] writeToArray(Object object) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + IOObjectSerializer.getInstance().serialize(stream, object); + return stream.toByteArray(); + } + + private Object readFromArray(byte[] array) throws IOException { + ByteArrayInputStream stream = new ByteArrayInputStream(array); + return IOObjectSerializer.getInstance().deserialize(stream); + } + + + private static final ConcurrencyContext CONTEXT = new ConcurrencyContext() { + + private ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors()); + + @Override + public List> submit(List> callables) throws IllegalArgumentException { + List> futures = new ArrayList<>(); + for (Callable callable : callables) { + futures.add(pool.submit(callable)); + } + return futures; + } + + @Override + public List call(List> callables) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + List> futures = submit(callables); + List results = new ArrayList<>(); + for (Future future : futures) { + try { + results.add(future.get()); + } catch (InterruptedException e) { + throw new RuntimeException("must not happen"); + } + } + return results; + } + + @Override + public void run(List runnables) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + } + + @Override + public List invokeAll(List> tasks) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + return null; + } + + @Override + public T invoke(ForkJoinTask task) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + return null; + } + + @Override + public int getParallelism() { + return pool.getParallelism(); + } + + @Override + public List collectResults(List> futures) + throws ExecutionException, ExecutionStoppedException, IllegalArgumentException { + return null; + } + + @Override + public void checkStatus() throws ExecutionStoppedException { + } + + }; + +} \ No newline at end of file diff --git a/src/test/java/com/rapidminer/search/GlobalSearchHandlerTest.java b/src/test/java/com/rapidminer/search/GlobalSearchHandlerTest.java index 6e1fafab5..027cc3b86 100644 --- a/src/test/java/com/rapidminer/search/GlobalSearchHandlerTest.java +++ b/src/test/java/com/rapidminer/search/GlobalSearchHandlerTest.java @@ -1,5 +1,4 @@ /** - * * Copyright (C) 2001-2018 by RapidMiner and the contributors * Complete list of developers available at our web site: * @@ -76,7 +75,8 @@ public void searchNullQuery() throws ParseException { int maxNumberOfResults = 23; boolean highlightResult = false; ScoreDoc after = null; - GlobalSearchResult searchResult = GlobalSearchHandler.INSTANCE.search(null, categories, simpleMode, maxNumberOfResults, highlightResult, after); + final int moreResults = 0; + GlobalSearchResult searchResult = GlobalSearchHandler.INSTANCE.search(null, categories, simpleMode, maxNumberOfResults, moreResults, highlightResult, after); Assert.assertEquals("The result has to be empty since nothing was added to the Global Search", 0, searchResult.getNumberOfResults()); } @@ -88,11 +88,11 @@ public void searchEmptyQuery() throws ParseException { int maxNumberOfResults = 23; boolean highlightResult = false; ScoreDoc after = null; - GlobalSearchResult searchResult = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, highlightResult, after); + GlobalSearchResult searchResult = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, 0, highlightResult, after); Assert.assertEquals("The result has to be empty since nothing was added to the Global Search", 0, searchResult.getNumberOfResults()); searchQueryString = " \t \n \t \r "; - searchResult = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, highlightResult, after); + searchResult = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, 0, highlightResult, after); Assert.assertEquals("The result has to be empty since nothing was added to the Global Search", 0, searchResult.getNumberOfResults()); } @@ -125,7 +125,7 @@ public void testSearch() throws ParseException { } private GlobalSearchResult checkGlobalSearchResult(List categories, boolean simpleMode, int maxNumberOfResults, boolean highlightResult, ScoreDoc after, String searchQueryString, int expected) throws ParseException { - GlobalSearchResult life = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, highlightResult, after); + GlobalSearchResult life = GlobalSearchHandler.INSTANCE.search(searchQueryString, categories, simpleMode, maxNumberOfResults, 0, highlightResult, after); Assert.assertEquals("Should have found " + expected + " results for " + (simpleMode ? "simple" : "advanced") + " searchQuery '" + searchQueryString + "'" + (after != null ? " after given ScoreDoc" : ""), expected, life.getNumberOfResults()); if (highlightResult) { Assert.assertEquals("Should have found " + expected + " highlight results for " + (simpleMode ? "simple" : "advanced") + " searchQuery '" + searchQueryString + "'" + (after != null ? " after given ScoreDoc" : ""), expected, life.getBestFragments().size()); diff --git a/src/test/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSourceDataTest.java b/src/test/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSourceDataTest.java index 843c3f097..fe5cad213 100644 --- a/src/test/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSourceDataTest.java +++ b/src/test/java/com/rapidminer/studio/io/data/internal/file/csv/CSVDataSourceDataTest.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.studio.io.data.internal.file.csv; import static org.junit.Assert.assertEquals; @@ -413,7 +413,7 @@ public void noHeaderRowDefined() throws DataSetException, ParseException { } @Test - public void missingInHeaderRow() throws DataSetException, ParseException { + public void missingInHeaderRow() throws DataSetException { try (CSVDataSource dataSource = new CSVDataSource()) { dataSource.setLocation(missingInHeaderRow.toPath()); @@ -567,7 +567,7 @@ public void firstDataRowDefined() throws DataSetException, ParseException { } @Test(expected = StartRowNotFoundException.class) - public void wrongColumnSeparator() throws DataSetException, ParseException { + public void wrongColumnSeparator() throws DataSetException { try (CSVDataSource dataSource = new CSVDataSource()) { dataSource.setLocation(simpleTestFile.toPath()); dataSource.getResultSetConfiguration().setColumnSeparators("\t"); diff --git a/src/test/java/com/rapidminer/tools/AuthCacheClearingTest.java b/src/test/java/com/rapidminer/tools/AuthCacheClearingTest.java new file mode 100644 index 000000000..820423f43 --- /dev/null +++ b/src/test/java/com/rapidminer/tools/AuthCacheClearingTest.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2001-2018 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.tools; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import static org.junit.Assert.*; + +import org.junit.Test; + + +/** + * This test copies & pastes the {@link com.rapidminer.tools.WebServiceTools#clearAuthCache} code as it would swallow + * any exceptions. The purpose of this test is to make sure the sun classes currently in use will still be available in + * future, OpenJDK Java builds. + * + * @author Marco Boeck + * @since 9.1 + */ +public class AuthCacheClearingTest { + + @Test + public void testWebServiceToolsClearAuthCache() { + // remove this test once WebServiceTools#clearAuthCache() no longer uses the code below + try { + Class authCacheValueClass = Class.forName("sun.net.www.protocol.http.AuthCacheValue"); + Class authCacheClass = Class.forName("sun.net.www.protocol.http.AuthCache"); + Class authCacheImplClass = Class.forName("sun.net.www.protocol.http.AuthCacheImpl"); + Constructor authCacheImplConstructor = authCacheImplClass.getConstructor(); + Method setAuthCacheMethod = authCacheValueClass.getMethod("setAuthCache", authCacheClass); + setAuthCacheMethod.invoke(null, authCacheImplConstructor.newInstance()); + } catch (Throwable t) { + t.printStackTrace(); + fail("Clearing Auth Cache failed! " + t.getMessage()); + } + } +} diff --git a/src/test/java/com/rapidminer/tools/StrictDecimalFormatTest.java b/src/test/java/com/rapidminer/tools/StrictDecimalFormatTest.java index 919381878..1430ca0a9 100644 --- a/src/test/java/com/rapidminer/tools/StrictDecimalFormatTest.java +++ b/src/test/java/com/rapidminer/tools/StrictDecimalFormatTest.java @@ -1,21 +1,21 @@ /** * Copyright (C) 2001-2018 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.tools; import static org.junit.Assert.assertEquals; @@ -31,7 +31,6 @@ * Tests the parser method of {@link StrictDecimalFormat}. * * @author Peter Hellinger - * */ public class StrictDecimalFormatTest { @@ -67,6 +66,18 @@ public void parseInvalidExponent() { } } + @Test + public void parsePositiveExponent() throws ParseException { + assertEquals(12330000L, strictDecimalFormat.parse("1.233e+7")); + assertEquals(59876000L, strictDecimalFormat.parse("5.9876E+7")); + } + + @Test + public void parseNegativeExponent() throws ParseException { + assertEquals(0.0000001233, strictDecimalFormat.parse("1.233e-7")); + assertEquals(0.00000041973, strictDecimalFormat.parse("4.1973E-7")); + } + @Test public void parseInvalidDecimalSeparator() { try { @@ -77,6 +88,16 @@ public void parseInvalidDecimalSeparator() { } } + @Test + public void parseEmptyExponent() { + try { + strictDecimalFormat.parse("1,2337E"); + fail(); + } catch (ParseException e) { + assertNotNull(e.getMessage()); + } + } + @Test public void parseCommaDecimalSeparator() { StrictDecimalFormat strictDecimalFormatComma = new StrictDecimalFormat(','); @@ -99,25 +120,25 @@ public void parseEmptyStrings() { try { strictDecimalFormatComma.parse(""); fail(); - } catch (ParseException e){ + } catch (ParseException e) { assertNotNull(e.getMessage()); } try { strictDecimalFormatComma.parse(" "); fail(); - } catch (ParseException e){ + } catch (ParseException e) { assertNotNull(e.getMessage()); } try { strictDecimalFormatComma.parse("\n"); fail(); - } catch (ParseException e){ + } catch (ParseException e) { assertNotNull(e.getMessage()); } try { strictDecimalFormatComma.parse("\t"); fail(); - } catch (ParseException e){ + } catch (ParseException e) { assertNotNull(e.getMessage()); } } diff --git a/src/test/java/com/rapidminer/tools/i18n/ExtensibleResourceBundleTest.java b/src/test/java/com/rapidminer/tools/i18n/ExtensibleResourceBundleTest.java new file mode 100644 index 000000000..2ce06b3fe --- /dev/null +++ b/src/test/java/com/rapidminer/tools/i18n/ExtensibleResourceBundleTest.java @@ -0,0 +1,151 @@ +/** + * Copyright (C) 2001-2018 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.tools.i18n; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.ResourceBundle; + +import org.junit.Assert; +import org.junit.Test; + +import com.rapidminer.tools.ExtensibleResourceBundle; + + +/** + * Tests the behavior of the ExtensibleResourceBundle class + *

    + * The tests are very limited and don't contain hierarchical ResourceBundles + * + * @author Jonas Wilms-Pfau + * @since 9.1.0 + */ +public class ExtensibleResourceBundleTest { + + /** + * Bundle that can hold a single key-value pair, no language hierarchy + */ + private static final class DummyBundle extends ResourceBundle { + private String key; + private String value; + private Locale locale; + + public DummyBundle(String key, String value, String language) { + this.key = key; + this.value = value; + this.locale = Locale.forLanguageTag(language); + } + + @Override + protected Object handleGetObject(String key) { + if (key.equals(this.key)) { + return value; + } else { + return null; + } + } + + @Override + public Enumeration getKeys() { + return new Enumeration() { + private boolean found = false; + + @Override + public boolean hasMoreElements() { + return !found; + } + + @Override + public String nextElement() { + found = true; + return key; + } + }; + } + + @Override + public Locale getLocale() { + return locale; + } + } + + @Test + public void testOrder() { + Locale.setDefault(Locale.forLanguageTag("de")); + String key = "foobar"; + String expected = "second"; + ExtensibleResourceBundle test = new ExtensibleResourceBundle(new DummyBundle(key, "root", "")); + // first registered german language + test.addResourceBundle(new DummyBundle(key, expected, "de")); + test.addResourceBundle(new DummyBundle(key, "third", "")); + test.addResourceBundle(new DummyBundle(key, "fourth", "de")); + Assert.assertEquals(expected, test.getString(key)); + } + + @Test + public void testOrderWithCountry() { + Locale.setDefault(Locale.forLanguageTag("de-AT")); + String key = "foobar"; + String expected = "second"; + ExtensibleResourceBundle test = new ExtensibleResourceBundle(new DummyBundle(key, "root", "")); + test.addResourceBundle(new DummyBundle(key, "first", "de")); + test.addResourceBundle(new DummyBundle("bla", "bla", "de-AT")); + // first registered german austrian bundle that matches the key + test.addResourceBundle(new DummyBundle(key, expected, "de-AT")); + test.addResourceBundle(new DummyBundle(key, "third", "de-DE")); + test.addResourceBundle(new DummyBundle(key, "fourth", "de-AT")); + Assert.assertEquals(expected, test.getString(key)); + } + + @Test + public void testIcon() { + Locale.setDefault(Locale.forLanguageTag("de")); + String key = "rapidminer.icon"; + String expected = "rapidminer.png"; + ExtensibleResourceBundle test = new ExtensibleResourceBundle(new DummyBundle(key, expected, "")); + test.addResourceBundle(new DummyBundle(key, "evil.tiff", "de")); + test.addResourceBundle(new DummyBundle(key, "ugly.jpg", "de")); + Assert.assertEquals(expected, test.getString(key)); + } + + @Test + public void testNewIcon() { + Locale.setDefault(Locale.forLanguageTag("de")); + String key = "new.icon"; + String expected = "extension.png"; + ExtensibleResourceBundle test = new ExtensibleResourceBundle(new DummyBundle("rapidminer.icon", "rapidminer.png", "")); + test.addResourceBundle(new DummyBundle(key, expected, "de")); + test.addResourceBundle(new DummyBundle(key, "evil.tiff", "de")); + Assert.assertEquals(expected, test.getString(key)); + } + + + @Test + public void testFallback() { + Locale.setDefault(Locale.forLanguageTag("ja")); + String key = "YES"; + String expected = "yes"; + ExtensibleResourceBundle test = new ExtensibleResourceBundle(new DummyBundle(key, expected, "")); + test.addResourceBundle(new DummyBundle(key, "oui", "")); + test.addResourceBundle(new DummyBundle(key, "ja", "")); + test.addResourceBundle(new DummyBundle(key, "si", "")); + Assert.assertEquals(expected, test.getString(key)); + } + +} diff --git a/src/test/java/com/rapidminer/tools/update/internal/MigrationManagerTest.java b/src/test/java/com/rapidminer/tools/update/internal/MigrationManagerTest.java new file mode 100644 index 000000000..39467d4e8 --- /dev/null +++ b/src/test/java/com/rapidminer/tools/update/internal/MigrationManagerTest.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2001-2018 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.tools.update.internal; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.rapidminer.gui.tools.VersionNumber; + + +/** + * Tests for the necessary Tests retrieved from the {@link MigrationManager} + * + * @author Andreas Timm + * @since 9.1.0 + */ +public class MigrationManagerTest { + + @Test + public void checkNull() { + final List necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(null, null); + Assert.assertNotNull(necessaryMigrationSteps); + Assert.assertTrue(necessaryMigrationSteps.isEmpty()); + } + + @Test + public void checkTests() { + // right now there is only the migration from any version to 9.1.0 so all other versions around that are not to be migrated + VersionNumber VN_8_0_0 = new VersionNumber(8, 0, 0); + VersionNumber VN_9_0_0 = new VersionNumber(9, 0, 0); + VersionNumber VN_9_1_0 = new VersionNumber(9, 1, 0); + + List necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(VN_8_0_0, VN_8_0_0); + Assert.assertEquals(0, necessaryMigrationSteps.size()); + + necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(VN_8_0_0, VN_9_0_0); + Assert.assertEquals(0, necessaryMigrationSteps.size()); + + necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(VN_8_0_0, VN_9_1_0); + Assert.assertEquals(1, necessaryMigrationSteps.size()); + + necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(VN_9_0_0, VN_9_1_0); + Assert.assertEquals(1, necessaryMigrationSteps.size()); + + necessaryMigrationSteps = MigrationManager.getNecessaryMigrationSteps(VN_9_1_0, VN_9_1_0); + Assert.assertEquals(0, necessaryMigrationSteps.size()); + } +}