+ return null;
+ }
+
+ /**
+ * Return a {@link String} that can be used to identify this object in DEBUG
+ * mode, i.e., a "toString" method that can identify the object's content
+ * but still be readable in a log.
+ *
+ * @param depth
+ * the depth into which to descend (0 = only this object, not its
+ * children)
+ *
+ * @return the debug {@link String}
+ */
+ public String getDebugInfo(int depth) {
+ StringBuilder builder = new StringBuilder();
+ getDebugInfo(builder, depth, 0);
+ return builder.toString();
+ }
+
+ /**
+ * Return the current ID of this object -- it is allowed to change over time
+ * (so, do not cache it).
+ *
+ * @return the current ID
+ */
+ abstract public String getId();
+
+ /**
+ * Get the state of the current object, children <b>not included</b>. It
+ * represents the full state information about this object, but do not check
+ * its children (see {@link BaseClass#getContentState()} for that). It may
+ * not contains spaces nor new lines.
+ *
+ * <p>
+ * Not that this state is <b>lossy</b>. You cannot retrieve the data from
+ * the state, it can only be used as an ID to check if thw data are
+ * identical.
+ * </p>
+ *
+ * @return a {@link String} representing the current state of this object,
+ * children not included
+ */
+ abstract public String getState();
+
+ /**
+ * Get the recursive state of the current object, i.e., its children
+ * included. It represents the full state information about this object's
+ * children.
+ *
+ * It is not hashed.
+ *
+ * @param builder
+ * the {@link StringBuilder} that will represent the current
+ * content state of this object, i.e., its children included
+ * @param self
+ * also include state information about the current object itself
+ * (as opposed to its children)
+ */
+ void buildContentStateRaw(StringBuilder builder, boolean self) {
+ Collections.sort(this.list, comparator);
+ if (self)
+ builder.append(getState());
+ for (E child : this) {
+ child.buildContentStateRaw(builder, true);
+ }
+ }
+
+ /**
+ * Populate a {@link StringBuilder} that can be used to identify this object
+ * in DEBUG mode, i.e., a "toString" method that can identify the object's
+ * content but still be readable in a log.
+ *
+ * @param depth
+ * the depth into which to descend (0 = only this object, not its
+ * children)
+ *
+ * @param tab
+ * the current tabulation increment
+ */
+ void getDebugInfo(StringBuilder builder, int depth, int tab) {
+ for (int i = 0; i < tab; i++)
+ builder.append(" ");
+ builder.append(getContentState(false) + " " + getId());
+
+ if (depth > 0)
+ builder.append(": [");
+
+ if (depth > 0) {
+ for (E child : this) {
+ builder.append("\n");
+ child.getDebugInfo(builder, depth - 1, tab + 1);
+ }
+ }
+ if (depth > 0) {
+ builder.append("\n");
+ for (int i = 0; i < tab; i++)
+ builder.append(" ");
+ builder.append("]");
+ }