code: /*
   * Copyright (c) 2019 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.stack.core;
  
  import java.util.Optional;
  
  import com.google.common.collect.ImmutableSet;
  import com.google.common.collect.Sets;
  import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
  
  import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
  
  public enum AttributeId {
  
      NodeId(1),
      NodeClass(2),
      BrowseName(3),
      DisplayName(4),
      Description(5),
      WriteMask(6),
      UserWriteMask(7),
      IsAbstract(8),
      Symmetric(9),
      InverseName(10),
      ContainsNoLoops(11),
      EventNotifier(12),
      Value(13),
      DataType(14),
      ValueRank(15),
      ArrayDimensions(16),
      AccessLevel(17),
      UserAccessLevel(18),
      MinimumSamplingInterval(19),
      Historizing(20),
      Executable(21),
      UserExecutable(22);
  
      public static final ImmutableSet<AttributeId> BASE_ATTRIBUTES = ImmutableSet.copyOf(
          ImmutableSet.of(
              NodeId, NodeClass, BrowseName, DisplayName, Description, WriteMask, UserWriteMask)
      );
  
      public static final ImmutableSet<AttributeId> DATA_TYPE_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(IsAbstract))
      );
  
      public static final ImmutableSet<AttributeId> METHOD_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(Executable, UserExecutable))
      );
  
      public static final ImmutableSet<AttributeId> OBJECT_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(EventNotifier))
      );
  
      public static final ImmutableSet<AttributeId> OBJECT_TYPE_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(IsAbstract))
      );
  
      public static final ImmutableSet<AttributeId> REFERENCE_TYPE_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(IsAbstract, Symmetric, InverseName))
      );
  
      public static final ImmutableSet<AttributeId> VARIABLE_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(Value, DataType, ValueRank, ArrayDimensions,
                  AccessLevel, UserAccessLevel, MinimumSamplingInterval, Historizing))
      );
  
      public static final ImmutableSet<AttributeId> VARIABLE_TYPE_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(Value, DataType, ValueRank, ArrayDimensions, IsAbstract))
      );
  
      public static final ImmutableSet<AttributeId> VIEW_ATTRIBUTES = ImmutableSet.copyOf(
          Sets.union(
              BASE_ATTRIBUTES,
              ImmutableSet.of(ContainsNoLoops, EventNotifier))
      );
  
      private final int id;
  
      AttributeId(int id) {
          this.id = id;
      }
  
      public final int id() {
          return id;
      }
  
      public final UInteger uid() {
          return uint(id);
      }
  
      public static Optional<AttributeId> from(UInteger attributeId) {
          return from(attributeId.intValue());
      }
  
      public static Optional<AttributeId> from(int attributeId) {
          if (attributeId > 0 && attributeId <= values().length) {
              return Optional.of(values()[attributeId - 1]);
          } else {
              return Optional.empty();
          }
      }
  
      public boolean isEqual(UInteger attributeId) {
          return attributeId != null && isEqual(attributeId.intValue());
      }
  
      public boolean isEqual(int attributeId) {
          return id == attributeId;
      }
  
      /**
       * @param attributeId the id to test for validity.
       * @return {@code true} if {@code attributeId} is valid.
       */
      public static boolean isValid(UInteger attributeId) {
          return from(attributeId).isPresent();
      }
  
      /**
       * @param attributeId the id to test for validity.
       * @return {@code true} if {@code attributeId} is valid.
       */
      public static boolean isValid(int attributeId) {
          return from(attributeId).isPresent();
      }
  
      /**
       * Get the set of valid attributes for a {@link org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass}.
       *
       * @param nodeClass the {@link org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass}.
       * @return the set of valid attributes for {@code nodeClass}.
       */
      public static ImmutableSet<AttributeId> getAttributes(
          org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass nodeClass) {
  
          //@formatter:off
          switch (nodeClass) {
              case Object:        return OBJECT_ATTRIBUTES;
              case Variable:      return VARIABLE_ATTRIBUTES;
              case Method:        return METHOD_ATTRIBUTES;
              case ObjectType:    return OBJECT_TYPE_ATTRIBUTES;
              case VariableType:  return VARIABLE_TYPE_ATTRIBUTES;
              case ReferenceType: return REFERENCE_TYPE_ATTRIBUTES;
              case DataType:      return DATA_TYPE_ATTRIBUTES;
              case View:          return VIEW_ATTRIBUTES;
              default:            return ImmutableSet.of();
          }
          //@formatter:on
      }
  
  }
  