github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekaerr/class.go (about)

     1  // Copyright © 2020-2021. All rights reserved.
     2  // Author: Ilya Stroy.
     3  // Contacts: iyuryevich@pm.me, https://github.com/qioalice
     4  // License: https://opensource.org/licenses/MIT
     5  
     6  package ekaerr
     7  
     8  type (
     9  	// Class is a special type that represents Error's abstract class
    10  	// and provides a mechanism of error classifying.
    11  	//
    12  	// Using Class's object you can instantiate an *Error object
    13  	// using New() or Wrap() methods. See them for more info.
    14  	//
    15  	// DO NOT INSTANTIATE Class OBJECTS MANUALLY! THEY WILL NOT BE INITIALIZED
    16  	// PROPERLY AND WILL BE CONSIDERED BROKEN. THAT CLASS IS NOT VALID.
    17  	// YOU CAN NOT CREATE ERROR OBJECTS USING INVALID CLASS.
    18  	// YOU CAN NOT CREATE ANOTHER DERIVED CLASSES USING INVALID CLASS AS BASE.
    19  	//
    20  	// A Class can not exist w/o a Namespace. Ekaerr provides you builtin classes
    21  	// you may use and, typically, that covers ~90% all error classifying models.
    22  	// But if you need your own classes or even subclasses (yes, you can derive them)
    23  	// you may:
    24  	//
    25  	// - Create your own Class.
    26  	//   Use <Namespace>.NewClass(...) method.
    27  	//   You can use builtin "Common" namespace (allowed by CommonNamespace variable)
    28  	//   or create your own Namespace at first and then create a Class that you want.
    29  	//
    30  	// - Create a new class but derive them from another.
    31  	//   Use <Class>.NewSubClass(...) method.
    32  	//   You can use builtin classes (see them at the "class_builtin.go" file)
    33  	//   or crate your own Class (see above how) and derive from them.
    34  	//
    35  	// You also need to know that there is a special Class - an 'invalidClass'.
    36  	// This is a special class that you may get if you instantiate Class object
    37  	// manually like "new(Class)" or "var c Class". That class IS NOT VALID.
    38  	// YOU MUST NOT USE INVALID CLASS!
    39  	// But you may get an invalid class also if you will call "(*Error)(nil).Class()".
    40  	// So, you can check whether your class is valid using IsValid() method.
    41  	//
    42  	// Class is a very lightweight datatype and all Class's methods
    43  	// (and function that takes Class as argument) uses Class's objects by value.
    44  	// It means there is no reason to use Class's object by reference in your code.
    45  	Class struct {
    46  
    47  		// id is an unique per Class its ID.
    48  		// If it's == _ERR_INVALID_CLASS_ID, the Class is considered broken
    49  		// (has been instantiated manually instead of using Class constructors).
    50  		id ClassID
    51  
    52  		// parentID is an ID of some Class that is base Class for this Class.
    53  		// (it means that this Class has been created by Class.NewSubClass()).
    54  		parentID ClassID
    55  
    56  		// namespaceID is an ID of some Namespace this Class belongs to.
    57  		// (it means that this Class has been created by Namespace.NewClass() or
    58  		// derived from the Class that was created that way).
    59  		namespaceID NamespaceID
    60  
    61  		// name is this Class's name specified by user at the creation.
    62  		// It's just a class's name as is, nothing more.
    63  		name string
    64  
    65  		// fullName is this Class's name but with base Classes and Namespaces
    66  		// chaining. E.g: "<Namespace>.<BaseClass1>.<BaseClass2>. ... .<ThisClass>".
    67  		//
    68  		// WARNING!
    69  		// READ THIS FIELD ONLY OF OBJECTS YOU OBTAIN FROM THE CLASS'S POOL!
    70  		fullName string
    71  	}
    72  )
    73  
    74  // New is an Error's constructor. Specify what happen by 'message' and key-value
    75  // paired arguments 'args' and that is! A new *Error object is returned.
    76  // Arguments adding works the same as (*Error).AddFields() do.
    77  //
    78  // Requirements:
    79  // c must be valid Class object. Otherwise nil Error is returned.
    80  func (c Class) New(message string, args ...any) *Error {
    81  	if !isValidClassID(c.id) {
    82  		return nil
    83  	}
    84  	return newError(false, c.id, c.namespaceID, nil, message, args)
    85  }
    86  
    87  // LightNew is the same as just New() but creates a lightweight Error instead.
    88  // Read more what lightweight error is in Error's doc.
    89  func (c Class) LightNew(message string, args ...any) *Error {
    90  	if !isValidClassID(c.id) {
    91  		return nil
    92  	}
    93  	return newError(true, c.id, c.namespaceID, nil, message, args)
    94  }
    95  
    96  // Wrap is an Error's constructor. Specify what legacy Golang error you need
    97  // to wrap using 'err', what happen by 'message' and key-value paired arguments 'args'
    98  // and that is! A new *Error object is returned.
    99  // Arguments adding works the same as (*Error).AddFields() do.
   100  //
   101  // Requirements:
   102  // c must be valid Class object. Otherwise nil Error is returned.
   103  // 'err' != nil. Otherwise nil Error is returned.
   104  func (c Class) Wrap(err error, message string, args ...any) *Error {
   105  	if !isValidClassID(c.id) || err == nil {
   106  		return nil
   107  	}
   108  	return newError(false, c.id, c.namespaceID, err, message, args)
   109  }
   110  
   111  // LightWrap is the same as just Wrap() but creates a lightweight Error instead.
   112  // Read more what lightweight error is in Error's doc.
   113  func (c Class) LightWrap(err error, message string, args ...any) *Error {
   114  	if !isValidClassID(c.id) || err == nil {
   115  		return nil
   116  	}
   117  	return newError(true, c.id, c.namespaceID, err, message, args)
   118  }
   119  
   120  // IsValid reports whether c is valid Class object or not.
   121  //
   122  // It returns false if c has not been initialized properly (instantiated manually
   123  // instead of Class's or Namespace's constructors calling or obtaining from the
   124  // Error's Class() method).
   125  func (c Class) IsValid() bool {
   126  	return isValidClassID(c.id)
   127  }
   128  
   129  // ParentClass returns a copy of Class object that has been used as a base class
   130  // for the current's one or a special 'invalidClass' if this Class has been
   131  // created directly from the namespace not as a subclass.
   132  func (c Class) ParentClass() Class {
   133  	if !c.IsValid() || !isValidClassID(c.parentID) {
   134  		return invalidClass
   135  	}
   136  	return classByID(c.parentID, true)
   137  }
   138  
   139  // Name returns a current Class's name that was used at the Class creation.
   140  // If you want to get a full name (without Namespace's and Base classes' use
   141  // c.FullName() instead).
   142  func (c Class) Name() string {
   143  	if !c.IsValid() {
   144  		return ""
   145  	}
   146  	return c.name
   147  }
   148  
   149  // FullName returns a current Class's full name:
   150  // a Class's name but with base Classes and Namespaces chaining.
   151  // E.g: "<Namespace>.<BaseClass1>.<BaseClass2>. ... .<ThisClass>".
   152  func (c Class) FullName() string {
   153  	if !c.IsValid() {
   154  		return ""
   155  	}
   156  	return classByID(c.id, true).fullName
   157  }
   158  
   159  // NewSubClass is a Class's constructor. Specify the derived Class's name 'name'
   160  // and that is! A new Class will be created and its copy is returned
   161  // (created class will belongs to the same Namespace as based one).
   162  //
   163  // Warnings:
   164  // A two classes with the same names is the two DIFFERENT classes!
   165  //
   166  // Requirements:
   167  // c must be valid Class object. Otherwise 'invalidClass' is returned.
   168  func (c Class) NewSubClass(subClassName string) Class {
   169  	if !isValidClassID(c.id) {
   170  		return invalidClass
   171  	}
   172  	fullName := classByID(c.id, true).fullName + "." + subClassName
   173  	return newClass(c.id, c.namespaceID, subClassName, fullName)
   174  }