Class PlainData

java.lang.Object
com.ultikits.ultitools.config.document.PlainData

@Internal public final class PlainData extends Object
The plain-data boundary of the config storage layer.

Plain data is exactly: null, String, Boolean, Integer, Long, BigInteger, Double, a List of plain data, and a Map whose keys are Strings and whose values are plain data. Nothing else may reach a config file: a value outside this set is refused before any YAML node is built, so no Java-class tag can ever be written.

This class also defines when two plain values are "the same value" for the purpose of leaving a file's text untouched: integral numbers compare by numeric value whatever their box type (Integer 1 equals Long 1), doubles compare with Double.equals(Object) (so 1.50 read from a file equals 1.5), maps compare entry by entry regardless of order, and lists element by element. A value read from a file that lies outside plain data - a YAML !!binary read as a byte[], a !!pairs or !!omap pair read as an Object[], a !!set read as a Set - compares by content, never by identity: copy(Object) hands out a fresh copy of each of them on every read, so two copies of an unchanged value must compare equal. Binaries compare byte by byte, arrays element by element, and two sets are equal when they have the same size and every member of each has an equal member in the other; a value whose content differs compares unequal.

Since:
6.3.0
  • Constructor Details

    • PlainData

      private PlainData()
  • Method Details

    • isPlain

      public static boolean isPlain(Object value)
      Returns whether value is plain data, recursively.
      Parameters:
      value - the value to test
      Returns:
      true when every node of value is plain data
    • requirePlain

      public static void requirePlain(List<String> path, Object value)
      Refuses a value that is not plain data.
      Parameters:
      path - the key path the value is about to be stored at, used in the message
      value - the value to check
      Throws:
      IllegalArgumentException - naming the key path of the first offending node and its class
    • describePath

      public static String describePath(List<String> path)
      Formats a key path for messages: the keys in brackets, separated by a comma, so a key that itself contains a . stays readable ([emojis, o.O]).
      Parameters:
      path - the key path
      Returns:
      the formatted path
    • plainEquals

      public static boolean plainEquals(Object a, Object b)
      Compares two plain values as values, not as text. See the class description for the rules.
      Parameters:
      a - one plain value
      b - another plain value
      Returns:
      whether writing b over a would change nothing a reader can observe
    • arrayEquals

      private static boolean arrayEquals(Object[] left, Object[] right)
    • everyMemberMatched

      private static boolean everyMemberMatched(Set<?> members, Set<?> candidates)
      Whether every member of members has a plainEquals(java.lang.Object, java.lang.Object)-equal member in candidates. A set read from a file may hold a binary or another value whose own equals is identity, so membership is matched by value rather than by Set.contains(Object).
    • copy

      public static Object copy(Object value)
      Deep-copies plain values and every mutable value SafeConstructor can return: maps (including keys), lists, sets, pair arrays, dates and binary arrays. Copies never share mutable data with their source. Shared aliases are independently copied, and recursive containers are refused. Other safe YAML leaves are immutable.
      Parameters:
      value - a plain value (or a value read from a file, which may hold non-plain leaves such as a java.util.Date for a YAML timestamp)
      Returns:
      the copy
    • copy

      private static Object copy(Object value, Set<Object> visiting)
    • depth

      static int depth(Object value)
      The number of nested collections in a plain value: 0 for a scalar, 1 for a flat list or map.
      Parameters:
      value - a plain value (checked by requirePlain(java.util.List<java.lang.String>, java.lang.Object) first, so it has no cycle)
      Returns:
      the nesting depth
    • isIntegral

      static boolean isIntegral(Object value)
    • toBigInteger

      private static BigInteger toBigInteger(Object value)
    • newVisited

      private static Set<Object> newVisited()
    • firstViolation

      private static String firstViolation(List<String> path, Object value, Set<Object> visiting)
    • containerViolation

      private static String containerViolation(List<String> path, Object value, Set<Object> visiting)