项目作者: makiftutuncu

项目描述 :
An easy-to-use library written in Scala for providing immutable, lightweight, extensible way to represent errors in your project
高级语言: Scala
项目地址: git://github.com/makiftutuncu/Errors.git
创建时间: 2016-01-21T10:56:53Z
项目社区:https://github.com/makiftutuncu/Errors

开源协议:MIT License

下载


Errors Build Status

Errors is an easy-to-use library written in Scala for providing immutable, lightweight, extensible way to represent errors in your project.

How to Include in Your Project

Add following to your build.sbt if you are using SBT

  1. libraryDependencies += "com.github.mehmetakiftutuncu" %% "errors" % "1.2"

Or add following to your pom.xml if you are using Maven (use errors_2.11 for Scala 2.11)

  1. <dependency>
  2. <groupId>com.github.mehmetakiftutuncu</groupId>
  3. <artifactId>errors_2.12</artifactId>
  4. <version>1.2</version>
  5. </dependency>

Or add following to your build.gradle if you are using Gradle (use errors_2.11 for Scala 2.11)

  1. compile 'com.github.mehmetakiftutuncu:errors_2.12:1.2'

Examples

Since Errors is immutable, any kind of update operation (i.e. any method returning Errors or any error extending ErrorBase) return a new copy with new data.

Creating an Errors Instance

You can easily create both empty and non-empty Errors instances. Just use empty or apply methods.

Example

  1. // Empty errors
  2. val errors1 = Errors.empty
  3. val errors2 = Errors()
  4. // Non-empty errors already containing given errors
  5. val errors3 = Errors(CommonError.timeout, SimpleError.authorization)

Creating Error Objects

You can create error objects to add to or remove from or even perform checks on an Errors instance. There are 2 types of errors already defined; CommonError and SimpleError. However, you can use any type of errors as long as they extend from ErrorBase.

Example

  1. // You can provide all info.
  2. val error1 = CommonError(name = "invalidData", reason = "Value must be a positive integer.", data = "-5")
  3. // You can provide some info and update reason and data of a CommonError later.
  4. val error2 = CommonError("timeout").reason("Network might be down.").data("30 seconds")
  5. // There are even some predefined helper methods to give you appropriate instances easily.
  6. val error3 = CommonError.authorization.reason("Username or password is invalid!")
  7. // Literally "simple", just an error name
  8. val error4 = SimpleError("database")
  9. val error5 = SimpleError.timeout

Adding Errors

You can add a single error, multiple errors or the errors in an existing Errors instance to an Errors instance.

Example

  1. val errors1 = Errors.empty
  2. val errors2 = Errors(SimpleError.authorization)
  3. val errors3 = errors1 + CommonError.timeout
  4. val errors4 = errors1.addAll(CommonError.timeout, SimpleError.authorization)
  5. val errors5 = errors3 ++ Errors(SimpleError.authorization)

Removing Errors

You can remove a single error, multiple errors or the errors in an existing Errors instance from an Errors instance.

Example

  1. val errors1 = Errors(CommonError.timeout, SimpleError.authorization)
  2. val errors2 = errors1 - CommonError.timeout
  3. // Database error will be ignored here since it does not exist in errors1 anyway.
  4. val errors3 = errors1.removeAll(SimpleError.authorization, CommonError.database)
  5. val errors4 = errors1 -- Errors(SimpleError.authorization)

Checking Errors Instance for Errors

You can perform several checks on an Errors instance.

Example

  1. val errors1 = Errors(CommonError.timeout, SimpleError.authorization)
  2. val errors2 = Errors.empty
  3. errors1.isEmpty // false
  4. errors2.isEmpty // true
  5. errors1.nonEmpty // true
  6. errors2.nonEmpty // false
  7. errors1.hasErrors // true
  8. errors2.hasErrors // false
  9. errors1.size // 2
  10. errors2.size // 0
  11. errors1.numberOfErrors // 2
  12. errors2.numberOfErrors // 0
  13. errors1.contains(CommonError.timeout) // true
  14. errors1.contains(CommonError.database) // false
  15. errors2.contains(CommonError.timeout) // false
  16. // true
  17. errors1.exists {
  18. case CommonError(name, _, _) if name == "timeout" => true
  19. case _ => false
  20. }

Using Maybe

There is a type alias for Either[Errors, V] defined as Maybe. It can be useful for error handling while accessing a value.

Example

  1. // Method will either return some Errors or an Int
  2. def divide(n1: Int, n2: Int): Maybe[Int] = {
  3. if (n2 == 0) {
  4. // Create maybe with Errors
  5. Maybe(Errors(CommonError.invalidData.reason("Cannot divide by 0!")))
  6. } else {
  7. // Create Maybe with a value
  8. Maybe(n1 / n2)
  9. }
  10. }
  11. val result1: Maybe[Int] = divide(3, 0)
  12. val result2: Maybe[Int] = divide(4, 2)
  13. result1.maybeErrors // Returns Some(Errors(CommonError.invalidData.reason("Cannot divide by 0!")))
  14. result2.maybeErrors // Returns None
  15. result1.maybeValue // Returns None
  16. result2.maybeValue // Returns Some(2)
  17. result1.hasErrors // Returns true
  18. result2.hasErrors // Returns false
  19. result1.hasValue // Returns false
  20. result2.hasValue // Returns true
  21. // Methods below throw exceptions unless their criteria are met. So, use them with caution!
  22. result1.errors // Returns Errors(CommonError.invalidData.reason("Cannot divide by 0!"))
  23. result2.errors // Throws HasNoErrorsException!
  24. result1.value // Throws HasNoValueException!
  25. result2.value // Returns 2

Representing Errors

As default implementation, Errors will use JsonStringErrorRepresenter and give a Json formatted string representation of all errors as an array. You may also provide your own error representer extending ErrorRepresenter so you can represent your errors in any way you want.

Example

  1. val error1 = CommonError(name = "foo")
  2. val error2 = CommonError(name = "foo", reason = "bar")
  3. val error3 = CommonError(name = "foo", data = "bar")
  4. val error4 = CommonError(name = "foo", reason = "bar", data = "baz")
  5. val error5 = SimpleError(name = "goo")
  6. val errors = Errors(error1, error2, error3, error4, error5)
  7. // Output will be
  8. // [{"name":"foo"},{"name":"foo","reason":"bar"},{"name":"foo","data":"bar"},{"name":"foo","reason":"bar","data":"baz"},{"name":"goo"}]
  9. errors.represent(includeWhen = false)
  10. errors.toString
  11. // Output will be
  12. // [{"name":"foo","when":1454271634493},{"name":"foo","reason":"bar","when":1454271634557},{"name":"foo","data":"bar","when":1454271634621},{"name":"foo","reason":"bar","data":"baz","when":1454271634680},{"name":"goo","when":1454271634737}]
  13. errors.represent(includeWhen = true)
  14. // Custom error representer giving true unless Errors is empty, for demonstration purposes
  15. val customBooleanRepresenter = new ErrorRepresenter[Boolean] {
  16. override def represent(error: ErrorBase, includeWhen: Boolean): Boolean = true
  17. override def represent(errors: List[ErrorBase], includeWhen: Boolean): Boolean = if (errors.isEmpty) false else true
  18. override def asString(representation: Boolean): String = representation.toString
  19. }
  20. Errors.empty.represent(customBooleanRepresenter, includeWhen = false) // Returns false
  21. errors.represent(customBooleanRepresenter, includeWhen = true) // Returns true

You can see a real error representer example in JsonErrorRepresenter.

Contributing

I’d appreciate if you comment, file an issue, send pull requests. Please feel free to and do contribute.

Contributors

  • @forthy - Cross compilation for Scala 2.11 and 2.12

License

The MIT License (MIT), Copyright (c) 2016 Mehmet Akif Tütüncü

See LICENSE.md for details.