/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI 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.openengsb.core.api.context; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import com.google.common.base.Preconditions; /** * A Context is a tree-like structure that contains key-value pairs (leafs) and child contexts (inner nodes of the * tree). */ public class Context { private String id; private Map<String, String> values = new TreeMap<String, String>(); private Map<String, Context> children = new TreeMap<String, Context>(); /** * Returns an unmodifiable {@code Set} of keys where values exist at the current {@code Context} level. */ public Set<String> getKeys() { return Collections.unmodifiableSet(values.keySet()); } /** * Returns the value for the given {@code key} or null if the {@code key} has not been set. */ public String get(String key) { Preconditions.checkNotNull(key, "key is null"); return values.get(key); } /** * Puts the {@code key-value} pair at the current {@code Context} level. The {@code key} must not contain any * slashes ({@code '/'}). * * @throws NullPointerException if {@code key} or {@code value} is null * @throws IllegalArgumentException if a child {@code Context} with the given {@code key} exists. */ public void put(String key, String value) { Preconditions.checkNotNull(key, "key is null"); Preconditions.checkNotNull(value, "value is null"); Preconditions.checkArgument(key.indexOf('/') == -1, "key must not contain a slash"); Preconditions.checkArgument(!children.containsKey(key), "key identifies a path, put operation not allowed"); values.put(key, value); } /** * Returns an unmodifiable {@code Map} of child {@code Context}s. */ public Map<String, Context> getChildren() { return Collections.unmodifiableMap(children); } /** * Returns the child {@code Context} for the given {@code name} or null if the child does not exist. */ public Context getChild(String name) { return children.get(name); } /** * Create a new child {@code Context}. The name must not contain any slashes ({@code '/'}). * * @throws IllegalArgumentException if a child or key-value pair with the given @{code name} exists. */ public Context createChild(String name) { Preconditions.checkArgument(name.indexOf('/') == -1, "name must not contain a slash"); Preconditions.checkArgument(!children.containsKey(name), "child with name '%s' already exists", name); Preconditions.checkArgument(!values.containsKey(name), "name identifies a key-value pair", "createChild operation not allowed"); Context child = new Context(); children.put(name, child); return child; } /** * Removes the child {@code Context} or key-value pair the given parameter identifies. */ public void remove(String nameOrKey) { Preconditions.checkNotNull(nameOrKey, "name or key for removal is null"); values.remove(nameOrKey); children.remove(nameOrKey); } public void setId(String id) { this.id = id; } public String getId() { return this.id; } @Override public String toString() { StringBuffer result = new StringBuffer(); for (Entry<String, Context> ch : children.entrySet()) { String child = ch.getValue().toString(); String elem = ch.getKey() + ":\n" + indent(child) + "\n"; result.append(elem); } for (Entry<String, String> val : values.entrySet()) { String elem = val.getKey() + " = " + val.getValue() + "\n"; result.append(elem); } return result.toString(); } private static final String INDENTION_STRING = ".."; private static String indent(String arg) { String s1 = INDENTION_STRING + arg.replaceAll("\n", "\n" + INDENTION_STRING); String s2 = s1.replaceAll("\n" + INDENTION_STRING + "$", ""); return s2; } }