/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.common; import java.util.Objects; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.api.NodeIdentifierService; /** * Utility methods for handling node identifiers and related exception. All methods that require a {@link NodeIdentifierService} instance * call {@link NodeIdentifierContextHolder#getDeserializationServiceForCurrentThread()} implicitly. * * @author Robert Mischke */ public final class NodeIdentifierUtils { private NodeIdentifierUtils() {} /** * Recreates a {@link InstanceNodeId} from the string representation returned by {@link InstanceNodeSessionId#getInstanceNodeIdString()} * . * * @see NodeIdentifierService#parseInstanceNodeIdString(String) * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful * @throws IdentifierException on failure, typically because of a null or malformed string representation */ public static InstanceNodeId parseInstanceNodeIdString(String input) throws IdentifierException { return getNodeIdentifierServiceForCurrentThread().parseInstanceNodeIdString(input); } /** * Transitional method; forwards to {@link #parseInstanceNodeIdString(String)}, but maps any {@link IdentifierException} to a * RuntimeException. * * TODO >= 8.0.0: replace calls to this with proper exception handling * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful */ public static InstanceNodeId parseInstanceNodeIdStringWithExceptionWrapping(String input) { try { return parseInstanceNodeIdString(input); } catch (IdentifierException e) { throw wrapIdentifierException(e); } } /** * Recreates a {@link InstanceSessionIdId} from the string representation returned by * {@link InstanceNodeSessionId#getInstanceNodeSessionIdString()}. * * @see NodeIdentifierService#parseInstanceNodeSessionIdString(String) * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful * @throws IdentifierException on failure, typically because of a null or malformed string representation */ public static InstanceNodeSessionId parseInstanceNodeSessionIdString(String input) throws IdentifierException { return getNodeIdentifierServiceForCurrentThread().parseInstanceNodeSessionIdString(input); } /** * Transitional method; forwards to {@link #parseInstanceNodeIdString(String)}, but maps any {@link IdentifierException} to a * RuntimeException. * * TODO >= 8.0.0: replace calls to this with proper exception handling * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful */ public static InstanceNodeSessionId parseInstanceNodeSessionIdStringWithExceptionWrapping(String input) { try { return parseInstanceNodeSessionIdString(input); } catch (IdentifierException e) { throw wrapIdentifierException(e); } } /** * Recreates a {@link LogicalNodeId} from the string representation returned by {@link LogicalNodeSessionId#getLogicalNodeIdString()}. * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful * @throws IdentifierException on failure, typically because of a null or malformed string representation */ public static LogicalNodeId parseLogicalNodeIdString(String input) throws IdentifierException { return getNodeIdentifierServiceForCurrentThread().parseLogicalNodeIdString(input); } /** * As {@link #parseLogicalNodeIdString(String)}, but with implicit exception wrapping until migration is complete. * * TODO >= 8.0.0: replace calls to this with proper exception handling * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful */ public static LogicalNodeId parseLogicalNodeIdStringWithExceptionWrapping(String input) { try { return parseLogicalNodeIdString(input); } catch (IdentifierException e) { throw wrapIdentifierException(e); } } /** * Special backwards compatibility method. Behaves as {@link #parseLogicalNodeIdString()}, but also accepts other id strings, which are * mapped to the default {@link LogicalNodeId} for that {@link InstanceNodeId}. * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful * @throws IdentifierException on failure, typically because of a null or malformed string representation */ public static LogicalNodeId parseArbitraryIdStringToLogicalNodeId(String input) throws IdentifierException { // TODO (p2) move method into service? Objects.requireNonNull(input, "Cannot parse 'null' string to a node identifier"); // null ids are not allowed since 8.0 final int length = input.length(); if (length == CommonIdBase.INSTANCE_ID_STRING_LENGTH) { return parseInstanceNodeIdString(input).convertToDefaultLogicalNodeId(); } else if (length == CommonIdBase.INSTANCE_SESSION_ID_STRING_LENGTH) { return parseInstanceNodeSessionIdString(input).convertToDefaultLogicalNodeId(); } else { // logical node or logical node session id; determine by looking at the separator positions int pos = input.lastIndexOf(CommonIdBase.STRING_FORM_PART_SEPARATOR); if (pos == CommonIdBase.INSTANCE_ID_STRING_LENGTH) { // only one separator; the one after the instance part -> logical node id return parseLogicalNodeIdString(input); } else { if (pos < 0) { throw new IdentifierException("Unexpected state while trying to parse arbitrary id string '" + input + "'"); } // by exclusion, assuming a logical node id now return parseLogicalNodeSessionIdString(input).convertToLogicalNodeId(); } } } /** * As {@link #parseArbitraryIdStringToLogicalNodeId(String)}, but with implicit exception wrapping until migration is complete. * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful */ public static LogicalNodeId parseArbitraryIdStringToLogicalNodeIdWithExceptionWrapping(String input) { try { return parseArbitraryIdStringToLogicalNodeId(input); } catch (IdentifierException e) { throw wrapIdentifierException(e); } } /** * Recreates a {@link LogicalNodeSessionId} from the string representation returned by * {@link LogicalNodeSessionId#getLogicalNodeSessionIdString()}. * * @param input the string representation to reconstruct the object from * @return the reconstructed object, if successful * @throws IdentifierException on failure, typically because of a null or malformed string representation */ public static LogicalNodeSessionId parseLogicalNodeSessionIdString(String input) throws IdentifierException { return getNodeIdentifierServiceForCurrentThread().parseLogicalNodeSessionIdString(input); } /** * Central method to wrap {@link IdentifierException}s as {@link RuntimeException}s in places where proper exception handling is not * currently possible (as the old code did not cause such exceptions, instead failing silently or with undefined behavior). Obviously, * calls to this method should be eliminated better sooner than later. * * @param e the exception to wrap * @return the wrapping {@link RuntimeException} */ public static RuntimeException wrapIdentifierException(IdentifierException e) { LogFactory.getLog(NodeIdentifierUtils.class).error("Wrapping IdentifierException for backwards compatibility", e); return new RuntimeException("Wrapping identifier exception for backwards compatibility", e); } private static NodeIdentifierService getNodeIdentifierServiceForCurrentThread() { return NodeIdentifierContextHolder.getDeserializationServiceForCurrentThread(); } }