Java tutorial
// Copyright 2017 JanusGraph Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package org.janusgraph.diskstorage.configuration; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import org.janusgraph.core.util.ReflectiveConfigOptionLoader; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.HashCodeBuilder; import java.util.List; /** * @author Matthias Broecheler (me@matthiasb.com) */ public abstract class ConfigElement { public static final char SEPARATOR = '.'; public static final char[] ILLEGAL_CHARS = new char[] { SEPARATOR, ' ', '\t', '#', '@', '<', '>', '?', '/', ';', '"', '\'', ':', '+', '(', ')', '*', '^', '`', '~', '$', '%', '|', '\\', '{', '[', ']', '}' }; private final ConfigNamespace namespace; private final String name; private final String description; public ConfigElement(ConfigNamespace namespace, String name, String description) { Preconditions.checkArgument(StringUtils.isNotBlank(name), "Name cannot be empty: %s", name); Preconditions.checkArgument(!StringUtils.containsAny(name, ILLEGAL_CHARS), "Name contains illegal character: %s (%s)", name, ILLEGAL_CHARS); Preconditions.checkArgument(namespace != null || this instanceof ConfigNamespace, "Need to specify namespace for ConfigOption"); Preconditions.checkArgument(StringUtils.isNotBlank(description)); this.namespace = namespace; this.name = name; this.description = description; if (namespace != null) namespace.registerChild(this); } public ConfigNamespace getNamespace() { Preconditions.checkArgument(namespace != null, "Cannot get namespace of root"); return namespace; } public boolean isRoot() { return namespace == null; } public ConfigNamespace getRoot() { if (isRoot()) return (ConfigNamespace) this; else return getNamespace().getRoot(); } public String getName() { return name; } public String getDescription() { return description; } public abstract boolean isOption(); public boolean isNamespace() { return !isOption(); } @Override public String toString() { return (namespace != null ? namespace.toString() + SEPARATOR : "") + name; } @Override public int hashCode() { return new HashCodeBuilder().append(name).append(namespace).toHashCode(); } @Override public boolean equals(Object oth) { if (this == oth) return true; else if (oth == null || !getClass().isInstance(oth)) return false; ConfigElement c = (ConfigElement) oth; return name.equals(c.name) && namespace == c.namespace; } public static String[] getComponents(final String path) { return StringUtils.split(path, SEPARATOR); } public static String toStringSingle(ConfigElement element) { return toStringSingle(element, ""); } private static String toStringSingle(ConfigElement element, String indent) { String result = element.getName(); if (element.isNamespace()) { result = "+ " + result; if (((ConfigNamespace) element).isUmbrella()) result += " [*]"; } else { result = "- " + result; ConfigOption option = (ConfigOption) element; result += " ["; switch (option.getType()) { case FIXED: result += "f"; break; case GLOBAL_OFFLINE: result += "g!"; break; case GLOBAL: result += "g"; break; case MASKABLE: result += "m"; break; case LOCAL: result += "l"; break; } result += "," + option.getDatatype().getSimpleName(); result += "," + option.getDefaultValue(); result += "]"; } result = indent + result + "\n" + indent; String desc = element.getDescription(); result += "\t" + '"' + desc.substring(0, Math.min(desc.length(), 50)) + '"'; return result; } public static String toString(ConfigElement element) { //return toStringRecursive(element,""); return toStringSingle(element, ""); } // private static String toStringRecursive(ConfigElement element, String indent) { // String result = toStringSingle(element, indent) + "\n"; // if (element.isNamespace()) { // ConfigNamespace ns = (ConfigNamespace)element; // indent += "\t"; // for (ConfigElement child : ns.getChildren()) { // result += toStringRecursive(child,indent); // } // } // return result; // } public static String getPath(ConfigElement element, String... umbrellaElements) { return getPath(element, false, umbrellaElements); } public static String getPath(ConfigElement element, boolean includeRoot, String... umbrellaElements) { Preconditions.checkNotNull(element); if (umbrellaElements == null) umbrellaElements = new String[0]; String path = element.getName(); int umbrellaPos = umbrellaElements.length - 1; while (!element.isRoot() && !element.getNamespace().isRoot()) { ConfigNamespace parent = element.getNamespace(); if (parent.isUmbrella()) { Preconditions.checkArgument(umbrellaPos >= 0, "Missing umbrella element path for element: %s", element); String umbrellaName = umbrellaElements[umbrellaPos]; Preconditions.checkArgument(!StringUtils.containsAny(umbrellaName, ILLEGAL_CHARS), "Invalid umbrella name provided: %s. Contains illegal chars", umbrellaName); path = umbrellaName + SEPARATOR + path; umbrellaPos--; } path = parent.getName() + SEPARATOR + path; element = parent; } if (includeRoot) { // Assumes that roots are not umbrellas // If roots could be umbrellas, we might have to change the interpretation of umbrellaElements path = (element.isRoot() ? element.getName() : element.getNamespace().getName()) + SEPARATOR + path; } //Don't make this check so that we can still access more general config items Preconditions.checkArgument(umbrellaPos < 0, "Found unused umbrella element: %s", umbrellaPos < 0 ? null : umbrellaElements[umbrellaPos]); return path; } public static PathIdentifier parse(ConfigNamespace root, String path) { Preconditions.checkNotNull(root); if (StringUtils.isBlank(path)) return new PathIdentifier(root, new String[] {}, false); String[] components = getComponents(path); Preconditions.checkArgument(components.length > 0, "Empty path provided: %s", path); List<String> umbrellaElements = Lists.newArrayList(); ConfigNamespace parent = root; ConfigElement last = root; boolean lastIsUmbrella = false; for (int i = 0; i < components.length; i++) { if (parent.isUmbrella() && !lastIsUmbrella) { umbrellaElements.add(components[i]); lastIsUmbrella = true; } else { last = parent.getChild(components[i]); Preconditions.checkArgument(last != null, "Unknown configuration element in namespace [%s]: %s", parent.toString(), components[i]); if (i + 1 < components.length) { Preconditions.checkArgument(last instanceof ConfigNamespace, "Expected namespace at position [%s] of [%s] but got: %s", i, path, last); parent = (ConfigNamespace) last; } lastIsUmbrella = false; } } return new PathIdentifier(last, umbrellaElements.toArray(new String[umbrellaElements.size()]), lastIsUmbrella); } public static class PathIdentifier { public final ConfigElement element; public final String[] umbrellaElements; public final boolean lastIsUmbrella; private PathIdentifier(ConfigElement element, String[] umbrellaElements, boolean lastIsUmbrella) { this.lastIsUmbrella = lastIsUmbrella; Preconditions.checkNotNull(element); Preconditions.checkNotNull(umbrellaElements); this.element = element; this.umbrellaElements = umbrellaElements; } public boolean hasUmbrellaElements() { return umbrellaElements.length > 0; } } }