ContextUtil.java
- package nl.tudelft.simulation.naming.context.util;
- import java.rmi.RemoteException;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map.Entry;
- import javax.naming.NameNotFoundException;
- import javax.naming.NamingException;
- import nl.tudelft.simulation.naming.context.ContextInterface;
- /**
- * ContextUtil contains a few helper methods to deal with an InitialEventContext.
- * <p>
- * Copyright (c) 2020-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
- * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
- * project is distributed under a three-clause BSD-style license, which can be found at
- * <a href="https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
- * </p>
- * @author <a href="https://github.com/averbraeck" target="_blank">Alexander Verbraeck</a>
- */
- public class ContextUtil
- {
- /**
- * Lookup or create a sub-context in the parentContext with the name as its path. The path can be absolute or relative. The
- * terminating part of the name will be used as the key under which the created subcontext will be registered.
- * @param parentContext ContextInterface; the parent context
- * @param name String; the name to register the new subcontext
- * @return ContextInterface; the newly created subcontext
- * @throws NamingException when terminating key in the name is blank or contains "/" character(s)
- * @throws RemoteException on a network error when the Context is used over RMI
- */
- public static ContextInterface lookupOrCreateSubContext(final ContextInterface parentContext, final String name)
- throws NamingException, RemoteException
- {
- try
- {
- if (parentContext.exists(name))
- {
- Object result = parentContext.get(name);
- if (result instanceof ContextInterface)
- return (ContextInterface) result;
- throw new NamingException(
- "lookup for " + name + " in context " + parentContext + " returned object that is not a Context");
- }
- }
- catch (NameNotFoundException nnfe)
- {
- // ignore -- create the context path
- }
- return parentContext.createSubcontext(name);
- }
- /**
- * Lookup a sub-context in the parentContext with the name as its path. The path can be absolute or relative. The
- * terminating part of the name will be used as the key under which the created subcontext will be registered.
- * @param parentContext ContextInterface; the parent context
- * @param name String; the name to register the new subcontext
- * @return ContextInterface; the newly created subcontext
- * @throws NamingException when terminating key in the name is blank or contains "/" character(s)
- * @throws RemoteException on a network error when the Context is used over RMI
- */
- public static ContextInterface lookupSubContext(final ContextInterface parentContext, final String name)
- throws NamingException, RemoteException
- {
- if (parentContext.exists(name))
- {
- Object result = parentContext.get(name);
- if (result instanceof ContextInterface)
- return (ContextInterface) result;
- throw new NamingException(
- "lookup for " + name + " in context " + parentContext + " returned object that is not a Context");
- }
- throw new NamingException("Context " + name + " not found in parentContext " + parentContext);
- }
- /**
- * Destroy a sub-context in the parentContext with the name as its path. The path can be absolute or relative. The
- * terminating part of the name will be used as the key under for the subcontext to be removed.
- * @param parentContext ContextInterface; the parent context
- * @param name String; the name to use to find the subcontext to remove
- * @throws NamingException when terminating key in the name is blank or contains "/" character(s)
- * @throws RemoteException on a network error when the Context is used over RMI
- */
- public static void destroySubContext(final ContextInterface parentContext, final String name)
- throws NamingException, RemoteException
- {
- parentContext.destroySubcontext(name);
- }
- /**
- * Resolve the key(s) for an object for a given context. This can be an expensive operation if the context is large. An
- * object can be registered zero or more times in the context, so a List of keys under which the object is registered will
- * be returned. The keys are relative to the startContext. The method starts with the given context. It is possible to look
- * up null objects in the Context.
- * @param startContext ContextInterface; the context to start the search
- * @param object Object; the object to look up in the tree under the startContext
- * @return List<String>; the list of keys that are bound to the object, or an empty list if no bindings for the object
- * were found
- * @throws NamingException when an error occurs during searching
- * @throws RemoteException on a network error when the Context is used over RMI
- */
- public static List<String> resolveKeys(final ContextInterface startContext, final Object object)
- throws NamingException, RemoteException
- {
- List<String> result = new ArrayList<>();
- resolveKeys(startContext, object, result, "");
- return result;
- }
- /**
- * Resolve the key(s) for an object for a given context. This can be an expensive operation if the context is large. An
- * object can be registered zero or more times in the context, so a List of keys under which the object is registered will
- * be returned. The keys are relative to the startContext. The method starts with the given context. It is possible to look
- * up null objects in the Context.
- * @param context ContextInterface; the context to start the search
- * @param object Object; the object to look up in the tree under the startContext
- * @param result List<String>; the current list of keys that are bound to the object, or an empty list if no bindings
- * for the object were found yet
- * @param partialKey the key of the current level in the tree, relative to the original start context of the search
- * @throws NamingException when an error occurs during searching
- * @throws RemoteException on a network error when the Context is used over RMI
- */
- private static void resolveKeys(final ContextInterface context, final Object object, final List<String> result,
- final String partialKey) throws NamingException, RemoteException
- {
- for (Entry<String, Object> binding : context.bindings().entrySet())
- {
- Object value = binding.getValue();
- if (value instanceof ContextInterface)
- {
- resolveKeys((ContextInterface) value, object, result,
- partialKey + ContextInterface.SEPARATOR + binding.getKey());
- }
- // no else; we might be looking for an object that implements ContextInterface
- if ((value == null && object == null) || (value != null && value.equals(object)))
- {
- result.add(partialKey + ContextInterface.SEPARATOR + binding.getKey());
- }
- }
- }
- /**
- * recursively print the context in human-readable format to a String.
- * @param ctx the context to print
- * @return a human-readable String with the context tree
- */
- public static String toText(final ContextInterface ctx)
- {
- return toText(ctx, new StringBuffer(), 0);
- }
- /**
- * recursively print the context in human-readable format to a String.
- * @param ctx the context to print
- * @param sb the StringBuffer to add the information to
- * @param indent the indentation on the screen
- * @return a human-readable String with the context tree
- */
- private static String toText(final ContextInterface ctx, final StringBuffer sb, final int indent)
- {
- try
- {
- if (indent > 0)
- {
- sb.append(String.join("", Collections.nCopies(indent - 1, "| ")));
- sb.append("+ ");
- }
- sb.append("CTX ");
- sb.append(ctx.getAtomicName());
- sb.append("\n");
- for (String key : ctx.keySet())
- {
- Object obj = ctx.getObject(key);
- if (obj instanceof ContextInterface)
- {
- toText((ContextInterface) obj, sb, indent + 1);
- }
- else
- {
- sb.append(String.join("", Collections.nCopies(indent, "| ")));
- sb.append("+ ");
- sb.append(key);
- sb.append("=");
- sb.append(obj);
- sb.append("\n");
- }
- }
- }
- catch (NamingException | RemoteException exception)
- {
- sb.append("ERR " + exception.getMessage() + "\n");
- }
- return sb.toString();
- }
- }