New launcher class to start all 3 modes:
[jvcard.git] / src / be / nikiroo / jvcard / BaseClass.java
index b6be10e47795fd31d1169c07068eb4ca3963c6b2..ed9a693a355b01a7df8a222ee3296b13cea07d50 100644 (file)
@@ -9,6 +9,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 
+import be.nikiroo.jvcard.resources.StringUtils;
+
 /**
  * This class is basically a List with a parent and a "dirty" state check. It
  * sends all commands down to the initial list, but will mark itself and its
@@ -167,7 +169,7 @@ public abstract class BaseClass<E extends BaseClass<?>> implements List<E> {
                                equ = false;
                        } else {
                                // they represent the same item
-                               if (!((BaseClass) here).isEquals(there)) {
+                               if (!((BaseClass) here).isEquals(there, false)) {
                                        if (from != null)
                                                from.add(here);
                                        if (to != null)
@@ -206,32 +208,72 @@ public abstract class BaseClass<E extends BaseClass<?>> implements List<E> {
         * @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) {
+       public boolean isEquals(BaseClass<E> other, boolean contentOnly) {
                if (other == null)
                        return false;
 
                if (size() != other.size())
                        return false;
 
-               if (!isSame(other))
-                       return false;
+               if (!contentOnly) {
+                       if (!isSame(other))
+                               return false;
 
-               if (!getState().equals(other.getState()))
-                       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)))
+                       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.
+        * 
+        * @return a {@link String} representing the current content state of this
+        *         object, i.e., its children included
+        */
+       public String getContentState() {
+               StringBuilder builder = new StringBuilder();
+               buildContentStateRaw(builder);
+               return StringUtils.getHash(builder.toString());
+       }
+
+       /**
+        * Return the (first) child element with the given ID or NULL if not found.
+        * 
+        * @param id
+        *            the id to look for
+        * 
+        * @return the child element or NULL
+        */
+       public E getById(String id) {
+               for (E child : this) {
+                       if (id == null) {
+                               if (child.getId() == null)
+                                       return child;
+                       } else {
+                               if (id.equals(child.getId()))
+                                       return child;
+                       }
+               }
+
+               return null;
+       }
+
        /**
         * Return the current ID of this object -- it is allowed to change over time
         * (so, do not cache it).
@@ -242,16 +284,31 @@ public abstract class BaseClass<E extends BaseClass<?>> implements List<E> {
 
        /**
         * Get the state of the current object, children <b>not included</b>. It
-        * represents the full state information about this object, that is, two
-        * objects with the same state (and class) must return TRUE if
-        * {@link BaseClass#isEquals(BaseClass)} is called <b>and</b> their children
-        * are equivalent.
+        * 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();
 
+       /**
+        * Get the recursive state of the current object, i.e., its children. 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
+        */
+       void buildContentStateRaw(StringBuilder builder) {
+               builder.append(getState());
+               for (E child : this) {
+                       child.buildContentStateRaw(builder);
+               }
+       }
+
        /**
         * Notify that this element has unsaved changes.
         */