private Tag createTag(ExpressionNode node) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);
    List<String> labels = new ArrayList<>();
    List<String> notLabels = new ArrayList<>();
    extractLabels(node, labels, notLabels);
    Collections.sort(labels);
    Collections.sort(notLabels);
    // We will write the NOT labels 1st followed by normal labels
    // Each of the label we will write with label length (as short 1st) followed
    // by the label bytes.
    // For a NOT node we will write the label length as -ve.
    for (String label : notLabels) {
      byte[] bLabel = Bytes.toBytes(label);
      short length = (short) bLabel.length;
      length = (short) (-1 * length);
      dos.writeShort(length);
      dos.write(bLabel);
    }
    for (String label : labels) {
      byte[] bLabel = Bytes.toBytes(label);
      dos.writeShort(bLabel.length);
      dos.write(bLabel);
    }
    return new ArrayBackedTag(VISIBILITY_TAG_TYPE, baos.toByteArray());
  }
This is a VisibilityLabelService where labels in Mutation's visibility expression will be
persisted as Strings itself rather than ordinals in 'labels' table. Also there is no need to add
labels to the system, prior to using them in Mutations/Authorizations.
hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java