text: # Copyright (c) 2020 DDN. All rights reserved.
  # Use of this source code is governed by a MIT-style
  # license that can be found in the LICENSE file.
  
  
  from chroma_core.models.storage_plugin import StorageResourceAttributeSerialized
  
  
  class BaseResourceAttribute(object):
      """Base class for declared attributes of BaseStorageResource.  This is
      to BaseStorageResource as models.fields.Field is to models.Model
  
      """
  
      # This is a hack to store the order in which attributes are declared so
      # that I can sort the BaseStorageResource attribute dict for presentation in the same order
      # as the plugin author declared the attributes.
      creation_counter = 0
  
      model_class = StorageResourceAttributeSerialized
  
      def __init__(self, optional=False, label=None, hidden=False, user_read_only=False, default=None):
          """
          :param optional: If this is True, the attribute may be left unassigned (i.e. null).  Otherwise,
              a non-null value must be provided for all instances.
          :param label: Human readable string for use in the user interface.  Use this if the programmatic
              attribute name in the resource declaration is not appropriate for presentation to the user.
          :param hidden: If this is True, this attribute will not be included as a column in the tabular view
              of storage resources.
          :param user_read_only: If this is True, this attribute can only be set internally by the plugin, not
              by the user.  For example, a controller might have some attributes entered by the user, and some
              read from the hardware: those read from the hardware would be marked `user_read_only`.  Attributes
              which are `user_read_only` must also be `optional`.
          :param default: If not None then this default value will be used in the case of a non-optional value
              missing. Generally used in the case of upgrades to supply previous records. default maybe callable
              or a fixed value.
          """
          self.optional = optional
          self.default = default
          self.label = label
          self.hidden = hidden
          self.user_read_only = user_read_only
  
          self.creation_counter = BaseResourceAttribute.creation_counter
          BaseResourceAttribute.creation_counter += 1
  
      def get_label(self, name):
          if self.label:
              return self.label
          else:
              words = name.split("_")
              return " ".join([words[0].title()] + words[1:])
  
      def validate(self, value):
          """Note: this validation is NOT intended to be used for catching cases
          in production, it does not provide hooks for user-friendly error messages
          etc.  Think of it more as an assert."""
          pass
  
      def human_readable(self, value):
          """Subclasses should format their value for human consumption, e.g.
             1024 => 1kB"""
          return value
  
      def encode(self, value):
          return value
  
      def decode(self, value):
          return value
  
      def encrypt(self, value):
          """The encryption function will be called by the manager server when processing user input (e.g.
          when a resource is added in the UI).  The obfuscated text will be seen by
          the plugin when the resource is retrieved.
  
          :param value: value to encrypt
          :return: encrypted value
  
          """
  
          return value
  
      def to_markup(self, value):
          from django.utils.html import conditional_escape
  
          return conditional_escape(value)
  
      def cast(self, value):
          """Cast a value to the correct type for the ResourceAttribute.
  
          Will throw an exception if the value cannot be cast. (in child classes)
  
          An example of usage is that when values come from the rest interface they may not be of the correct type.
          :param value: Value to be cast.
          """
  
          return value
  