code: /*
   * Copyright (c) 2021 the Eclipse Milo Authors
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  
  package org.eclipse.milo.opcua.sdk.client;
  
  import java.util.EnumSet;
  import java.util.List;
  
  import org.eclipse.milo.opcua.sdk.client.AddressSpace.BrowseOptions;
  import org.eclipse.milo.opcua.sdk.client.model.nodes.objects.ServerTypeNode;
  import org.eclipse.milo.opcua.sdk.client.model.nodes.variables.ServerStatusTypeNode;
  import org.eclipse.milo.opcua.sdk.client.nodes.UaNode;
  import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
  import org.eclipse.milo.opcua.sdk.test.AbstractClientServerTest;
  import org.eclipse.milo.opcua.stack.core.BuiltinReferenceType;
  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.NodeId;
  import org.eclipse.milo.opcua.stack.core.types.enumerated.BrowseDirection;
  import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
  import org.junit.jupiter.api.Test;
  
  import static org.junit.jupiter.api.Assertions.assertEquals;
  import static org.junit.jupiter.api.Assertions.assertFalse;
  import static org.junit.jupiter.api.Assertions.assertNotNull;
  import static org.junit.jupiter.api.Assertions.assertSame;
  import static org.junit.jupiter.api.Assertions.assertThrows;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  public class AddressSpaceTest extends AbstractClientServerTest {
  
      @Test
      public void browse() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
  
          UaNode serverNode = addressSpace.getNode(Identifiers.Server);
          List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode);
  
          nodes.forEach(n -> {
              System.out.println(String.format("%s (%s) [%s]",
                  n.getBrowseName().toParseableString(),
                  n.getNodeId().toParseableString(),
                  n.getNodeClass()
              ));
  
              if (n instanceof UaVariableNode) {
                  System.out.println("\u2514\u2500 value = " +
                      ((UaVariableNode) n).getValue().getValue());
              }
          });
      }
  
      @Test
      public void browseWithBrowseDirection() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
  
          {
              UaNode serverNode = addressSpace.getNode(Identifiers.Server);
              BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
                  b ->
                      b.setBrowseDirection(BrowseDirection.Inverse)
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode, browseOptions);
  
              assertEquals(1, nodes.size());
              assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.ObjectsFolder)));
          }
  
          {
              UaNode objectsFolderNode = addressSpace.getNode(Identifiers.ObjectsFolder);
              BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
                  b ->
                      b.setBrowseDirection(BrowseDirection.Both)
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(objectsFolderNode, browseOptions);
  
              assertEquals(7, nodes.size());
              assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.RootFolder)));
              assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server)));
          }
      }
  
      @Test
      public void browseWithReferenceType() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
  
          UaNode serverNode = addressSpace.getNode(Identifiers.Server);
  
          BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
              b ->
                  b.setReferenceType(BuiltinReferenceType.HasProperty)
          );
  
          List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode, browseOptions);
  
          assertEquals(5, nodes.size());
          assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server_ServerArray)));
          assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server_NamespaceArray)));
          assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server_ServiceLevel)));
          assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server_Auditing)));
          assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server_EstimatedReturnTime)));
      }
  
      @Test
      public void browseWithNodeClassMask() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
          UaNode serverNode = addressSpace.getNode(Identifiers.Server);
  
          {
              BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Method))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode, browseOptions);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Method));
          }
  
          {
              BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Object))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode, browseOptions);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Object));
          }
  
          {
              BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Variable))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode, browseOptions);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Variable));
          }
      }
  
      @Test
      public void modifyBrowseOptions() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
          UaNode serverNode = addressSpace.getNode(Identifiers.Server);
  
          {
              addressSpace.modifyBrowseOptions(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Method))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Method));
          }
  
          {
              addressSpace.modifyBrowseOptions(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Object))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Object));
          }
  
          {
              addressSpace.modifyBrowseOptions(
                  b ->
                      b.setNodeClassMask(EnumSet.of(NodeClass.Variable))
              );
  
              List<? extends UaNode> nodes = addressSpace.browseNodes(serverNode);
  
              assertFalse(nodes.isEmpty());
              assertTrue(nodes.stream().allMatch(n -> n.getNodeClass() == NodeClass.Variable));
          }
      }
  
      @Test
      public void getNode() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
  
          UaNode serverNode = addressSpace.getNode(Identifiers.Server);
          assertNotNull(serverNode);
          assertTrue(serverNode instanceof ServerTypeNode);
  
          UaNode serverStatusNode = addressSpace.getNode(Identifiers.Server_ServerStatus);
          assertNotNull(serverStatusNode);
          assertTrue(serverStatusNode instanceof ServerStatusTypeNode);
      }
  
      @Test
      public void getObjectNode() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
          ServerTypeNode serverNode = (ServerTypeNode) addressSpace.getObjectNode(Identifiers.Server);
  
          assertNotNull(serverNode);
          assertEquals(Identifiers.Server, serverNode.getNodeId());
  
          // should be cached now, check instance equality
          assertSame(serverNode, addressSpace.getObjectNode(Identifiers.Server));
      }
  
      @Test
      public void getObjectNodeWithNonObject() {
          AddressSpace addressSpace = client.getAddressSpace();
  
          assertThrows(
              UaException.class,
              () -> addressSpace.getObjectNode(Identifiers.Server_ServerStatus)
          );
      }
  
      @Test
      public void getVariableNode() throws UaException {
          AddressSpace addressSpace = client.getAddressSpace();
          ServerStatusTypeNode serverNode = (ServerStatusTypeNode)
              addressSpace.getVariableNode(Identifiers.Server_ServerStatus);
  
          assertNotNull(serverNode);
          assertEquals(Identifiers.Server_ServerStatus, serverNode.getNodeId());
  
          // should be cached now, check instance equality
          assertSame(serverNode, addressSpace.getVariableNode(Identifiers.Server_ServerStatus));
      }
  
      @Test
      public void getVariableNodeWithNonVariable() {
          AddressSpace addressSpace = client.getAddressSpace();
  
          assertThrows(
              UaException.class,
              () -> addressSpace.getVariableNode(Identifiers.Server)
          );
      }
  
      @Test
      public void getNodeThatDoesNotExist() {
          UaException exception = assertThrows(
              UaException.class,
              () -> client.getAddressSpace().getNode(NodeId.parse("ns=2;s=DoesNotExist"))
          );
  
          assertEquals(StatusCodes.Bad_NodeIdUnknown, exception.getStatusCode().getValue());
      }
  
  }
  