+ /**
+ * Check if the given instance and this one represent the same objects (they
+ * may have different states).
+ *
+ * @param other
+ * the other instance
+ *
+ * @return TRUE if they represent the same object
+ */
+ public boolean isSame(BaseClass<E> other) {
+ if (other == null)
+ return false;
+
+ if (!getClass().equals(other.getClass()))
+ return false;
+
+ return getId().equals(other.getId());
+ }
+
+ /**
+ * Check if the given instance and this one are equivalent (both objects in
+ * the same state, all child elements equivalent).
+ *
+ * @param other
+ * the other instance
+ *
+ * @param contentOnly
+ * do not check the state of the object itslef, only its content
+ *
+ * @return TRUE if they are equivalent
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public boolean isEquals(BaseClass<E> other, boolean contentOnly) {
+ if (other == null)
+ return false;
+
+ if (size() != other.size())
+ return false;
+
+ if (!contentOnly) {
+ if (!isSame(other))
+ return false;
+
+ if (!getState().equals(other.getState()))
+ return false;
+ }
+
+ Collections.sort(list, comparator);
+ Collections.sort(other.list, other.comparator);
+ for (int index = 0; index < size(); index++) {
+ if (!((BaseClass) get(index)).isEquals(other.get(index), false))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the recursive state of the current object, i.e., its children. It
+ * represents the full state information about this object's children. It
+ * does not check the state of the object itself.
+ *
+ * @return a {@link String} representing the current content state of this
+ * object, i.e., its children
+ */
+ public String getContentState() {
+ StringBuilder builder = new StringBuilder();
+
+ for (E child : this) {
+ builder.append(child.getContentState());
+ }
+
+ return StringUtils.getHash(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).
+ *
+ * @return a {@link String} representing the current state of this object,
+ * children not included
+ */
+ abstract public String getState();
+