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.sdk.server.events.conversions;
  
  import org.eclipse.milo.opcua.stack.core.BuiltinDataType;
  import org.jetbrains.annotations.NotNull;
  import org.jetbrains.annotations.Nullable;
  
  public class ImplicitConversions {
  
      @Nullable
      public static Object convert(@NotNull Object sourceValue, @NotNull BuiltinDataType targetType) {
          BuiltinDataType sourceType = BuiltinDataType.fromBackingClass(sourceValue.getClass());
  
          if (sourceType == null) {
              return null;
          }
  
          if (!sourceType.getBackingClass().isAssignableFrom(sourceValue.getClass())) {
              return null;
          }
  
          return convert(sourceValue, sourceType, targetType);
      }
  
      private static Object convert(
          @NotNull Object sourceValue,
          BuiltinDataType sourceType,
          BuiltinDataType targetType) {
  
          switch (sourceType) {
              case Boolean:
                  return BooleanConversions
                      .convert(sourceValue, targetType, true);
              case Byte:
                  return ByteConversions
                      .convert(sourceValue, targetType, true);
  
              case ByteString:
                  return ByteStringConversions
                      .convert(sourceValue, targetType, true);
  
              case DateTime:
                  return DateTimeConversions
                      .convert(sourceValue, targetType, true);
  
              case Double:
                  return DoubleConversions
                      .convert(sourceValue, targetType, true);
  
              case ExpandedNodeId:
                  return ExpandedNodeIdConversions
                      .convert(sourceValue, targetType, true);
  
              case Float:
                  return FloatConversions
                      .convert(sourceValue, targetType, true);
              case Guid:
                  return GuidConversions
                      .convert(sourceValue, targetType, true);
  
              case Int16:
                  return Int16Conversions
                      .convert(sourceValue, targetType, true);
  
              case Int32:
                  return Int32Conversions
                      .convert(sourceValue, targetType, true);
  
              case Int64:
                  return Int64Conversions
                      .convert(sourceValue, targetType, true);
  
              case NodeId:
                  return NodeIdConversions
                      .convert(sourceValue, targetType, true);
  
              case SByte:
                  return SByteConversions
                      .convert(sourceValue, targetType, true);
  
              case StatusCode:
                  return StatusCodeConversions
                      .convert(sourceValue, targetType, true);
  
              case String:
                  return StringConversions
                      .convert(sourceValue, targetType, true);
  
              case LocalizedText:
                  return LocalizedTextConversions
                      .convert(sourceValue, targetType, true);
  
              case QualifiedName:
                  return QualifiedNameConversions
                      .convert(sourceValue, targetType, true);
  
              case UInt16:
                  return UInt16Conversions
                      .convert(sourceValue, targetType, true);
  
              case UInt32:
                  return UInt32Conversions
                      .convert(sourceValue, targetType, true);
  
              case UInt64:
                  return UInt64Conversions
                      .convert(sourceValue, targetType, true);
  
              default:
                  return null;
          }
      }
  
      public static int getPrecedence(@NotNull BuiltinDataType dataType) {
          //@formatter:off
          switch (dataType) {
              case Double:            return 18;
              case Float:             return 17;
              case Int64:             return 16;
              case UInt64:            return 15;
              case Int32:             return 14;
              case UInt32:            return 13;
              case StatusCode:        return 12;
              case Int16:             return 11;
              case UInt16:            return 10;
              case SByte:             return 9;
              case Byte:              return 8;
              case Boolean:           return 7;
              case Guid:              return 6;
              case String:            return 5;
              case ExpandedNodeId:    return 4;
              case NodeId:            return 3;
              case LocalizedText:     return 2;
              case QualifiedName:     return 1;
              default:                return 0;
          }
          //@formatter:on
      }
  
  }
  