/*
* Copyright 2016 Kevin Herron
*
* 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 com.digitalpetri.opcua.sdk.client.nodes;
import java.util.concurrent.CompletableFuture;
import com.digitalpetri.opcua.sdk.client.OpcUaClient;
import com.digitalpetri.opcua.sdk.client.api.nodes.AddressSpace;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaDataTypeNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaMethodNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaObjectNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaObjectTypeNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaReferenceTypeNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaVariableNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaVariableTypeNode;
import com.digitalpetri.opcua.sdk.client.api.nodes.attached.UaViewNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedDataTypeNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedMethodNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedObjectNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedObjectTypeNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedReferenceTypeNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedVariableNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedVariableTypeNode;
import com.digitalpetri.opcua.sdk.client.nodes.attached.AttachedViewNode;
import com.digitalpetri.opcua.stack.core.AttributeId;
import com.digitalpetri.opcua.stack.core.UaException;
import com.digitalpetri.opcua.stack.core.types.builtin.DataValue;
import com.digitalpetri.opcua.stack.core.types.builtin.NodeId;
import com.digitalpetri.opcua.stack.core.types.builtin.QualifiedName;
import com.digitalpetri.opcua.stack.core.types.builtin.StatusCode;
import com.digitalpetri.opcua.stack.core.types.enumerated.NodeClass;
import com.digitalpetri.opcua.stack.core.types.enumerated.TimestampsToReturn;
import com.digitalpetri.opcua.stack.core.types.structured.ReadResponse;
import com.digitalpetri.opcua.stack.core.types.structured.ReadValueId;
import static com.google.common.collect.Lists.newArrayList;
public class DefaultAddressSpace implements AddressSpace {
private final OpcUaClient client;
public DefaultAddressSpace(OpcUaClient client) {
this.client = client;
}
@Override
public CompletableFuture<UaNode> getNode(NodeId nodeId) {
ReadValueId readValueId = new ReadValueId(
nodeId, AttributeId.NodeClass.uid(), null, QualifiedName.NULL_VALUE);
CompletableFuture<ReadResponse> future =
client.read(0.0, TimestampsToReturn.Neither, newArrayList(readValueId));
return future.thenCompose(response -> {
DataValue value = response.getResults()[0];
NodeClass nodeClass = (NodeClass) value.getValue().getValue();
if (nodeClass != null) {
client.getNodeCache().putAttribute(nodeId, AttributeId.NodeClass, value);
return CompletableFuture.completedFuture(createNode(nodeId, nodeClass));
} else {
return failedFuture(new UaException(value.getStatusCode(), "NodeClass was null"));
}
});
}
@Override
public UaDataTypeNode getDataTypeNode(NodeId nodeId) {
return new AttachedDataTypeNode(client, nodeId);
}
@Override
public UaMethodNode getMethodNode(NodeId nodeId) {
return new AttachedMethodNode(client, nodeId);
}
@Override
public UaObjectNode getObjectNode(NodeId nodeId) {
return new AttachedObjectNode(client, nodeId);
}
@Override
public UaObjectTypeNode getObjectTypeNode(NodeId nodeId) {
return new AttachedObjectTypeNode(client, nodeId);
}
@Override
public UaReferenceTypeNode getReferenceTypeNode(NodeId nodeId) {
return new AttachedReferenceTypeNode(client, nodeId);
}
@Override
public UaVariableNode getVariableNode(NodeId nodeId) {
return new AttachedVariableNode(client, nodeId);
}
@Override
public UaVariableTypeNode getVariableTypeNode(NodeId nodeId) {
return new AttachedVariableTypeNode(client, nodeId);
}
@Override
public UaViewNode getViewNode(NodeId nodeId) {
return new AttachedViewNode(client, nodeId);
}
private UaNode createNode(NodeId nodeId, NodeClass nodeClass) {
switch (nodeClass) {
case DataType:
return new AttachedDataTypeNode(client, nodeId);
case Method:
return new AttachedMethodNode(client, nodeId);
case Object:
return new AttachedObjectNode(client, nodeId);
case ObjectType:
return new AttachedObjectTypeNode(client, nodeId);
case ReferenceType:
return new AttachedReferenceTypeNode(client, nodeId);
case Variable:
return new AttachedVariableNode(client, nodeId);
case VariableType:
return new AttachedVariableTypeNode(client, nodeId);
case View:
return new AttachedViewNode(client, nodeId);
default:
throw new IllegalStateException("unhandled NodeClass: " + nodeClass);
}
}
private static <T> CompletableFuture<T> failedFuture(StatusCode statusCode) {
return failedFuture(new UaException(statusCode));
}
private static <T> CompletableFuture<T> failedFuture(UaException exception) {
CompletableFuture<T> f = new CompletableFuture<>();
f.completeExceptionally(exception);
return f;
}
}