00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package org.ros.internal.node.server;
00018
00019 import java.util.Collection;
00020 import java.util.List;
00021 import java.util.Map;
00022 import java.util.Set;
00023 import java.util.Stack;
00024
00025 import org.apache.commons.logging.Log;
00026 import org.apache.commons.logging.LogFactory;
00027 import org.ros.internal.node.client.SlaveClient;
00028 import org.ros.namespace.GraphName;
00029
00030 import com.google.common.base.Preconditions;
00031 import com.google.common.collect.HashMultimap;
00032 import com.google.common.collect.Maps;
00033 import com.google.common.collect.Multimap;
00034 import com.google.common.collect.Multimaps;
00035 import com.google.common.collect.Sets;
00036
00042 public class ParameterServer {
00043
00044 private static final Log log = LogFactory.getLog(ParameterServer.class);
00045
00046 private final Map<String, Object> tree;
00047 private final Multimap<GraphName, NodeIdentifier> subscribers;
00048 private final GraphName masterName;
00049
00050 public ParameterServer() {
00051 tree = Maps.newConcurrentMap();
00052 subscribers = Multimaps.synchronizedMultimap(HashMultimap.<GraphName, NodeIdentifier>create());
00053 masterName = GraphName.of("/master");
00054 }
00055
00056 public void subscribe(GraphName name, NodeIdentifier nodeIdentifier) {
00057 subscribers.put(name, nodeIdentifier);
00058 }
00059
00060 private Stack<String> getGraphNameParts(GraphName name) {
00061 Stack<String> parts = new Stack<String>();
00062 GraphName tip = name;
00063 while (!tip.isRoot()) {
00064 parts.add(tip.getBasename().toString());
00065 tip = tip.getParent();
00066 }
00067 return parts;
00068 }
00069
00070 @SuppressWarnings("unchecked")
00071 public Object get(GraphName name) {
00072 Preconditions.checkArgument(name.isGlobal());
00073 Stack<String> parts = getGraphNameParts(name);
00074 Object possibleSubtree = tree;
00075 while (!parts.empty() && possibleSubtree != null) {
00076 if (!(possibleSubtree instanceof Map)) {
00077 return null;
00078 }
00079 possibleSubtree = ((Map<String, Object>) possibleSubtree).get(parts.pop());
00080 }
00081 return possibleSubtree;
00082 }
00083
00084 @SuppressWarnings("unchecked")
00085 private void setValue(GraphName name, Object value) {
00086 Preconditions.checkArgument(name.isGlobal());
00087 Stack<String> parts = getGraphNameParts(name);
00088 Map<String, Object> subtree = tree;
00089 while (!parts.empty()) {
00090 String part = parts.pop();
00091 if (parts.empty()) {
00092 subtree.put(part, value);
00093 } else if (subtree.containsKey(part) && subtree.get(part) instanceof Map) {
00094 subtree = (Map<String, Object>) subtree.get(part);
00095 } else {
00096 Map<String, Object> newSubtree = Maps.newHashMap();
00097 subtree.put(part, newSubtree);
00098 subtree = newSubtree;
00099 }
00100 }
00101 }
00102
00103 private interface Updater {
00104 void update(SlaveClient client);
00105 }
00106
00107 private <T> void update(GraphName name, T value, Updater updater) {
00108 setValue(name, value);
00109 synchronized (subscribers) {
00110 for (NodeIdentifier nodeIdentifier : subscribers.get(name)) {
00111 SlaveClient client = new SlaveClient(masterName, nodeIdentifier.getUri());
00112 try {
00113 updater.update(client);
00114 } catch (Exception e) {
00115 log.error(e);
00116 }
00117 }
00118 }
00119 }
00120
00121 public void set(final GraphName name, final boolean value) {
00122 update(name, value, new Updater() {
00123 @Override
00124 public void update(SlaveClient client) {
00125 client.paramUpdate(name, value);
00126 }
00127 });
00128 }
00129
00130 public void set(final GraphName name, final int value) {
00131 update(name, value, new Updater() {
00132 @Override
00133 public void update(SlaveClient client) {
00134 client.paramUpdate(name, value);
00135 }
00136 });
00137 }
00138
00139 public void set(final GraphName name, final double value) {
00140 update(name, value, new Updater() {
00141 @Override
00142 public void update(SlaveClient client) {
00143 client.paramUpdate(name, value);
00144 }
00145 });
00146 }
00147
00148 public void set(final GraphName name, final String value) {
00149 update(name, value, new Updater() {
00150 @Override
00151 public void update(SlaveClient client) {
00152 client.paramUpdate(name, value);
00153 }
00154 });
00155 }
00156
00157 public void set(final GraphName name, final List<?> value) {
00158 update(name, value, new Updater() {
00159 @Override
00160 public void update(SlaveClient client) {
00161 client.paramUpdate(name, value);
00162 }
00163 });
00164 }
00165
00166 public void set(final GraphName name, final Map<?, ?> value) {
00167 update(name, value, new Updater() {
00168 @Override
00169 public void update(SlaveClient client) {
00170 client.paramUpdate(name, value);
00171 }
00172 });
00173 }
00174
00175 @SuppressWarnings("unchecked")
00176 public void delete(GraphName name) {
00177 Preconditions.checkArgument(name.isGlobal());
00178 Stack<String> parts = getGraphNameParts(name);
00179 Map<String, Object> subtree = tree;
00180 while (!parts.empty() && subtree.containsKey(parts.peek())) {
00181 String part = parts.pop();
00182 if (parts.empty()) {
00183 subtree.remove(part);
00184 } else {
00185 subtree = (Map<String, Object>) subtree.get(part);
00186 }
00187 }
00188 }
00189
00190 public Object search(GraphName name) {
00191 throw new UnsupportedOperationException();
00192 }
00193
00194 @SuppressWarnings("unchecked")
00195 public boolean has(GraphName name) {
00196 Preconditions.checkArgument(name.isGlobal());
00197 Stack<String> parts = getGraphNameParts(name);
00198 Map<String, Object> subtree = tree;
00199 while (!parts.empty() && subtree.containsKey(parts.peek())) {
00200 String part = parts.pop();
00201 if (!parts.empty()) {
00202 subtree = (Map<String, Object>) subtree.get(part);
00203 }
00204 }
00205 return parts.empty();
00206 }
00207
00208 @SuppressWarnings("unchecked")
00209 private Set<GraphName> getSubtreeNames(GraphName parent, Map<String, Object> subtree,
00210 Set<GraphName> names) {
00211 for (String name : subtree.keySet()) {
00212 Object possibleSubtree = subtree.get(name);
00213 if (possibleSubtree instanceof Map) {
00214 names.addAll(getSubtreeNames(parent.join(GraphName.of(name)),
00215 (Map<String, Object>) possibleSubtree, names));
00216 } else {
00217 names.add(parent.join(GraphName.of(name)));
00218 }
00219 }
00220 return names;
00221 }
00222
00223 public Collection<GraphName> getNames() {
00224 Set<GraphName> names = Sets.newHashSet();
00225 return getSubtreeNames(GraphName.root(), tree, names);
00226 }
00227
00228 }