blob: d95a8d8d547db1e411c06f91470680472f6241c3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.javafx2.project;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.openide.filesystems.FileObject;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
/**
* Project configurations maintenance class
*
* Getter/Setter naming conventions:
* "Property" in method name -> method deals with single properties in configuration given by method parameter config
* "Default" in method name -> method deals with properties in default configuration
* "Active" in method name -> method deals with properties in currently chosen configuration
* "Transparent" in method name -> method deals with property in configuration fiven by method parameter config if
* exists, or with property in default configuration otherwise. This is to provide simple access to
* union of default and non-default properties that are to be presented to users in non-default configurations
*
* @author Petr Somol
*/
public class JFXProjectConfigurations {
private static final Logger LOG = Logger.getLogger(JFXProjectConfigurations.class.getName());
public static final String APPLICATION_ARGS = ProjectProperties.APPLICATION_ARGS;
public static final String DEFAULT_CONFIG_NAME = "default"; //NOI18N
public static final String APP_PARAM_PREFIX = "javafx.param."; // NOI18N
public static final String APP_PARAM_SUFFIXES[] = new String[] { "name", "value", "hidden" }; // NOI18N
public static final String APP_PARAM_CONNECT_SIGN = "="; // NOI18N
public static final String APP_MANIFEST_PREFIX = "javafx.manifest.entry."; // NOI18N
public static final String APP_MANIFEST_SUFFIXES[] = new String[] { "name", "value", "hidden" }; // NOI18N
public static final String APP_MANIFEST_CONNECT_SIGN = ": "; // NOI18N
private static final String MULTI_PROPERTY_STRING = "MultiProperty"; //NOI18N
private static final String MULTI_PROPERTY_EMPTY = "empty"; // NOI18N
public static final String APP_MULTIPROP_HIDDEN_TRUE = "true"; // NOI18N
// folders and files
public static final String PROJECT_CONFIGS_DIR = "nbproject/configs"; // NOI18N
public static final String PROJECT_PRIVATE_CONFIGS_DIR = "nbproject/private/configs"; // NOI18N
public static final String PROPERTIES_FILE_EXT = "properties"; // NOI18N
// the following should be J2SEConfigurationProvider.CONFIG_PROPS_PATH which is now inaccessible from here
public static final String CONFIG_PROPERTIES_FILE = "nbproject/private/config.properties"; // NOI18N
public static String getSharedConfigFilePath(final @NonNull String config)
{
return PROJECT_CONFIGS_DIR + "/" + config + "." + PROPERTIES_FILE_EXT; // NOI18N
}
public static String getPrivateConfigFilePath(final @NonNull String config)
{
return PROJECT_PRIVATE_CONFIGS_DIR + "/" + config + "." + PROPERTIES_FILE_EXT; // NOI18N
}
private Map<String/*|null*/,Map<String,String/*|null*/>/*|null*/> RUN_CONFIGS;
private MultiProperty appParams;
private MultiProperty appManifestEntries;
private Set<String> ERASED_CONFIGS;
private BoundedPropertyGroups groups = new BoundedPropertyGroups();
private String active;
private FileObject projectDir;
// list of all properties related to project configurations (excluding application parameter properties that are handled separately)
private List<String> PROJECT_PROPERTIES = new ArrayList<String>();
// list of those properties that should be stored in private.properties instead of project.properties
private List<String> PRIVATE_PROPERTIES = new ArrayList<String>();
// list of properties that, if set, should later not be overriden by changes in default configuration
// (useful for keeping pre-defined configurations that do not change unexpectedly after changes in default config)
// Note that the standard behavior is: when setting a default property, the property is checked in all configs
// and reset if its value in any non-def config is equal to that in default config
private List<String> STATIC_PROPERTIES = new ArrayList<String>();
// defaults if missing - on read, substitute missing property values by those registered here
private Map<String, String> DEFAULT_IF_MISSING = new HashMap<String, String>();
// on save remove the following props from file if they are empty
private List<String> CLEAN_EMPTY_PROJECT_PROPERTIES = new ArrayList<String>();
private List<String> CLEAN_EMPTY_PRIVATE_PROPERTIES = new ArrayList<String>();
private Comparator<String> getComparator() {
return new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1 != null ? (s2 != null ? s1.compareTo(s2) : 1) : (s2 != null ? -1 : 0);
}
};
}
JFXProjectConfigurations(final @NonNull FileObject projectDirFO) {
projectDir = projectDirFO;
reset();
}
public void registerProjectProperties(String[] props) {
if(props != null) {
PROJECT_PROPERTIES.addAll(Arrays.asList(props));
}
}
public void registerPrivateProperties(String[] props) {
if(props != null) {
PRIVATE_PROPERTIES.addAll(Arrays.asList(props));
}
}
public void registerStaticProperties(String[] props) {
if(props != null) {
STATIC_PROPERTIES.addAll(Arrays.asList(props));
}
}
public void registerDefaultsIfMissing(Map<String, String> defaults) {
if(defaults != null) {
DEFAULT_IF_MISSING.putAll(defaults);
}
}
public void registerCleanEmptyProjectProperties(String[] props) {
if(props != null) {
CLEAN_EMPTY_PROJECT_PROPERTIES.addAll(Arrays.asList(props));
}
}
public void registerCleanEmptyPrivateProperties(String[] props) {
if(props != null) {
CLEAN_EMPTY_PRIVATE_PROPERTIES.addAll(Arrays.asList(props));
}
}
public void resetProjectProperties() {
PROJECT_PROPERTIES.clear();
}
public void resetPrivateProperties() {
PRIVATE_PROPERTIES.clear();
}
public void resetStaticProperties() {
STATIC_PROPERTIES.clear();
}
public void resetDefaultsIfMissing() {
DEFAULT_IF_MISSING.clear();
}
public void resetCleanEmptyProjectProperties() {
CLEAN_EMPTY_PROJECT_PROPERTIES.clear();
}
public void resetCleanEmptyPrivateProperties() {
CLEAN_EMPTY_PRIVATE_PROPERTIES.clear();
}
public void reset() {
RUN_CONFIGS = new TreeMap<String,Map<String,String>>(getComparator());
ERASED_CONFIGS = null;
appParams = new MultiProperty(APP_PARAM_PREFIX, APP_PARAM_SUFFIXES, APP_PARAM_CONNECT_SIGN);
appManifestEntries = new MultiProperty(APP_MANIFEST_PREFIX, APP_MANIFEST_SUFFIXES, APP_MANIFEST_CONNECT_SIGN);
}
private boolean configNameWrong(String config) {
return config !=null && config.contains(DEFAULT_CONFIG_NAME); //NOI18N
}
public final void defineGroup(String groupName, Collection<String> props) {
groups.defineGroup(groupName, props);
}
public final void clearGroup(String groupName) {
groups.clearGroup(groupName);
}
public final void clearAllGroups() {
groups.clearAllGroups();
}
public boolean isBound(String prop) {
return groups.isBound(prop);
}
public Collection<String> getBoundedProperties(String prop) {
return groups.getBoundedProperties(prop);
}
//==========================================================
public String getActive() {
return active;
}
public void setActive(String config) {
assert !configNameWrong(config);
active = config;
}
//==========================================================
public boolean hasConfig(String config) {
assert !configNameWrong(config);
return RUN_CONFIGS.containsKey(config);
}
public boolean isConfigEmpty(String config) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap != null) {
return configMap.isEmpty();
}
return true;
}
public boolean isDefaultConfigEmpty() {
return isConfigEmpty(null);
}
public boolean isActiveConfigEmpty() {
return isConfigEmpty(getActive());
}
//----------------------------------------------------------
public Set<String> getConfigNames() {
return Collections.unmodifiableSet(RUN_CONFIGS.keySet());
}
private Map<String,String/*|null*/> getConfigUnmodifyable(String config) {
assert !configNameWrong(config);
return Collections.unmodifiableMap(RUN_CONFIGS.get(config));
}
private Map<String,String/*|null*/> getDefaultConfigUnmodifyable() {
return getConfigUnmodifyable(null);
}
private Map<String,String/*|null*/> getActiveConfigUnmodifyable() {
return getConfigUnmodifyable(getActive());
}
private Map<String,String/*|null*/> getConfig(String config) {
assert !configNameWrong(config);
return RUN_CONFIGS.get(config);
}
private Map<String,String/*|null*/> getDefaultConfig() {
return getConfig(null);
}
private Map<String,String/*|null*/> getActiveConfig() {
return getConfig(getActive());
}
private Map<String,String/*|null*/> getConfigNonNull(String config) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap == null) {
configMap = new TreeMap<String,String>(getComparator());
RUN_CONFIGS.put(config, configMap);
}
return configMap;
}
private Map<String,String/*|null*/> getDefaultConfigNonNull() {
return getConfigNonNull(null);
}
private Map<String,String/*|null*/> getActiveConfigNonNull() {
return getConfigNonNull(getActive());
}
//----------------------------------------------------------
/**
* Adds new and replaces existing properties
* @param config
* @param props
*/
public void addToConfig(String config, Map<String,String/*|null*/> props) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap == null) {
configMap = new TreeMap<String,String>(getComparator());
RUN_CONFIGS.put(config, configMap);
}
configMap.putAll(props);
}
public void addToDefaultConfig(Map<String,String/*|null*/> props) {
addToConfig(null, props);
}
public void addToActiveConfig(Map<String,String/*|null*/> props) {
addToConfig(getActive(), props);
}
public void addToConfig(String config, EditableProperties props) {
assert !configNameWrong(config);
addToConfig(config, new HashMap<String,String>(props));
}
public void addToDefaultConfig(EditableProperties props) {
addToConfig(null, props);
}
public void addToActiveConfig(EditableProperties props) {
addToConfig(getActive(), props);
}
//----------------------------------------------------------
public void eraseConfig(String config) {
assert !configNameWrong(config);
assert config != null; // erasing default config not allowed
RUN_CONFIGS.remove(config);
if(ERASED_CONFIGS == null) {
ERASED_CONFIGS = new HashSet<String>();
}
ERASED_CONFIGS.add(config);
}
//==========================================================
/**
* Returns true if property name is defined in configuration config, false otherwise
* @param config
* @param name
* @return
*/
public boolean isPropertySet(String config, @NonNull String prop) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap != null) {
return configMap.containsKey(prop);
}
return false;
}
public boolean isDefaultPropertySet(@NonNull String prop) {
return isPropertySet(null, prop);
}
public boolean isActivePropertySet(@NonNull String prop) {
return isPropertySet(getActive(), prop);
}
/**
* Returns true if bounded properties exist for prop and at least
* one of them is set. This is to be used in updateProperty() to
* indicate that an empty property needs to be stored to editable properties
*
* @param config
* @param prop
* @return
*/
private boolean isBoundedToNonemptyProperty(String config, String prop) {
assert !configNameWrong(config);
for(String name : groups.getBoundedProperties(prop)) {
if(isPropertySet(config, name)) {
return true;
}
}
return false;
}
//----------------------------------------------------------
/**
* Returns property value from configuration config if defined, null otherwise
* @param config
* @param name
* @return
*/
public String getProperty(String config, @NonNull String prop) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap != null) {
return configMap.get(prop);
}
return null;
}
public String getDefaultProperty(@NonNull String prop) {
return getProperty(null, prop);
}
public String getActiveProperty(@NonNull String prop) {
return getProperty(getActive(), prop);
}
/**
* Returns property value from configuration config (if exists), or
* value from default config (if exists) otherwise
*
* @param config
* @param name
* @return
*/
public String getPropertyTransparent(String config, @NonNull String prop) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
String value = null;
if(configMap != null) {
value = configMap.get(prop);
if(value == null && config != null) {
return getDefaultProperty(prop);
}
}
return value;
}
public String getActivePropertyTransparent(@NonNull String prop) {
return getPropertyTransparent(getActive(), prop);
}
//----------------------------------------------------------
public void setProperty(String config, @NonNull String prop, String value) {
setPropertyImpl(config, prop, value);
solidifyBoundedGroups(config, prop);
if(config == null) {
for(String c: getConfigNames()) {
if(c != null && JFXProjectProperties.isEqualText(getProperty(c, prop), value) && !STATIC_PROPERTIES.contains(prop) && isBoundedPropertiesEraseable(c, prop)) {
eraseProperty(c, prop);
}
}
}
}
private void setPropertyImpl(String config, @NonNull String prop, String value) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfigNonNull(config);
configMap.put(prop, value);
}
public void setDefaultProperty(@NonNull String prop, String value) {
setProperty(null, prop, value);
}
public void setActiveProperty(@NonNull String prop, String value) {
setProperty(getActive(), prop, value);
}
public void setPropertyTransparent(String config, @NonNull String prop, String value) {
assert !configNameWrong(config);
if(config != null && JFXProjectProperties.isEqualText(getDefaultProperty(prop), value) && (!STATIC_PROPERTIES.contains(prop) || !isPropertySet(config, prop)) && isBoundedPropertiesEraseable(config, prop)) {
eraseProperty(config, prop);
} else {
setProperty(config, prop, value);
}
}
public void setActivePropertyTransparent(@NonNull String prop, String value) {
setPropertyTransparent(getActive(), prop, value);
}
//----------------------------------------------------------
/**
* In non-default configurations if prop is not set, then
* this method sets it to a value taken from default config.
* The result is transparent to getPropertyTransparent(), which
* returns the same value before and after solidifyProperty() call.
*
* @param config
* @param prop
* @return false if property had existed in config, true if it had been set by this method
*/
public boolean solidifyProperty(String config, @NonNull String prop) {
if(!isPropertySet(config, prop)) {
if(config != null) {
setPropertyImpl(config, prop, getDefaultProperty(prop));
} else {
setPropertyImpl(null, prop, ""); // NOI18N
}
return true;
}
return false;
}
/**
* Solidifies all properties that are in any bounded group with the
* property prop
*
* @param config
* @param prop
* @return false if nothing was solidified, true otherwise
*/
private boolean solidifyBoundedGroups(String config, @NonNull String prop) {
boolean solidified = false;
for(String name : groups.getBoundedProperties(prop)) {
solidified |= solidifyProperty(config, name);
}
return solidified;
}
//----------------------------------------------------------
public void eraseProperty(String config, @NonNull String prop) {
assert !configNameWrong(config);
Map<String,String/*|null*/> configMap = getConfig(config);
if(configMap != null) {
configMap.remove(prop);
for(String name : groups.getBoundedProperties(prop)) {
configMap.remove(name);
}
}
}
public void eraseDefaultProperty(@NonNull String prop) {
eraseProperty(null, prop);
}
public void eraseActiveProperty(@NonNull String prop) {
eraseProperty(getActive(), prop);
}
/**
* Returns true if property prop and all properties bounded to it
* can be erased harmlessly, i.e., to ensure that getPropertyTransparent()
* returns for each of them the same value before and after erasing
*
* @param prop
* @return
*/
private boolean isBoundedPropertiesEraseable(String config, String prop) {
assert !configNameWrong(config);
if(config == null) {
return false;
}
boolean canErase = true;
for(String name : groups.getBoundedProperties(prop)) {
if((isPropertySet(config, name) && !JFXProjectProperties.isEqualText(getDefaultProperty(name), getProperty(config, name))) || STATIC_PROPERTIES.contains(name)) {
canErase = false;
break;
}
}
return canErase;
}
//==========================================================
// public proxies to access application parameters. May not cover
// the whole of Multiproperty; add missing if needed
/**
* Proxy
* @param config
* @param name
* @return
*/
public boolean hasParamTransparent(String config, @NonNull String name) {
return appParams.hasEntryTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasDefaultParamTransparent(@NonNull String name) {
return appParams.hasDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasActiveParamTransparent(@NonNull String name) {
return appParams.hasActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @param value
* @return
*/
public boolean hasParamTransparent(String config, @NonNull String name, @NonNull String value) {
return appParams.hasEntryTransparent(config, name, value);
}
/**
* Proxy
* @param name
* @param value
* @return
*/
public boolean hasDefaultParamTransparent(@NonNull String name, @NonNull String value) {
return appParams.hasDefaultEntryTransparent(name, value);
}
/**
* Proxy
* @param name
* @param value
* @return
*/
public boolean hasActiveParamTransparent(@NonNull String name, @NonNull String value) {
return appParams.hasActiveEntryTransparent(name, value);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public boolean hasParamValueTransparent(String config, @NonNull String name) {
return appParams.hasEntryValueTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasDefaultParamValueTransparent(@NonNull String name) {
return appParams.hasDefaultEntryValueTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasActiveParamValueTransparent(@NonNull String name) {
return appParams.hasActiveEntryValueTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public Map<String, String> getParamTransparent(String config, @NonNull String name) {
return appParams.getEntryTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public Map<String, String> getDefaultParamTransparent(@NonNull String name) {
return appParams.getDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public Map<String, String> getActiveParamTransparent(@NonNull String name) {
return appParams.getActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public String getParamValueTransparent(String config, @NonNull String name) {
return appParams.getEntryValueTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public String getDefaultParamValueTransparent(@NonNull String name) {
return appParams.getDefaultEntryValueTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public String getActiveParamValueTransparent(@NonNull String name) {
return appParams.getActiveEntryValueTransparent(name);
}
/**
* Proxy
* @param config
* @return
*/
public List<Map<String,String/*|null*/>> getParamsTransparent(String config) {
return appParams.getEntriesTransparent(config);
}
/**
* Proxy
* @return
*/
public List<Map<String,String/*|null*/>> getDefaultParamsTransparent() {
return appParams.getDefaultEntriesTransparent();
}
/**
* Proxy
* @return
*/
public List<Map<String,String/*|null*/>> getActiveParamsTransparent() {
return appParams.getActiveEntriesTransparent();
}
/**
* Proxy
* @param config
* @param name
*/
public void addParamTransparent(String config, @NonNull String name){
appParams.addEntryTransparent(config, name);
}
/**
* Proxy
* @param name
*/
public void addDefaultParamTransparent(@NonNull String name) {
appParams.addDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
*/
public void addActiveParamTransparent(@NonNull String name) {
appParams.addActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @param value
*/
public void addParamTransparent(String config, @NonNull String name, @NonNull String value) {
appParams.addEntryTransparent(config, name, value);
}
/**
* Proxy
* @param name
* @param value
*/
public void addDefaultParamTransparent(@NonNull String name, @NonNull String value) {
appParams.addDefaultEntryTransparent(name, value);
}
/**
* Proxy
* @param name
* @param value
*/
public void addActiveParamTransparent(@NonNull String name, @NonNull String value) {
appParams.addActiveEntryTransparent(name, value);
}
/**
* Proxy
* @param config
* @param params
*/
public void setParamsTransparent(String config, List<Map<String,String/*|null*/>>/*|null*/ params) {
appParams.setEntriesTransparent(config, params);
}
/**
* Proxy
* @param params
*/
public void setDefaultParamsTransparent(List<Map<String,String/*|null*/>>/*|null*/ params) {
appParams.setDefaultEntriesTransparent(params);
}
/**
* Proxy
* @param params
*/
public void setActiveParamsTransparent(List<Map<String,String/*|null*/>>/*|null*/ params) {
appParams.setActiveEntriesTransparent(params);
}
/**
* Proxy
* @param config
* @param name
*/
public void eraseParamTransparent(String config, @NonNull String name) {
appParams.eraseEntryTransparent(config, name);
}
/**
* Proxy
* @param name
*/
public void eraseDefaultParamTransparent(@NonNull String name) {
appParams.eraseDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
*/
public void eraseActiveParamTransparent(@NonNull String name) {
appParams.eraseActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
*/
public void eraseParamsTransparent(String config) {
appParams.eraseEntriesTransparent(config);
}
/**
* Proxy
*/
public void eraseDefaultParamsTransparent() {
appParams.eraseDefaultEntriesTransparent();
}
/**
* Proxy
*/
public void eraseActiveParamsTransparent() {
appParams.eraseActiveEntriesTransparent();
}
/**
* Proxy
* @param config
* @param commandLine
* @return
*/
public String getParamsTransparentAsString(String config, boolean commandLine) {
return appParams.getEntriesTransparentAsString(config, commandLine);
}
/**
* Proxy
* @param commandLine
* @return
*/
public String getDefaultParamsTransparentAsString(boolean commandLine) {
return appParams.getDefaultEntriesTransparentAsString(commandLine);
}
/**
* Proxy
* @param commandLine
* @return
*/
public String getActiveParamsTransparentAsString(boolean commandLine) {
return appParams.getActiveEntriesTransparentAsString(commandLine);
}
//----------------------------------------------------------
// primarily for testing purposes
public boolean hasActiveParam(@NonNull String name) {
return appParams.hasActiveEntry(name);
}
public String paramsToString() {
return appParams.toString();
}
public String getParamsAsString(String config, boolean commandLine) {
return appParams.getEntriesAsString(config, commandLine);
}
public String getDefaultParamsAsString(boolean commandLine) {
return appParams.getDefaultEntriesAsString(commandLine);
}
public String getActiveParamsAsString(boolean commandLine) {
return appParams.getActiveEntriesAsString(commandLine);
}
//==========================================================
// public proxies to access custom manifest entries. May not cover
// the whole of Multiproperty; add missing if needed
/**
* Proxy
* @param config
* @param name
* @return
*/
public boolean hasManifestEntryTransparent(String config, @NonNull String name) {
return appManifestEntries.hasEntryTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasDefaultManifestEntryTransparent(@NonNull String name) {
return appManifestEntries.hasDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasActiveManifestEntryTransparent(@NonNull String name) {
return appManifestEntries.hasActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @param value
* @return
*/
public boolean hasManifestEntryTransparent(String config, @NonNull String name, @NonNull String value) {
return appManifestEntries.hasEntryTransparent(config, name, value);
}
/**
* Proxy
* @param name
* @param value
* @return
*/
public boolean hasDefaultManifestEntryTransparent(@NonNull String name, @NonNull String value) {
return appManifestEntries.hasDefaultEntryTransparent(name, value);
}
/**
* Proxy
* @param name
* @param value
* @return
*/
public boolean hasActiveManifestEntryTransparent(@NonNull String name, @NonNull String value) {
return appManifestEntries.hasActiveEntryTransparent(name, value);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public boolean hasManifestEntryValueTransparent(String config, @NonNull String name) {
return appManifestEntries.hasEntryValueTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasDefaultManifestEntryValueTransparent(@NonNull String name) {
return appManifestEntries.hasDefaultEntryValueTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public boolean hasActiveManifestEntryValueTransparent(@NonNull String name) {
return appManifestEntries.hasActiveEntryValueTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public Map<String, String> getManifestEntryTransparent(String config, @NonNull String name) {
return appManifestEntries.getEntryTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public Map<String, String> getDefaultManifestEntryTransparent(@NonNull String name) {
return appManifestEntries.getDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public Map<String, String> getActiveManifestEntryTransparent(@NonNull String name) {
return appManifestEntries.getActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @return
*/
public String getManifestEntryValueTransparent(String config, @NonNull String name) {
return appManifestEntries.getEntryValueTransparent(config, name);
}
/**
* Proxy
* @param name
* @return
*/
public String getDefaultManifestEntryValueTransparent(@NonNull String name) {
return appManifestEntries.getDefaultEntryValueTransparent(name);
}
/**
* Proxy
* @param name
* @return
*/
public String getActiveManifestEntryValueTransparent(@NonNull String name) {
return appManifestEntries.getActiveEntryValueTransparent(name);
}
/**
* Proxy
* @param config
* @return
*/
public List<Map<String,String/*|null*/>> getManifestEntriesTransparent(String config) {
return appManifestEntries.getEntriesTransparent(config);
}
/**
* Proxy
* @return
*/
public List<Map<String,String/*|null*/>> getDefaultManifestEntriesTransparent() {
return appManifestEntries.getDefaultEntriesTransparent();
}
/**
* Proxy
* @return
*/
public List<Map<String,String/*|null*/>> getActiveManifestEntriesTransparent() {
return appManifestEntries.getActiveEntriesTransparent();
}
/**
* Proxy
* @param config
* @param name
*/
public void addManifestEntryTransparent(String config, @NonNull String name){
appManifestEntries.addEntryTransparent(config, name);
}
/**
* Proxy
* @param name
*/
public void addDefaultManifestEntryTransparent(@NonNull String name) {
appManifestEntries.addDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
*/
public void addActiveManifestEntryTransparent(@NonNull String name) {
appManifestEntries.addActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
* @param name
* @param value
*/
public void addManifestEntryTransparent(String config, @NonNull String name, @NonNull String value) {
appManifestEntries.addEntryTransparent(config, name, value);
}
/**
* Proxy
* @param name
* @param value
*/
public void addDefaultManifestEntryTransparent(@NonNull String name, @NonNull String value) {
appManifestEntries.addDefaultEntryTransparent(name, value);
}
/**
* Proxy
* @param name
* @param value
*/
public void addActiveManifestEntryTransparent(@NonNull String name, @NonNull String value) {
appManifestEntries.addActiveEntryTransparent(name, value);
}
/**
* Proxy
* @param config
* @param params
*/
public void setManifestEntriesTransparent(String config, List<Map<String,String/*|null*/>>/*|null*/ params) {
appManifestEntries.setEntriesTransparent(config, params);
}
/**
* Proxy
* @param params
*/
public void setDefaultManifestEntriesTransparent(List<Map<String,String/*|null*/>>/*|null*/ params) {
appManifestEntries.setDefaultEntriesTransparent(params);
}
/**
* Proxy
* @param params
*/
public void setActiveManifestEntriesTransparent(List<Map<String,String/*|null*/>>/*|null*/ params) {
appManifestEntries.setActiveEntriesTransparent(params);
}
/**
* Proxy
* @param config
* @param name
*/
public void eraseManifestEntryTransparent(String config, @NonNull String name) {
appManifestEntries.eraseEntryTransparent(config, name);
}
/**
* Proxy
* @param name
*/
public void eraseDefaultManifestEntryTransparent(@NonNull String name) {
appManifestEntries.eraseDefaultEntryTransparent(name);
}
/**
* Proxy
* @param name
*/
public void eraseActiveManifestEntryTransparent(@NonNull String name) {
appManifestEntries.eraseActiveEntryTransparent(name);
}
/**
* Proxy
* @param config
*/
public void eraseManifestEntriesTransparent(String config) {
appManifestEntries.eraseEntriesTransparent(config);
}
/**
* Proxy
*/
public void eraseDefaultManifestEntriesTransparent() {
appManifestEntries.eraseDefaultEntriesTransparent();
}
/**
* Proxy
*/
public void eraseActiveManifestEntriesTransparent() {
appManifestEntries.eraseActiveEntriesTransparent();
}
/**
* Proxy
* @param config
* @return
*/
public String getManifestEntriesTransparentAsString(String config) {
return appManifestEntries.getEntriesTransparentAsString(config, false);
}
/**
* Proxy
* @return
*/
public String getDefaultManifestEntriesTransparentAsString() {
return appManifestEntries.getDefaultEntriesTransparentAsString(false);
}
/**
* Proxy
* @return
*/
public String getActiveManifestEntriesTransparentAsString() {
return appManifestEntries.getActiveEntriesTransparentAsString(false);
}
//----------------------------------------------------------
// primarily for testing purposes
public boolean hasActiveManifestEntry(@NonNull String name) {
return appManifestEntries.hasActiveEntry(name);
}
public String manifestEntriesToString() {
return appManifestEntries.toString();
}
public int getNoOfManifestEntries(String config) {
return appManifestEntries.getNoOfEntries(config);
}
public int getNoOfDefaultManifestEntries() {
return appManifestEntries.getNoOfDefaultEntries();
}
public int getNoOfActiveManifestEntries() {
return appManifestEntries.getNoOfActiveEntries();
}
//==========================================================
/**
* Reads configuration properties from project properties files
* (modified from "A mess." from J2SEProjectProperties)"
*/
public void read() {
//Map<String/*|null*/,Map<String,String>> readRunConfigs() {
reset();
// read project properties
readDefaultConfig(AntProjectHelper.PROJECT_PROPERTIES_PATH);
// overwrite by project private properties
readDefaultConfig(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
// set properties that were not set but should have a value
addDefaultsIfMissing();
// add project properties read from config files
readNonDefaultConfigs(PROJECT_CONFIGS_DIR, true);
// add/overwrite project properties read from private config files
readNonDefaultConfigs(PROJECT_PRIVATE_CONFIGS_DIR, false);
}
private void readDefaultConfig(String propsFile) {
EditableProperties ep = null;
try {
ep = JFXProjectUtils.readFromFile(projectDir, propsFile);
} catch (IOException ex) {
// can be ignored
}
if(ep != null) {
for (String prop : PROJECT_PROPERTIES) {
String v = ep.getProperty(prop);
if (v != null) {
setDefaultProperty(prop, v);
}
}
}
appParams.extractDefaultEntries(ep);
appManifestEntries.extractDefaultEntries(ep);
}
private void addDefaultsIfMissing() {
for(String prop : DEFAULT_IF_MISSING.keySet()) {
if(!isDefaultPropertySet(prop)) {
setDefaultProperty(prop, DEFAULT_IF_MISSING.get(prop));
}
}
}
private void readNonDefaultConfigs(String subDir, boolean createIfNotExists) {
FileObject configsFO = projectDir.getFileObject(subDir); // NOI18N
if (configsFO != null) {
for (FileObject kid : configsFO.getChildren()) {
if (!kid.hasExt(PROPERTIES_FILE_EXT)) { // NOI18N
continue;
}
Map<String,String> c = getConfig(kid.getName());
if (c == null && !createIfNotExists) {
continue;
}
EditableProperties cep = null;
try {
cep = JFXProjectUtils.readFromFile( kid );
} catch (IOException ex) {
// can be ignored
}
addToConfig(kid.getName(), cep);
appParams.extractEntries(cep, kid.getName());
appManifestEntries.extractEntries(cep, kid.getName());
}
}
}
//----------------------------------------------------------
public void readActive() {
try {
setActive(JFXProjectUtils.readFromFile(projectDir, CONFIG_PROPERTIES_FILE).getProperty(ProjectProperties.PROP_PROJECT_CONFIGURATION_CONFIG));
} catch(IOException e) {
LOG.log(Level.WARNING, "Failed to read active configuration from {0}.", CONFIG_PROPERTIES_FILE); // NOI18N
}
}
public void storeActive() throws IOException {
String configPath = CONFIG_PROPERTIES_FILE;
if (active == null) {
try {
JFXProjectUtils.deleteFile(projectDir, configPath);
} catch (IOException ex) {
}
} else {
final EditableProperties configProps = JFXProjectUtils.readFromFile(projectDir, configPath);
configProps.setProperty(ProjectProperties.PROP_PROJECT_CONFIGURATION_CONFIG, active);
JFXProjectUtils.saveToFile(projectDir, configPath, configProps);
}
}
//----------------------------------------------------------
/**
* Gathers application parameters to one property APPLICATION_ARGS
* to be passed to run/debug target in build-impl.xml when Run as Standalone
*
* @param config
* @param ep editable properties to which to store the generated property
* @return true if properties have been edited
*/
private boolean storeParamsAsCommandLine(String config, EditableProperties projectProperties) {
assert !configNameWrong(config);
String params = appParams.getEntriesTransparentAsString(config, true, true);
if(config != null) {
if(JFXProjectProperties.isEqualText(params, appParams.getDefaultEntriesAsString(true, true))) {
params = null;
}
}
if (!Utilities.compareObjects(params, projectProperties.getProperty(APPLICATION_ARGS))) {
if (params != null && params.length() > 0) {
projectProperties.setProperty(APPLICATION_ARGS, params);
projectProperties.setComment(APPLICATION_ARGS, new String[]{"# " + NbBundle.getMessage(JFXProjectConfigurations.class, "COMMENT_app_args")}, false); // NOI18N
} else {
projectProperties.remove(APPLICATION_ARGS);
}
return true;
}
return false;
}
private boolean storeDefaultParamsAsCommandLine(EditableProperties projectProperties) {
return storeParamsAsCommandLine(null, projectProperties);
}
/**
* Stores/updates configuration properties and parameters to EditableProperties in case of default
* config, or directly to project properties files in case of non-default configs.
* (modified from "A royal mess." from J2SEProjectProperties)"
*/
public void store(EditableProperties projectProperties, EditableProperties privateProperties) throws IOException {
for (String name : PROJECT_PROPERTIES) {
String value = getDefaultProperty(name);
updateProperty(name, value, projectProperties, privateProperties, isBoundedToNonemptyProperty(null, name));
}
List<String> paramNamesUsed = new ArrayList<String>();
List<String> manifestEntryNamesUsed = new ArrayList<String>();
appParams.updateDefaultEntryProperties(projectProperties, privateProperties, paramNamesUsed);
appManifestEntries.updateDefaultEntryProperties(projectProperties, privateProperties, manifestEntryNamesUsed);
storeDefaultParamsAsCommandLine(privateProperties);
for (Map.Entry<String,Map<String,String>> entry : RUN_CONFIGS.entrySet()) {
String config = entry.getKey();
if (config == null) {
continue;
}
String sharedPath = getSharedConfigFilePath(config);
String privatePath = getPrivateConfigFilePath(config);
Map<String,String> configProps = entry.getValue();
if (configProps == null) {
try {
JFXProjectUtils.deleteFile(projectDir, sharedPath);
} catch (IOException ex) {
LOG.log(Level.WARNING, "Failed to delete file: {0}", sharedPath); // NOI18N
}
try {
JFXProjectUtils.deleteFile(projectDir, privatePath);
} catch (IOException ex) {
LOG.log(Level.WARNING, "Failed to delete file: {0}", privatePath); // NOI18N
}
continue;
}
final EditableProperties sharedCfgProps = JFXProjectUtils.readFromFile(projectDir, sharedPath);
final EditableProperties privateCfgProps = JFXProjectUtils.readFromFile(projectDir, privatePath);
boolean privatePropsChanged = false;
for (Map.Entry<String,String> prop : configProps.entrySet()) {
String name = prop.getKey();
String value = prop.getValue();
String defaultValue = getDefaultProperty(name);
boolean storeIfEmpty = (defaultValue != null && defaultValue.length() > 0) || isBoundedToNonemptyProperty(config, name);
privatePropsChanged |= updateProperty(name, value, sharedCfgProps, privateCfgProps, storeIfEmpty);
}
cleanPropertiesIfEmpty(CLEAN_EMPTY_PROJECT_PROPERTIES.toArray(new String[0]),
config, sharedCfgProps);
privatePropsChanged |= cleanPropertiesIfEmpty(CLEAN_EMPTY_PRIVATE_PROPERTIES.toArray(new String[0]),
config, privateCfgProps);
privatePropsChanged |= appParams.updateEntryProperties(config, sharedCfgProps, privateCfgProps, paramNamesUsed);
privatePropsChanged |= appManifestEntries.updateEntryProperties(config, sharedCfgProps, privateCfgProps, manifestEntryNamesUsed);
privatePropsChanged |= storeParamsAsCommandLine(config, privateCfgProps);
JFXProjectUtils.saveToFile(projectDir, sharedPath, sharedCfgProps); //Make sure the definition file is always created, even if it is empty.
if (privatePropsChanged) { //Definition file is written, only when changed
JFXProjectUtils.saveToFile(projectDir, privatePath, privateCfgProps);
}
}
if(ERASED_CONFIGS != null) {
for (String entry : ERASED_CONFIGS) {
if(!RUN_CONFIGS.containsKey(entry)) {
// config has been erased, and has not been recreated
String sharedPath = getSharedConfigFilePath(entry);
String privatePath = getPrivateConfigFilePath(entry);
try {
JFXProjectUtils.deleteFile(projectDir, sharedPath);
} catch (IOException ex) {
LOG.log(Level.WARNING, "Failed to delete file: {0}", sharedPath); // NOI18N
}
try {
JFXProjectUtils.deleteFile(projectDir, privatePath);
} catch (IOException ex) {
LOG.log(Level.WARNING, "Failed to delete file: {0}", privatePath); // NOI18N
}
}
}
}
}
//----------------------------------------------------------
/**
* Updates the value of existing property in editable properties if value differs.
* If value is not set or is set empty, removes property from editable properties
* unless storeEmpty==true, in which case the property is preserved and set to empty
* in editable properties.
*
* @param name property to be updated
* @param value new property value
* @param projectProperties project editable properties
* @param privateProperties private project editable properties
* @param storeEmpty true==keep empty properties in editable properties, false==remove empty properties
* @return true if private properties have been edited
*/
private boolean updateProperty(@NonNull String name, String value, @NonNull EditableProperties projectProperties, @NonNull EditableProperties privateProperties, boolean storeEmpty) {
boolean changePrivate = PRIVATE_PROPERTIES.contains(name) || privateProperties.containsKey(name);
EditableProperties ep = changePrivate ? privateProperties : projectProperties;
if(changePrivate) {
projectProperties.remove(name);
}
if (!Utilities.compareObjects(value, ep.getProperty(name))) {
if (value != null && (value.length() > 0 || storeEmpty)) {
ep.setProperty(name, value);
} else {
ep.remove(name);
}
return changePrivate;
}
return false;
}
/**
* Updates the value of existing property in editable properties if value differs.
* If value is not set or is set empty, removes property from editable properties.
*
* @param name property to be updated
* @param value new property value
* @param projectProperties project editable properties
* @param privateProperties private project editable properties
*/
private boolean updateProperty(@NonNull String name, String value, @NonNull EditableProperties projectProperties, @NonNull EditableProperties privateProperties) {
return updateProperty(name, value, projectProperties, privateProperties, false);
}
/**
* If property not present in config configuration, remove it from editable properties.
* This is to propagate property deletions in config to property files
* @param name
* @param config
* @param ep
* @return true if properties have been edited
*/
private boolean cleanPropertyIfEmpty(@NonNull String name, String config, @NonNull EditableProperties ep) {
if(!isPropertySet(config, name)) {
ep.remove(name);
return true;
}
return false;
}
private boolean cleanPropertiesIfEmpty(@NonNull String[] names, String config, @NonNull EditableProperties ep) {
boolean updated = false;
for(String name : names) {
updated |= cleanPropertyIfEmpty(name, config, ep);
}
return updated;
}
//----------------------------------------------------------
/**
* For properties registered in bounded groups special
* handling is to be followed. Either all bounded properties
* must exist or none of bounded properties must exist
* in project configuration. The motivation is to enable
* treating all Preloader related properties is one pseudo-property
*/
private class BoundedPropertyGroups {
Map<String, Set<String>> groups = new HashMap<String, Set<String>>();
public void defineGroup(String groupName, Collection<String> props) {
Set<String> group = new HashSet<String>();
group.addAll(props);
groups.put(groupName, group);
}
public void clearGroup(String groupName) {
groups.remove(groupName);
}
public void clearAllGroups() {
groups.clear();
}
/**
* Returns true if property prop is bound with any other properties
* @return
*/
public boolean isBound(String prop) {
for(Map.Entry<String, Set<String>> entry : groups.entrySet()) {
Set<String> group = entry.getValue();
if(group != null && group.contains(prop) && group.size() > 1) {
return true;
}
}
return false;
}
/**
* Returns collection of all properties from any group of which
* property prop is member. prop is not included in result.
* @param prop
* @return
*/
public Collection<String> getBoundedProperties(String prop) {
Set<String> bounded = new HashSet<String>();
for(Map.Entry<String, Set<String>> entry : groups.entrySet()) {
Set<String> group = entry.getValue();
if(group != null && group.contains(prop)) {
bounded.addAll(group);
}
}
bounded.remove(prop);
return bounded;
}
}
//----------------------------------------------------------
/**
* Project properties maintenance class. Handles properties that may have multiple
* instances, like FX Application parameters, or custom manifest entries
*/
private final class MultiProperty {
private Map<String/*|null*/,List<Map<String,String/*|null*/>>/*|null*/> APP_MULTIPROPS;
private String prefix;
private String suffixes[];
private String connectSign;
public MultiProperty(@NonNull String prefix, @NonNull String suffixes[], @NonNull String connectSign) {
assert suffixes.length == 3; // need "name" and "value" and "hidden"
this.prefix = prefix;
this.suffixes = suffixes;
this.connectSign = connectSign;
reset();
}
public void reset() {
APP_MULTIPROPS = new TreeMap<String,List<Map<String,String>>>(getComparator());
}
//==========================================================
/**
* Returns true if the key "hidden" is set to "true" in this entry.
* Hiding is used to record entry deletion (e.g., entry or custom manifest entry)
* in non-default configuration while keeping the entry in default config
*
* @param entry
* @return
*/
private boolean isEntryHidden(Map<String,String> entry) {
if(entry != null && JFXProjectProperties.isTrue(entry.get(suffixes[2]))) {
return true;
}
return false;
}
private boolean isEntryHidden(String config, @NonNull String name) {
Map<String, String> entry = getEntry(config, name);
if(entry != null) {
return isEntryHidden(entry);
}
return false;
}
private void hideEntry(@NonNull Map<String,String> entry) {
assert entry != null;
entry.put(suffixes[2], APP_MULTIPROP_HIDDEN_TRUE); // NOI18N
}
private void unhideEntry(@NonNull Map<String,String> entry) {
assert entry != null;
entry.remove(suffixes[2]);
}
private void hideEntry(String config, String name) {
Map<String, String> map = getEntry(config, name);
if(map != null) {
hideEntry(map);
}
}
private void unhideEntry(String config, String name) {
Map<String, String> map = getEntry(config, name);
if(map != null) {
unhideEntry(map);
}
}
/**
* Removes those entries from list that are marked as hidden
*
* @param entries
* @return filtered list
*/
private List<Map<String,String/*|null*/>> removeHiddenEntries(@NonNull List<Map<String,String/*|null*/>> entries) {
List<Map<String,String/*|null*/>> filtered = new ArrayList<Map<String,String>>();
if(entries != null) {
for(Map<String,String> map : entries) {
if(!isEntryHidden(map)) {
filtered.add(map);
}
}
}
return filtered;
}
//==========================================================
private String getEntryName(Map<String,String> entry) {
return entry != null ? entry.get(suffixes[0]) : null;
}
private String getEntryValue(Map<String,String> entry) {
return entry != null ? entry.get(suffixes[1]) : null;
}
private void setEntryName(Map<String,String> entry, String name) {
if(entry != null) {
entry.put(suffixes[0], name);
}
}
private void setEntryValue(Map<String,String> entry, String value) {
if(entry != null) {
entry.put(suffixes[1], value);
}
}
//==========================================================
/**
* Returns true if entry named name is present in configuration
* config in any form - with value or without value
* @param config
* @param name
* @return
*/
private boolean hasEntry(String config, @NonNull String name) {
assert !configNameWrong(config);
return getEntry(config, name) != null;
}
private boolean hasDefaultEntry(@NonNull String name) {
return hasEntry(null, name);
}
private boolean hasActiveEntry(@NonNull String name) {
return hasEntry(getActive(), name);
}
public boolean hasEntryTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
return getEntryTransparent(config, name) != null;
}
public boolean hasDefaultEntryTransparent(@NonNull String name) {
return hasEntryTransparent((String)null, name);
}
public boolean hasActiveEntryTransparent(@NonNull String name) {
return hasEntryTransparent(getActive(), name);
}
//----------------------------------------------------------
/**
* Returns true if exactly the entry with name name and value value
* is present in configuration config
*
* @param config
* @param name
* @param value
* @return
*/
private boolean hasEntry(String config, @NonNull String name, @NonNull String value) {
assert !configNameWrong(config);
String v = getEntryValue(config, name);
return JFXProjectProperties.isEqualText(v, value);
}
private boolean hasDefaultEntry(@NonNull String name, @NonNull String value) {
return hasEntry(null, name, value);
}
private boolean hasActiveEntry(@NonNull String name, @NonNull String value) {
return hasEntry(getActive(), name, value);
}
public boolean hasEntryTransparent(String config, @NonNull String name, @NonNull String value) {
assert !configNameWrong(config);
String v = getEntryValueTransparent(config, name);
return JFXProjectProperties.isEqualText(v, value);
}
public boolean hasDefaultEntryTransparent(@NonNull String name, @NonNull String value) {
return hasEntryTransparent((String)null, name, value);
}
public boolean hasActiveEntryTransparent(@NonNull String name, @NonNull String value) {
return hasEntryTransparent(getActive(), name, value);
}
//----------------------------------------------------------
// note that these do not search for concrete value, they
// search for entry named name and ask whether such
// entry has any value
private boolean hasEntryValue(Map<String,String> entry) {
return entry != null && entry.containsKey(suffixes[1]);
}
private boolean hasEntryValue(String config, @NonNull String name) {
assert !configNameWrong(config);
Map<String, String> entry = getEntry(config, name);
return hasEntryValue(entry);
}
private boolean hasDefaultEntryValue(@NonNull String name) {
return hasEntryValue(null, name);
}
private boolean hasActiveEntryValue(@NonNull String name) {
return hasEntryValue(getActive(), name);
}
public boolean hasEntryValueTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
Map<String, String> entry = getEntry(config, name);
if(config != null && entry == null) {
return hasEntryValueTransparent((String)null, name);
}
return isEntryHidden(entry) ? false : hasEntryValue(entry);
}
public boolean hasDefaultEntryValueTransparent(@NonNull String name) {
return hasEntryValueTransparent((String)null, name);
}
public boolean hasActiveEntryValueTransparent(@NonNull String name) {
return hasEntryValueTransparent(getActive(), name);
}
//----------------------------------------------------------
/**
* Returns entry as map if exists in configuration config, null otherwise
*
* @param config
* @param name
* @return
*/
private Map<String, String> getEntry(String config, @NonNull String name) {
assert !configNameWrong(config);
return getEntry(getEntries(config), name);
}
private Map<String, String> getDefaultEntry(@NonNull String name) {
return getEntry((String)null, name);
}
private Map<String, String> getActiveEntry(@NonNull String name) {
return getEntry(getActive(), name);
}
public Map<String, String> getEntryTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
Map<String, String> entry = getEntry(config, name);
if(config != null && entry == null) {
return getEntryTransparent((String)null, name);
}
return isEntryHidden(entry) ? null : entry;
}
public Map<String, String> getDefaultEntryTransparent(@NonNull String name) {
return getEntryTransparent((String)null, name);
}
public Map<String, String> getActiveEntryTransparent(@NonNull String name) {
return getEntryTransparent(getActive(), name);
}
//----------------------------------------------------------
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param config
* @param name
* @return
*/
private String getEntryValue(String config, @NonNull String name) {
assert !configNameWrong(config);
Map<String,String/*|null*/> entry = getEntry(config, name);
if(entry != null) {
return getEntryValue(entry);
}
return null;
}
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param name
* @return
*/
private String getDefaultEntryValue(@NonNull String name) {
return getEntryValue((String)null, name);
}
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param name
* @return
*/
private String getActiveEntryValue(@NonNull String name) {
return getEntryValue(getActive(), name);
}
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param config
* @param name
* @return
*/
public String getEntryValueTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
Map<String, String> entry = getEntry(config, name);
if(config != null && entry == null) {
return getEntryValueTransparent((String)null, name);
}
return isEntryHidden(entry) ? null : getEntryValue(entry);
}
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param name
* @return
*/
public String getDefaultEntryValueTransparent(@NonNull String name) {
return getEntryValueTransparent((String)null, name);
}
/**
* Note that returned null is ambiguous - may mean that there
* was no value defined or that it was defined and its value was null.
* To check this ask has*EntryValue*()
*
* @param name
* @return
*/
public String getActiveEntryValueTransparent(@NonNull String name) {
return getEntryValueTransparent(getActive(), name);
}
//----------------------------------------------------------
private @NonNull List<Map<String,String/*|null*/>> getEntries(String config) {
assert !configNameWrong(config);
return APP_MULTIPROPS.get(config);
}
private List<Map<String,String/*|null*/>> getDefaultEntries() {
return APP_MULTIPROPS.get(null);
}
private List<Map<String,String/*|null*/>> getActiveEntries() {
return APP_MULTIPROPS.get(getActive());
}
/**
* Returns (copy of) list of default entries if config==default or
* union of default config and current config entries otherwise
* (excludes hidden entries)
*
* @param config current config
* @return union of default and current entries
*/
public List<Map<String,String/*|null*/>> getEntriesTransparent(String config) {
assert !configNameWrong(config);
if(config == null) {
return removeHiddenEntries(getDefaultEntries());
}
List<Map<String,String/*|null*/>> union = new ArrayList<Map<String,String>>();
// create marker set - identify entries to be added from default and current configs
Set<String> markerDefault = new HashSet<String>();
Set<String> markerConfig = new HashSet<String>();
List<Map<String,String/*|null*/>> defaultEntries = getDefaultEntries();
if(defaultEntries != null) {
for(Map<String,String> map : defaultEntries) {
if(!isEntryHidden(map)) {
markerDefault.add(getEntryName(map));
}
}
}
List<Map<String,String/*|null*/>> configEntries = getEntries(config);
if(configEntries != null) {
for(Map<String,String> map : configEntries) {
if(!isEntryHidden(map)) {
markerConfig.add(getEntryName(map));
} else {
markerDefault.remove(getEntryName(map));
}
}
}
// copy entries from default and current config based on marker
if(defaultEntries != null) {
for(Map<String,String> map : defaultEntries) {
String name = getEntryName(map);
if(markerDefault.contains(name) && !markerConfig.contains(name)) {
union.add(createEntry(name, getEntryValue(map)));
}
}
}
if(configEntries != null) {
for(Map<String,String> map : configEntries) {
String name = getEntryName(map);
if(markerConfig.contains(name)) {
union.add(createEntry(name, getEntryValue(map)));
}
}
}
return union;
}
public List<Map<String,String/*|null*/>> getDefaultEntriesTransparent() {
return getEntriesTransparent((String)null);
}
public List<Map<String,String/*|null*/>> getActiveEntriesTransparent() {
return getEntriesTransparent(getActive());
}
//----------------------------------------------------------
/**
* Gathers all entries applicable to config configuration to one String
*
* @param commandLine if true, formats output as if to be passed on command line, otherwise prouces comma separated list
* @return a String containing all entries as if passed as command line parameters
*/
private String getEntriesAsString(String config, boolean commandLine) {
return getEntriesAsString(getEntries(config), commandLine);
}
private String getDefaultEntriesAsString(boolean commandLine, boolean quoteEntries) {
return getEntriesAsString(getDefaultEntries(), commandLine, quoteEntries);
}
private String getDefaultEntriesAsString(boolean commandLine) {
return getEntriesAsString(getDefaultEntries(), commandLine);
}
private String getActiveEntriesAsString(boolean commandLine) {
return getEntriesAsString(getActiveEntries(), commandLine);
}
public String getEntriesTransparentAsString(String config, boolean commandLine) {
assert !configNameWrong(config);
return getEntriesAsString(getEntriesTransparent(config), commandLine);
}
public String getEntriesTransparentAsString(String config, boolean commandLine, boolean quoteParams) {
assert !configNameWrong(config);
return getEntriesAsString(getEntriesTransparent(config), commandLine, quoteParams);
}
public String getDefaultEntriesTransparentAsString(boolean commandLine) {
return getEntriesAsString(getDefaultEntriesTransparent(), commandLine);
}
public String getActiveEntriesTransparentAsString(boolean commandLine) {
return getEntriesAsString(getActiveEntriesTransparent(), commandLine);
}
private String getEntriesAsString(List<Map<String,String/*|null*/>> props, boolean commandLine) {
return getEntriesAsString(props, commandLine, false);
}
private String getEntriesAsString(List<Map<String,String/*|null*/>> props, boolean commandLine, boolean quoteParams) {
StringBuilder sb = new StringBuilder();
if(props != null) {
int index = 0;
for(Map<String,String> m : props) {
String name = getEntryName(m);
String value = getEntryValue(m);
if(name != null && name.length() > 0 && !isEntryHidden(m)) {
if(sb.length() > 0) {
if(!commandLine) {
sb.append(","); // NOI18N
}
sb.append(" "); // NOI18N
}
if(value != null && value.length() > 0) {
if(commandLine) {
sb.append("--"); // NOI18N
}
if (quoteParams) {
sb.append("'").append(name).append("'");
} else {
sb.append(name);
}
if(commandLine) {
sb.append("="); // NOI18N
} else {
sb.append(connectSign); // NOI18N
}
if (quoteParams) {
sb.append("'").append(value).append("'");
} else {
sb.append(value);
}
} else {
if (quoteParams) {
sb.append("'").append(name).append("'");
} else {
sb.append(name);
}
}
index++;
}
}
}
return sb.toString();
}
public int getNoOfEntries(String config) {
assert !configNameWrong(config);
return getNoOfEntries(getEntriesTransparent(config));
}
public int getNoOfDefaultEntries() {
return getNoOfEntries(getDefaultEntriesTransparent());
}
public int getNoOfActiveEntries() {
return getNoOfEntries(getActiveEntriesTransparent());
}
private int getNoOfEntries(List<Map<String,String/*|null*/>> props)
{
int sum = 0;
if(props != null) {
for(Map<String,String> m : props) {
String name = getEntryName(m);
if(name != null && name.length() > 0 && !isEntryHidden(m)) {
sum++;
}
}
}
return sum;
}
//----------------------------------------------------------
private Map<String, String> createEntry(@NonNull String name) {
Map<String, String> prop = new TreeMap<String,String>(getComparator());
setEntryName(prop, name);
return prop;
}
private Map<String, String> createEntry(@NonNull String name, String value) {
Map<String, String> prop = new TreeMap<String,String>(getComparator());
setEntryName(prop, name);
setEntryValue(prop, value);
return prop;
}
private Map<String, String> copyEntry(@NonNull Map<String, String> entry) {
Map<String, String> newEntry = new HashMap<String, String>();
for(String name : suffixes) {
String value = entry.get(name);
if(value != null && !value.isEmpty()) {
newEntry.put(name, value);
}
}
return newEntry;
}
//----------------------------------------------------------
/**
* Add (or replace if present) entry
* to configuration config
*/
private void addEntry(String config, @NonNull Map<String,String> entry) {
assert !configNameWrong(config);
List<Map<String,String/*|null*/>> props = getEntries(config);
if(props == null) {
props = new ArrayList<Map<String,String/*|null*/>>();
APP_MULTIPROPS.put(config, props);
} else {
eraseEntry(props, entry);
}
props.add(entry);
}
private void addDefaultEntry(@NonNull Map<String,String> entry) {
addEntry((String)null, entry);
}
private void addActiveEntry(@NonNull Map<String,String> entry) {
addEntry(getActive(), entry);
}
//----------------------------------------------------------
/**
* Add (or replace if present) valueless entry (e.g., run argument)
* to configuration config
*/
private Map<String, String> addEntry(String config, @NonNull String name) {
assert !configNameWrong(config);
List<Map<String,String/*|null*/>> props = getEntries(config);
if(props == null) {
props = new ArrayList<Map<String,String/*|null*/>>();
APP_MULTIPROPS.put(config, props);
} else {
eraseEntry(props, name);
}
Map<String, String> newEntry = createEntry(name);
props.add(newEntry);
return newEntry;
}
private Map<String, String> addDefaultEntry(@NonNull String name) {
return addEntry((String)null, name);
}
private Map<String, String> addActiveEntry(@NonNull String name) {
return addEntry(getActive(), name);
}
public Map<String, String> addEntryTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
if(config == null) {
for(String c: getConfigNames()) {
final Map<String,String> entry = getEntry(c, name);
if(c != null && entry != null && getEntryValue(entry) == null && !isEntryHidden(entry)) {
eraseEntry(c, name);
}
}
return addDefaultEntry(name);
} else {
if(hasDefaultEntryTransparent(name) && !hasDefaultEntryValueTransparent(name)) {
eraseEntry(config, name);
return null;
} else {
return addEntry(config, name);
}
}
}
public Map<String, String> addDefaultEntryTransparent(@NonNull String name) {
return addEntryTransparent((String)null, name);
}
public Map<String, String> addActiveEntryTransparent(@NonNull String name) {
return addEntryTransparent(getActive(), name);
}
//----------------------------------------------------------
/**
* Add (or replace if present) named entry (i.e., having a value)
* to configuration config
*/
private Map<String, String> addEntry(String config, @NonNull String name, String value) {
assert !configNameWrong(config);
List<Map<String,String/*|null*/>> props = getEntries(config);
if(props == null) {
props = new ArrayList<Map<String,String/*|null*/>>();
APP_MULTIPROPS.put(config, props);
} else {
eraseEntry(props, name);
}
Map<String, String> newEntry = createEntry(name, value);
props.add(newEntry);
return newEntry;
}
private Map<String, String> addDefaultEntry(@NonNull String name, String value) {
return addEntry(null, name, value);
}
private Map<String, String> addActiveEntry(@NonNull String name, String value) {
return addEntry(getActive(), name, value);
}
public Map<String, String> addEntryTransparent(String config, @NonNull String name, String value) {
assert !configNameWrong(config);
if(config == null) {
for(String c: getConfigNames()) {
final Map<String, String> entry = getEntry(c, name);
if(c != null && entry != null && JFXProjectProperties.isEqualText(getEntryValue(entry), value) && !isEntryHidden(entry) ) {
eraseEntry(c, name);
}
}
return addDefaultEntry(name, value);
} else {
if(hasDefaultEntryTransparent(name, value)) {
eraseEntry(config, name);
return null;
} else {
return addEntry(config, name, value);
}
}
}
public Map<String, String> addDefaultEntryTransparent(@NonNull String name, String value) {
return addEntryTransparent((String)null, name, value);
}
public Map<String, String> addActiveEntryTransparent(@NonNull String name, String value) {
return addEntryTransparent(getActive(), name, value);
}
//----------------------------------------------------------
/**
* Updates entries; if config==default, then simply updates default entries,
* otherwise updates entries in current config so that only those different
* from those in default config are stored.
*
* @param config
* @param entries
*/
public void setEntriesTransparent(String config, List<Map<String,String/*|null*/>>/*|null*/ entries) {
assert !configNameWrong(config);
if(config == null) {
List<Map<String,String>> newDefault = new ArrayList<Map<String, String>>();
Set<String> toClean = new HashSet<String>();
if(APP_MULTIPROPS.get(null) != null) {
for(Map<String,String> entry : APP_MULTIPROPS.get(null)) {
if(isEntryHidden(entry)) {
newDefault.add(entry);
} else {
toClean.add(getEntryName(entry));
}
}
}
APP_MULTIPROPS.put(null, newDefault);
if(entries != null) {
for(Map<String, String> entry : entries) {
String name = getEntryName(entry);
toClean.remove(name);
Map<String, String> added;
if(hasEntryValue(entry)) {
added = addDefaultEntryTransparent(name, getEntryValue(entry));
} else {
added = addDefaultEntryTransparent(name);
}
if(isEntryHidden(entry)) {
hideEntry(added);
}
}
}
for(String name : toClean) {
eraseNonDefaultEntries(name, true);
}
} else {
List<Map<String,String/*|null*/>> reduct = new ArrayList<Map<String,String/*|null*/>>();
if(entries != null) {
List<Map<String,String/*|null*/>> def = JFXProjectUtils.copyList(getDefaultEntriesTransparent());
for(Map<String,String> map : entries) {
String name = getEntryName(map);
String value = getEntryValue(map);
Map<String, String> defEntry = getDefaultEntryTransparent(name);
if(defEntry != null) {
String defValue = getEntryValue(defEntry);
if( !JFXProjectProperties.isEqualText(value, defValue) ) {
reduct.add(JFXProjectUtils.copyMap(map));
}
def.remove(defEntry);
} else {
if(!isEntryHidden(map)) {
reduct.add(JFXProjectUtils.copyMap(map));
}
}
}
for(Map<String,String> map : def) { //def cannot be null
Map<String,String> defCopy = JFXProjectUtils.copyMap(map);
hideEntry(defCopy);
reduct.add(defCopy);
}
}
APP_MULTIPROPS.put(config, reduct);
}
}
public void setDefaultEntriesTransparent(List<Map<String,String/*|null*/>>/*|null*/ entries) {
setEntriesTransparent((String)null, entries);
}
public void setActiveEntriesTransparent(List<Map<String,String/*|null*/>>/*|null*/ entries) {
setEntriesTransparent(getActive(), entries);
}
//----------------------------------------------------------
private void eraseEntry(String config, @NonNull String name) {
assert !configNameWrong(config);
eraseEntry(getEntries(config), name);
}
private void eraseDefaultEntry(@NonNull String name) {
eraseEntry((String)null, name);
}
private void eraseActiveEntry(@NonNull String name) {
eraseEntry(getActive(), name);
}
private void eraseNonDefaultEntries(@NonNull String name, boolean hidden) {
for(String c: getConfigNames()) {
final Map<String, String> entry = getEntry(c, name);
if(c != null && entry != null && isEntryHidden(entry)==hidden ) {
eraseEntry(c, name);
}
}
}
public void eraseEntryTransparent(String config, @NonNull String name) {
assert !configNameWrong(config);
if(config == null) {
eraseNonDefaultEntries(name, true);
eraseDefaultEntry(name); // do not hide (though that should work too)
} else {
if(hasDefaultEntryTransparent(name)) {
if(hasEntry(config, name)) {
hideEntry(config, name);
} else {
Map<String, String> toHide = addEntry(config, name);
hideEntry(toHide);
}
} else {
eraseEntry(config, name);
}
}
}
public void eraseDefaultEntryTransparent(@NonNull String name) {
eraseEntryTransparent((String)null, name);
}
public void eraseActiveEntryTransparent(@NonNull String name) {
eraseEntryTransparent(getActive(), name);
}
private void eraseEntries(String config) {
assert !configNameWrong(config);
APP_MULTIPROPS.remove(config);
}
private void eraseDefaultEntries() {
eraseEntries(null);
}
private void eraseActiveEntries() {
eraseEntries(getActive());
}
public void eraseEntriesTransparent(String config) {
assert !configNameWrong(config);
if(config == null) {
// erase all equal hidden entries in nondefault configs
if(APP_MULTIPROPS.get(null) != null) {
for(Map<String, String> defEntry : APP_MULTIPROPS.get(null)) {
if(!isEntryHidden(defEntry)) {
String name = getEntryName(defEntry);
for(String c: getConfigNames()) {
final Map<String, String> entry = getEntry(c, name);
if(c != null && entry != null && isEntryHidden(entry) ) {
eraseEntry(c, name);
}
}
}
}
}
eraseDefaultEntries(); // do not hide (though that should work too)
} else {
List<Map<String,String>> hidden = new ArrayList<Map<String, String>>();
List<Map<String,String>> configEntries = getEntries(config);
if(configEntries != null) {
for(Map<String, String> map : configEntries) {
String name = getEntryName(map);
if(hasDefaultEntryTransparent(name)) {
Map<String, String> h = JFXProjectUtils.copyMap(map);
hideEntry(h);
hidden.add(h);
}
}
}
APP_MULTIPROPS.put(config, hidden);
}
}
public void eraseDefaultEntriesTransparent() {
eraseEntriesTransparent((String)null);
}
public void eraseActiveEntriesTransparent() {
eraseEntriesTransparent(getActive());
}
//==========================================================
/**
* If entryName exists in entries, returns the map representing it
* Returns null if entry does not exist.
*
* @param entries list of application entries (each stored in a map in keys 'name' and 'value'
* @param entryName entry to be searched for
* @return entry if found, null otherwise
*/
private Map<String, String> getEntry(List<Map<String, String>> entries, String entryName) {
if(entries != null && entryName != null) {
for(Map<String, String> map : entries) {
String name = getEntryName(map);
if(name != null && name.equals(entryName)) {
return map;
}
}
}
return null;
}
private void eraseEntry(List<Map<String, String>> entries, String entryName) {
if(entries != null && entryName != null) {
Map<String, String> toErase = null;
for(Map<String, String> map : entries) {
String name = getEntryName(map);
if(name != null && name.equals(entryName)) {
toErase = map;
break;
}
}
if(toErase != null) {
entries.remove(toErase);
}
}
}
/**
* Erases entry from entries that has name equal to that in 'entry'
* @param entries
* @param entry
*/
private void eraseEntry(List<Map<String, String>> entries, Map<String,String> entry) {
if(entries != null && entry != null) {
String name = getEntryName(entry);
eraseEntry(entries, name);
}
}
//----------------------------------------------------------
private boolean isEntryNameProperty(@NonNull String prop) {
return prop != null && prop.startsWith(prefix) && prop.endsWith(suffixes[0]);
}
private boolean isEntryValueProperty(@NonNull String prop) {
return prop != null && prop.startsWith(prefix) && prop.endsWith(suffixes[1]);
}
private boolean isEntryHiddenProperty(@NonNull String prop) {
return prop != null && prop.startsWith(prefix) && prop.endsWith(suffixes[2]);
}
private String getEntryValueProperty(String entryNameProperty) {
if(entryNameProperty != null && isEntryNameProperty(entryNameProperty)) {
return entryNameProperty.replace(suffixes[0], suffixes[1]);
}
return null;
}
private String getEntryHiddenProperty(String entryNameProperty) {
if(entryNameProperty != null && isEntryNameProperty(entryNameProperty)) {
return entryNameProperty.replace(suffixes[0], suffixes[2]);
}
return null;
}
private String getEntryNameProperty(int index) {
return prefix + index + "." + suffixes[0]; // NOI18N
}
private String getEntryValueProperty(int index) {
return prefix + index + "." + suffixes[1]; // NOI18N
}
private String getEntryHiddenProperty(int index) {
return prefix + index + "." + suffixes[2]; // NOI18N
}
private boolean isFreeEntryPropertyIndex(int index, @NonNull EditableProperties ep) {
return !ep.containsKey(getEntryNameProperty(index));
}
private int getFreeEntryPropertyIndex(int start, @NonNull EditableProperties ep, @NonNull EditableProperties pep, List<String> propNamesUsed) {
int index = (start >= 0) ? start : 0;
while(index >= 0) {
if(isFreeEntryPropertyIndex(index, ep) && isFreeEntryPropertyIndex(index, pep) && (propNamesUsed == null || !propNamesUsed.contains(getEntryNameProperty(index)))) {
break;
}
index++;
}
return (index >= 0) ? index : 0;
}
/**
* Adds/updates properties representing entries in editable properties
*
* @param config
* @param projectProperties project.properties to update
* @param privateProperties private.properties to update
* @param propNamesUsed possibly nonempty list of property names to be avoided (to prevent duplication across various configurations etc)
* @return true if private properties have been updated
*/
private boolean updateEntryProperties(String config, @NonNull EditableProperties projectProperties, @NonNull EditableProperties privateProperties, @NonNull List<String> propNamesUsed) {
assert !configNameWrong(config);
boolean privateUpdated = false;
List<Map<String, String>> reduce = JFXProjectUtils.copyList(getEntries(config));
// remove properties with indexes used before (to be replaced later by new unique property names)
for(String prop : propNamesUsed) {
if(prop != null && prop.length() > 0) {
projectProperties.remove(prop);
projectProperties.remove(getEntryValueProperty(prop));
projectProperties.remove(getEntryHiddenProperty(prop));
privateProperties.remove(prop);
privateProperties.remove(getEntryValueProperty(prop));
privateProperties.remove(getEntryHiddenProperty(prop));
}
}
// delete those private entry properties not present in config
cleanEntryPropertiesIfEmpty(config, privateProperties);
// and log usage of the remaining private entry properties
for(String prop : privateProperties.keySet()) {
if(isEntryNameProperty(prop)) {
propNamesUsed.add(prop);
}
}
// update private properties
List<Map<String, String>> toEraseList = new LinkedList<Map<String, String>>();
for(Map<String, String> map : reduce) { // reduce cannot be null
if(updateEntryPropertyIfExists(map, privateProperties, true)) {
toEraseList.add(map);
privateUpdated = true;
}
}
for(Map<String, String> toErase : toEraseList) {
reduce.remove(toErase);
}
// delete those nonprivate prop properties not present in reduce
cleanEntryPropertiesNotListed(reduce, projectProperties);
// and log usage of the remaining private entry properties
for(String prop : projectProperties.keySet()) {
if(isEntryNameProperty(prop)) {
propNamesUsed.add(prop);
}
}
// now create new nonprivate prop properties
int index = 0;
for(Map<String, String> map : reduce) {
String name = getEntryName(map);
if(name != null && name.length() > 0 && !updateEntryPropertyIfExists(map, projectProperties, false)) {
index = getFreeEntryPropertyIndex(index, projectProperties, privateProperties, propNamesUsed);
exportEntryProperty(map, getEntryNameProperty(index), getEntryValueProperty(index), getEntryHiddenProperty(index), projectProperties);
propNamesUsed.add(getEntryNameProperty(index));
}
}
return privateUpdated;
}
private boolean updateDefaultEntryProperties(@NonNull EditableProperties projectProperties, @NonNull EditableProperties privateProperties, List<String> propNamesUsed) {
return updateEntryProperties(null, projectProperties, privateProperties, propNamesUsed);
}
/**
* Searches in properties for entry named 'name'. If found, updates
* all existing entry properties (for 'name' and 'value' and possibly 'hidden') and returns
* true, otherwise returns false.
*
* @param name entry name
* @param value entry value
* @param properties editable properties in which to search for updateable entries
* @param storeEmpty true==keep empty properties in editable properties, false==remove empty properties
* @return true if updated existing property, false otherwise
*/
private boolean updateEntryPropertyIfExists(Map<String, String> entry, EditableProperties ep, boolean storeEmpty) {
if(entry != null) {
String name = getEntryName(entry);
if(name != null && !name.isEmpty()) {
for(String prop : ep.keySet()) {
if(isEntryNameProperty(prop)) {
if(JFXProjectProperties.isEqualText(name, ep.get(prop))) {
String propVal = getEntryValueProperty(prop);
String value = getEntryValue(entry);
if (value != null && (value.length() > 0 || storeEmpty)) {
ep.setProperty(propVal, value);
} else {
ep.remove(propVal);
}
String propHid = getEntryHiddenProperty(prop);
if(isEntryHidden(entry)) {
ep.setProperty(propHid, APP_MULTIPROP_HIDDEN_TRUE);
} else {
ep.remove(propHid);
}
return true;
}
}
}
}
}
return false;
}
/**
* Remove from ep all prop related properties that represent
* entries not present in config
*
* @param ep editable properties
*/
private void cleanEntryPropertiesIfEmpty(String config, EditableProperties ep) {
assert !configNameWrong(config);
List<String> toRemove = new LinkedList<String>();
for(String prop : ep.keySet()) {
if(isEntryNameProperty(prop)) {
String name = ep.get(prop);
if(!hasEntry(config, name)) {
toRemove.add(prop);
}
}
}
for(String prop : toRemove) {
ep.remove(prop);
ep.remove(getEntryValueProperty(prop));
ep.remove(getEntryHiddenProperty(prop));
}
}
/**
* Remove from ep all entry related properties that represent
* entries not present in 'entries'
*
* @param ep editable properties
*/
private void cleanEntryPropertiesNotListed(List<Map<String, String>> entries, EditableProperties ep) {
List<String> toRemove = new LinkedList<String>();
for(String name : ep.keySet()) {
if(isEntryNameProperty(name)) {
boolean inProps = false;
if(entries != null) {
for(Map<String,String> map : entries) {
String prop = getEntryName(map);
if(JFXProjectProperties.isEqualText(name, prop)) {
inProps = true;
break;
}
}
}
if(!inProps) {
toRemove.add(name);
}
}
}
for(String prop : toRemove) {
ep.remove(prop);
ep.remove(getEntryValueProperty(prop));
ep.remove(getEntryHiddenProperty(prop));
}
}
/**
* Store one entry to editable properties (effectively as two or three properties,
* one for name, second for value, third to mark hidden properties), index is used to distinguish among
* entry-property instances
*
* @param entry property to be stored in editable properties
* @param newPropName name of property to store entry name
* @param newPropValue name of property to store entry value
* @param ep editable properties to which prop is to be stored
*/
private void exportEntryProperty(@NonNull Map<String, String> entry, String newPropName, String newPropValue, String newPropHidden, @NonNull EditableProperties ep) {
String name = getEntryName(entry);
String value = getEntryValue(entry);
if(name != null) {
ep.put(newPropName, name);
if(value != null && value.length() > 0) {
ep.put(newPropValue, value);
}
if(isEntryHidden(entry)) {
ep.put(newPropHidden, APP_MULTIPROP_HIDDEN_TRUE);
}
}
}
// -------------------------------------------------------------------
/**
* Extract from editable properties all properties depicting entries
* and store them as such in 'entries'. If such exist in 'entries', then override their values.
*
* @param ep editable properties to extract from
* @param props application entries to add to / update in
*/
private void extractEntries(@NonNull EditableProperties ep, String config) {
if(ep != null) {
for(String prop : ep.keySet()) {
if(isEntryNameProperty(prop)) {
String name = ep.getProperty(prop);
if(name != null) {
String value = ep.getProperty(getEntryValueProperty(prop));
String hidden = ep.getProperty(getEntryHiddenProperty(prop));
Map<String,String> map = createEntry(name);
if(value != null) {
setEntryValue(map, value);
}
if(hidden != null && JFXProjectProperties.isTrue(hidden)) {
hideEntry(map);
}
addEntry(config, map);
}
}
}
}
}
private void extractDefaultEntries(@NonNull EditableProperties ep) {
extractEntries(ep, null);
}
private void extractActiveEntries(@NonNull EditableProperties ep) {
extractEntries(ep, getActive());
}
/**
* Returns dump of APP_MULTIPROPS. Useful for testing.
* @return string representation of complete class contents
*/
public String toString() {
StringBuilder sb = new StringBuilder(MULTI_PROPERTY_STRING); // getClass().getName()); // NOI18N
sb.append(":"); // NOI18N
List<String> keys = new ArrayList<String>();
keys.addAll(APP_MULTIPROPS.keySet());
Collections.sort(keys, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if(o1 == null) {
if(o2 == null) {
return 0;
}
return -1;
}
if(o2 == null) {
return 1;
}
return o1.compareTo(o2);
}
});
if(keys == null || keys.isEmpty()) {
sb.append(" "); //NOI18N
sb.append(MULTI_PROPERTY_EMPTY);
} else {
for(String configName : keys) {
sb.append(" {"); // NOI18N
sb.append(configName);
sb.append("}"); // NOI18N
List<Map<String,String>> configList = new ArrayList<Map<String,String>>(APP_MULTIPROPS.get(configName));
Collections.sort(configList, new Comparator<Map<String,String>>() {
@Override
public int compare(Map<String, String> o1, Map<String, String> o2) {
String n1 = getEntryName(o1);
String n2 = getEntryName(o2);
if(n1 == null && n2 != null) {
return -1;
} else if (n1 != null && n2 == null) {
return 1;
}
if((n1 == null && n2 == null) || n1.compareTo(n2) == 0) {
String v1 = getEntryValue(o1);
String v2 = getEntryValue(o2);
if(v1 == null && v2 != null) {
return -1;
} else if (v1 != null && v2 == null) {
return 1;
} else if (v1 == null && v2 == null) {
return 0;
}
return v1.compareTo(v2);
}
return n1.compareTo(n2);
}
});
for(Map<String,String> map : configList) {
for(int i=0; i<suffixes.length; i++) {
String s = map.get(suffixes[i]);
if(s != null) {
sb.append(" "); // NOI18N
sb.append(suffixes[i]);
sb.append("="); // NOI18N
sb.append(s);
}
}
}
}
}
return sb.toString();
}
}
}