Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
package com.marginallyclever.util;
import org.json.JSONObject;
import org.json.Property;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import static com.marginallyclever.util.PreferencesHelper.MakelangeloPreferenceKey.*;
/**
* Helper class to be used when accessing preferences.
* @author Peter Colapietro
* @since v7.1.4
*/
public final class PreferencesHelper {
private static final Logger logger = LoggerFactory.getLogger(PreferencesHelper.class);
/**
* Internal mapping of all Makelangelo preference nodes.
*/
private static Map<MakelangeloPreferenceKey, Preferences> CLASS_TO_PREFERENCE_NODE_MAP;
/**
* Future Makelagelo root preference node path name.
*/
@SuppressWarnings("unused")
private static final String MAKELANGELO_ROOT_PATH_NAME = PreferencesHelper.class.getPackage().getName();
/**
* Load saved values
*/
@SuppressWarnings("unchecked")
static public void start() {
Map<MakelangeloPreferenceKey, ? super Preferences> initialMap = new HashMap<>();
Preferences userRootPreferencesNode = MarginallyCleverPreferences.userRoot();
final Preferences legacyMakelangeloPreferenceNode = userRootPreferencesNode.node(LEGACY_MAKELANGELO_ROOT.getNodeName());
try {
legacyMakelangeloPreferenceNode.sync();
} catch (BackingStoreException e) {
logger.error("Failed to sync pref", e);
}
initialMap.put(LEGACY_MAKELANGELO_ROOT, legacyMakelangeloPreferenceNode);
initialMap.put(GRAPHICS, legacyMakelangeloPreferenceNode.node(GRAPHICS.getNodeName()));
initialMap.put(MACHINES, legacyMakelangeloPreferenceNode.node(MACHINES.getNodeName()));
initialMap.put(LANGUAGE, legacyMakelangeloPreferenceNode.node(LANGUAGE.getNodeName()));
initialMap.put(SOUND, legacyMakelangeloPreferenceNode.node(SOUND.getNodeName()));
initialMap.put(METRICS, legacyMakelangeloPreferenceNode.node(METRICS.getNodeName()));
initialMap.put(PAPER, legacyMakelangeloPreferenceNode.node(PAPER.getNodeName()));
initialMap.put(FILE, legacyMakelangeloPreferenceNode.node(FILE.getNodeName()));
Map<? extends MakelangeloPreferenceKey, ? extends Preferences> castedMap = (Map<? extends MakelangeloPreferenceKey, ? extends Preferences>) initialMap;
CLASS_TO_PREFERENCE_NODE_MAP = Collections.unmodifiableMap(castedMap);
}
/**
* Enumeration used when getting a specific preference node.
* See #getPreferenceNode(MakelangeloPreferenceKey)
*/
public enum MakelangeloPreferenceKey {
/**
* Graphics preference node path, used to store things such as {@code "Draw all while running"} used when OpenGL
* renders the application.
*/
GRAPHICS("Graphics"),
/**
* Machine preference node path, used to store things such as paper height and width, invert left and right motors,
* etc.
* See com.marginallyclever.makelangeloRobot.plottersettings.MakelangeloRobotSettings
*/
MACHINES("Machines"),
LANGUAGE("Language"),
SOUND("Sound"),
FILE("File"),
METRICS("Metrics"),
PAPER("Paper"),
/**
* Legacy preference node path.
*/
@Deprecated
LEGACY_MAKELANGELO_ROOT("DrawBot");
MakelangeloPreferenceKey(String nodeName) {
this.nodeName = nodeName;
}
private String nodeName;
public String getNodeName() {
return nodeName;
}
}
/**
* NOOP Constructor.
*
* @throws IllegalStateException
*/
private PreferencesHelper() throws IllegalStateException {
throw new IllegalStateException();
}
/**
* @param key enumeration key used to look up a Makelangelo preference value.
* @return preference node associated with the given key.
*/
@SuppressWarnings("unchecked")
public static <P extends Preferences> P getPreferenceNode(MakelangeloPreferenceKey key) {
return (P) CLASS_TO_PREFERENCE_NODE_MAP.get(key);
}
/**
* @param preferenceNode Preference node whose name, and key values,
* as well as those of its children's are to be logged.
*/
public static <P extends Preferences> void logPreferenceNode(P preferenceNode) {
try {
if (logger.isDebugEnabled()) {
logger.debug("node name:{}", preferenceNode);
logKeyValuesForPreferenceNode(preferenceNode);
final String[] childrenPreferenceNodeNames = preferenceNode.childrenNames();
for (String childNodeName : childrenPreferenceNodeNames) {
final Preferences childNode = preferenceNode.node(childNodeName);
logPreferenceNode(childNode);
}
}
} catch (BackingStoreException e) {
logger.error("Failed to log node {}", preferenceNode, e);
}
}
/**
* @param preferenceNode Preference node to log key value pairs for.
*/
public static <P extends Preferences> void logKeyValuesForPreferenceNode(P preferenceNode) throws BackingStoreException {
final String[] keys = preferenceNode.keys();
for (String key : keys) {
logger.debug("key:{} value:{}", key, preferenceNode.get(key, null));
}
}
/**
* @param sourcePreferenceNode Preference node to be copied from.
* @param destinationPreferenceNode Preference node to be copied to.
*/
public static <P extends Preferences> void copyPreferenceNode(P sourcePreferenceNode, P destinationPreferenceNode) {
try {
final String[] keys = sourcePreferenceNode.keys();
for (String key : keys) {
final String value = sourcePreferenceNode.get(key, null);
destinationPreferenceNode.put(key, value);
}
final String[] childNames = sourcePreferenceNode.childrenNames();
for (String childName : childNames) {
final Preferences destinationChildNode = destinationPreferenceNode.node(childName);
copyPreferenceNode(sourcePreferenceNode.node(childName), destinationChildNode);
}
} catch (BackingStoreException e) {
logger.error("Failed to copy preference", e);
}
}
/**
* Recursively clears all the preferences (key-value associations) for a given node and its children.
*
* @param preferenceNode Preference node that you want recursively cleared of all key value pairs.
* See <a href="http://stackoverflow.com/a/6411855"></a>
*/
private static <P extends Preferences> void clearAll(P preferenceNode) throws BackingStoreException {
final String[] childrenNames = preferenceNode.childrenNames();
for (String childNodeName : childrenNames) {
final Preferences childNode = preferenceNode.node(childNodeName);
final String[] childNodesChildren = childNode.childrenNames();
if (childNodesChildren != null) {
final boolean hasChildren = childNodesChildren.length != 0;
if (hasChildren) {
clearAll(childNode);
}
childNode.clear();
}
}
preferenceNode.clear();
}
/**
* Removes all of the preferences (key-value associations) in this
* preference node with no effect on any descendants
* of this node.
*/
@SuppressWarnings("unused")
private static <P extends Preferences> void shallowClearPreferences(P preferenceNode) {
try {
preferenceNode.clear();
} catch (BackingStoreException e) {
logger.error("Failed to clear preference", e);
}
}
/**
* Removes all of the preferences (key-value associations) in this
* preference node and any descendants of this node.
*/
@SuppressWarnings("unused")
private static <P extends Preferences> void deepClearPreferences(P preferenceNode) {
try {
preferenceNode.clear();
final String[] childrenPreferenceNodeNames = preferenceNode.childrenNames();
for (String childNodeName : childrenPreferenceNodeNames) {
final Preferences childNode = preferenceNode.node(childNodeName);
childNode.clear();
}
} catch (BackingStoreException e) {
logger.error("Failed to deep clear preference", e);
}
}
/**
* @param sourcePreferenceNode Preference node to be copied from.
* @param destinationPreferenceNode Preference node to be copied to and logged.
* <br>
* {@link #copyPreferenceNode(Preferences, Preferences)}
* <br>
* {@link #logPropertiesNode(Properties)}
* <br>
* {@link #logAncestryable(Ancestryable)}
*/
@SuppressWarnings("unused")
private void copyAndLogPreferenceNode(AbstractPreferences sourcePreferenceNode, MarginallyCleverPreferences destinationPreferenceNode) {
try {
PreferencesHelper.clearAll(destinationPreferenceNode);
} catch (BackingStoreException e) {
logger.error(e.getMessage());
}
PreferencesHelper.copyPreferenceNode(sourcePreferenceNode, destinationPreferenceNode);
final File preferencesFile = MarginallyCleverPreferencesFileFactory.getPropertiesPreferencesFile();
final Properties p = new Properties();
try (final FileInputStream inStream = new FileInputStream(preferencesFile)) {
p.load(inStream);
} catch (IOException e) {
logger.error("Failed to copy preference file {}", preferencesFile, e);
}
logPropertiesNode(p);
logAncestryable(destinationPreferenceNode);
}
/**
* @param preferenceNode preference node to be logged.
*/
public static void logAncestryable(Ancestryable preferenceNode) {
final JSONObject object = new JSONObject(preferenceNode.getChildren());
logger.debug( object.toString());
}
/**
* @param properties Properties to be logged.
*/
public static <P extends Properties> void logPropertiesNode(P properties) {
final JSONObject jsonObject = Property.toJSONObject(properties);
logger.debug( jsonObject.toString());
}
}
f99985dc8This file is pinned to the selected release. Download the original to open it in your design tool.