| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF 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.apache.camel.component.milo.call; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Optional; |
| import java.util.concurrent.CompletableFuture; |
| |
| import org.eclipse.milo.opcua.sdk.core.Reference; |
| import org.eclipse.milo.opcua.sdk.server.OpcUaServer; |
| import org.eclipse.milo.opcua.sdk.server.api.AccessContext; |
| import org.eclipse.milo.opcua.sdk.server.api.DataItem; |
| import org.eclipse.milo.opcua.sdk.server.api.MethodInvocationHandler; |
| import org.eclipse.milo.opcua.sdk.server.api.MonitoredItem; |
| import org.eclipse.milo.opcua.sdk.server.api.Namespace; |
| import org.eclipse.milo.opcua.sdk.server.api.ServerNodeMap; |
| import org.eclipse.milo.opcua.sdk.server.model.nodes.objects.FolderNode; |
| import org.eclipse.milo.opcua.sdk.server.nodes.AttributeContext; |
| import org.eclipse.milo.opcua.sdk.server.nodes.ServerNode; |
| import org.eclipse.milo.opcua.sdk.server.nodes.UaFolderNode; |
| import org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode; |
| import org.eclipse.milo.opcua.sdk.server.util.SubscriptionModel; |
| import org.eclipse.milo.opcua.stack.core.Identifiers; |
| import org.eclipse.milo.opcua.stack.core.StatusCodes; |
| import org.eclipse.milo.opcua.stack.core.UaException; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; |
| import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort; |
| import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn; |
| import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId; |
| import org.eclipse.milo.opcua.stack.core.types.structured.WriteValue; |
| |
| import static java.util.stream.Collectors.toList; |
| |
| public class MockNamespace implements Namespace { |
| |
| public static final int FOLDER_ID = 1; |
| |
| public static final String URI = "urn:mock:namespace"; |
| |
| private final UShort index; |
| |
| private final ServerNodeMap nodeMap; |
| private final SubscriptionModel subscriptionModel; |
| |
| public MockNamespace(final UShort index, final OpcUaServer server, List<UaMethodNode> methods) { |
| this.index = index; |
| this.nodeMap = server.getNodeMap(); |
| this.subscriptionModel = new SubscriptionModel(server, this); |
| |
| registerItems(methods); |
| } |
| |
| private void registerItems(List<UaMethodNode> methods) { |
| |
| // create a folder |
| |
| final UaFolderNode folder = new UaFolderNode(this.nodeMap, new NodeId(this.index, FOLDER_ID), new QualifiedName(this.index, "FooBarFolder"), |
| LocalizedText.english("Foo Bar Folder")); |
| |
| // add our folder to the objects folder |
| |
| this.nodeMap.getNode(Identifiers.ObjectsFolder).ifPresent(node -> { |
| ((FolderNode)node).addComponent(folder); |
| }); |
| |
| // add method calls |
| |
| methods.forEach(folder::addComponent); |
| } |
| |
| // default method implementations follow |
| |
| @Override |
| public void read(final ReadContext context, final Double maxAge, final TimestampsToReturn timestamps, final List<ReadValueId> readValueIds) { |
| |
| final List<DataValue> results = new ArrayList<>(readValueIds.size()); |
| |
| for (final ReadValueId id : readValueIds) { |
| final ServerNode node = this.nodeMap.get(id.getNodeId()); |
| |
| final DataValue value = node != null ? node.readAttribute(new AttributeContext(context), id.getAttributeId()) : new DataValue(StatusCodes.Bad_NodeIdUnknown); |
| |
| results.add(value); |
| } |
| |
| // report back with result |
| |
| context.complete(results); |
| } |
| |
| @Override |
| public void write(final WriteContext context, final List<WriteValue> writeValues) { |
| |
| final List<StatusCode> results = writeValues.stream().map(value -> { |
| if (this.nodeMap.containsKey(value.getNodeId())) { |
| return new StatusCode(StatusCodes.Bad_NotWritable); |
| } else { |
| return new StatusCode(StatusCodes.Bad_NodeIdUnknown); |
| } |
| }).collect(toList()); |
| |
| // report back with result |
| |
| context.complete(results); |
| } |
| |
| @Override |
| public CompletableFuture<List<Reference>> browse(final AccessContext context, final NodeId nodeId) { |
| final ServerNode node = this.nodeMap.get(nodeId); |
| |
| if (node != null) { |
| return CompletableFuture.completedFuture(node.getReferences()); |
| } else { |
| final CompletableFuture<List<Reference>> f = new CompletableFuture<>(); |
| f.completeExceptionally(new UaException(StatusCodes.Bad_NodeIdUnknown)); |
| return f; |
| } |
| } |
| |
| @Override |
| public Optional<MethodInvocationHandler> getInvocationHandler(final NodeId methodId) { |
| return Optional.ofNullable(this.nodeMap.get(methodId)).filter(n -> n instanceof UaMethodNode).flatMap(n -> { |
| final UaMethodNode m = (UaMethodNode)n; |
| return m.getInvocationHandler(); |
| }); |
| } |
| |
| @Override |
| public void onDataItemsCreated(final List<DataItem> dataItems) { |
| this.subscriptionModel.onDataItemsCreated(dataItems); |
| } |
| |
| @Override |
| public void onDataItemsModified(final List<DataItem> dataItems) { |
| this.subscriptionModel.onDataItemsModified(dataItems); |
| } |
| |
| @Override |
| public void onDataItemsDeleted(final List<DataItem> dataItems) { |
| this.subscriptionModel.onDataItemsDeleted(dataItems); |
| } |
| |
| @Override |
| public void onMonitoringModeChanged(final List<MonitoredItem> monitoredItems) { |
| this.subscriptionModel.onMonitoringModeChanged(monitoredItems); |
| } |
| |
| @Override |
| public UShort getNamespaceIndex() { |
| return this.index; |
| } |
| |
| @Override |
| public String getNamespaceUri() { |
| return URI; |
| } |
| } |