diff --git a/simpleexample2/core/src/main/java/simpleex/core/LatLong.java b/simpleexample2/core/src/main/java/simpleex/core/LatLong.java
index 36f118497df7fffb33cafd90f8c7308237b9b78e..3c3de07c21a7bbc36856cfaf43580af832feb371 100644
--- a/simpleexample2/core/src/main/java/simpleex/core/LatLong.java
+++ b/simpleexample2/core/src/main/java/simpleex/core/LatLong.java
@@ -15,6 +15,8 @@ public class LatLong {
   private final double latitude;
   private final double longitude;
 
+  private MetaData metaData;
+
   /**
    * Initialize a LatLong with provided latitude and longitude.
    * @param latitude the latitude
@@ -177,4 +179,24 @@ public class LatLong {
   private static double rad2deg(final double rad) {
     return (rad * 180 / Math.PI);
   }
+
+  /**
+   * Checks if this object has meta data
+   * @return true if this LatLong object has meta data, false otherwise
+   */
+  public boolean hasMetaData() {
+    return metaData != null && (! metaData.isEmpty());
+  }
+
+  /**
+   * Gets the meta data of this object. Will create it if missing,
+   * so it will always be safe to chain a call.
+   * @return the meta data of this object
+   */
+  public MetaData getMetaData() {
+    if (metaData == null) {
+      metaData = new MetaData();
+    }
+    return metaData;
+  }
 }
diff --git a/simpleexample2/core/src/main/java/simpleex/core/MetaData.java b/simpleexample2/core/src/main/java/simpleex/core/MetaData.java
new file mode 100644
index 0000000000000000000000000000000000000000..33e4fa82b99508580b161a9a97f8ebf445089a88
--- /dev/null
+++ b/simpleexample2/core/src/main/java/simpleex/core/MetaData.java
@@ -0,0 +1,225 @@
+package simpleex.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public class MetaData {
+
+  private Collection<String> tags;
+  private List<String> properties;
+
+  boolean isEmpty() {
+    return (tags == null || tags.isEmpty()) && (properties == null || properties.isEmpty());
+  }
+
+  /**
+   * Checks if all the provided tags are present.
+   * @param tags the tags to check
+   * @return true if all the provided tags are present, false otherwise
+   */
+  public boolean hasTags(final String... tags) {
+    if (this.tags == null) {
+      return tags.length == 0;
+    }
+    for (final String tag : tags) {
+      if (! this.tags.contains(tag)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Sets the tags to those provided (old ones are removed).
+   * @param tags the new tags
+   */
+  public void setTags(final String... tags) {
+    if (tags.length == 0)  {
+      this.tags = null;
+    } else {
+      if (this.tags != null) {
+        this.tags.clear();
+      } else {
+        this.tags = new ArrayList<>();
+      }
+      // cannot use addAll, since tags may contain duplicates
+      addTags(tags);
+    }
+  }
+
+  /**
+   * Adds the provided tags.
+   * @param tags the tags to add
+   */
+  public void addTags(final String... tags) {
+    if (this.tags == null && tags.length > 0) {
+      this.tags = new ArrayList<>();
+    }
+    // avoid duplicates
+    for (final String tag : tags) {
+      if (! this.tags.contains(tag)) {
+        this.tags.add(tag);
+      }
+    }
+  }
+
+  /**
+   * Removes the provided tags.
+   * @param tags the tags to remove
+   */
+  public void removeTags(final String... tags) {
+    if (this.tags != null) {
+      this.tags.removeAll(Arrays.asList(tags));
+    }
+    if (this.tags.isEmpty()) {
+      this.tags = null;
+    }
+  }
+
+  private int indexOfProperty(final String propertyName) {
+    if (properties != null) {
+      for (int i = 0; i < properties.size(); i += 2)  {
+        if (propertyName.equals(properties.get(i))) {
+          return i;
+        }
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Checks if a property with the provided name is present.
+   * @param propertyName the name to check
+   * @return true if the property is present, false otherwise
+   */
+  public boolean hasProperty(final String propertyName) {
+    return indexOfProperty(propertyName) >= 0;
+  }
+
+  /**
+   * Gets the property value for the provided property name.
+   * @param propertyName the property name
+   * @return the value for the provided property name
+   */
+  public String getProperty(final String propertyName) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      return properties.get(pos + 1);
+    }
+    return null;
+  }
+
+  /**
+   * Gets the property value for the provided property name, as an int.
+   * If the property value doesn't exist or isn't a valid integer, def is returned.
+   * @param propertyName the property name
+   * @return the value for the provided property name, as an int, or def it is missing
+   */
+  public int getIntegerProperty(final String propertyName, final int def) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      try {
+        return Integer.valueOf(properties.get(pos + 1));
+      } catch (final NumberFormatException e) {
+      }
+    }
+    return def;
+  }
+
+  /**
+   * Gets the property value for the provided property name, as a double.
+   * If the property value doesn't exist or isn't a valid double, def is returned.
+   * @param propertyName the property name
+   * @return the value for the provided property name, as a double, or def it is missing
+   */
+  public double getDoubleProperty(final String propertyName, final double def) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      try {
+        return Double.valueOf(properties.get(pos + 1));
+      } catch (final NumberFormatException e) {
+      }
+    }
+    return def;
+  }
+
+  /**
+   * Gets the property value for the provided property name, as a boolean.
+   * If the property value doesn't exist, def is returned.
+   * @param propertyName the property name
+   * @return the value for the provided property name, as a boolean, or def it is missing
+   */
+  public boolean getBooleanProperty(final String propertyName, final boolean def) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      return Boolean.valueOf(properties.get(pos + 1));
+    }
+    return def;
+  }
+
+  /**
+   * Sets the property value for the provided property name.
+   * @param propertyName the property name
+   * @param propertyValue the (new) property value
+   */
+  public void setProperty(final String propertyName, final String propertyValue) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      properties.set(pos + 1, propertyValue);
+    } else {
+      if (properties == null) {
+        properties = new ArrayList<>();
+      }
+      // add the property name
+      properties.add(propertyName);
+      // and the value
+      properties.add(propertyValue);
+    }
+  }
+
+  /**
+   * Convenience method for setting integer property.
+   * @param propertyName the property name
+   * @param propertyValue the (new) property value
+   */
+  public void setIntegerProperty(final String propertyName, final int value) {
+    setProperty(propertyName, Integer.toString(value));
+  }
+
+  /**
+   * Convenience method for setting integer property.
+   * @param propertyName the property name
+   * @param propertyValue the (new) property value
+   */
+  public void setDoubleProperty(final String propertyName, final double value) {
+    setProperty(propertyName, Double.toString(value));
+  }
+
+  /**
+   * Convenience method for setting boolean property.
+   * @param propertyName the property name
+   * @param propertyValue the (new) property value
+   */
+  public void setBooleanProperty(final String propertyName, final boolean value) {
+    setProperty(propertyName, Boolean.toString(value));
+  }
+
+  /**
+   * Removes the property with the provided name.
+   * @param propertyName the property to remove.
+   */
+  public void removeProperty(final String propertyName) {
+    final int pos = indexOfProperty(propertyName);
+    if (pos >= 0) {
+      // remove the property value
+      properties.remove(pos + 1);
+      // and the name
+      properties.remove(pos);
+      if (properties.isEmpty()) {
+        properties = null;
+      }
+    }
+  }
+}