Accessing "schema pieces" through a namespace - e-ucm/ead GitHub Wiki

Identifying and retrieving objects through String ids using Accessor.

In eAdventure it is possible to access any object loaded in memory using a simple syntax. This is thanks to the Accessor utility. This wiki page is meant to describe the utility and its usage.

Simple example and syntax

The better way to see what Accessor does is through an example. Suppose we have classes A, B and C structured as follows:

public static class A{
   private int a;
   private List<B> bs;
   public A(){}
   public void set(int a, List<B> bs){
      this.a = a;
      this.bs = bs;
   }
}

public static class B{
   int b;
   Map<String, C> cs;
   public B(){}
   public void set(int b, Map<String, C> cs){
      this.b = b;
      this.cs = cs;
   }
}

public static class C{
   int c;
   public C(){}
   public void set (int c){
     this.c=c;
   }
}

Then, imagine we setup some objects like this:

...
// Create C object
C c1 = new C(); c1.set(3);
// Create B object
B b1 = new B();
Map<String, C> cs = new HashMap<String, C>(); cs.put("c1", c1);
b1.set(2, cs);
// Create A object
A a1 = new A();
List<B> bs = new ArrayList<B>(); bs.add(b1);
a1.set(1, bs);

Using Accessor we can access any property contained in the object hierarchy. For example, we can access the a value through an id like: "a.a", which will return 1. Notice how the "." is used to access any field in objects, either object fields (e.g. Object) or basic type fields (e.g. float, int, etc.).

Similarly, it is possible to access b value through an id like: "a.bs[0].b", which will return 2. Notice that [ and ] are used to access elements in objects of List type.

Also, it is possible to access value c through id: "a.bs[0].cs<\"c1\">.c", returning the value 3. In this case, < and > are used to access elements placed into Maps.

Purpose

Accessor was developed to serve two different purposes:

  1. Provide an easy way to identify and access schema pieces (i.e. properties and components in ModelEntities
  2. Provide a way to retrieve and modify runtime properties in the engine (i.e. Components and ActorEntity). This allows flexible modification of the game scene at any point.

However, Accessor is completely unaware of the structure that the schema or the runtime engine classes have, so it can be actually used to access any property in most object structures (see sections on Map and List types supported for more details).

##Public API Accessor provides two convenient methods:

  • resolve(String fullId)
  • resolve(Object parent, String fullId)

that, given the String that represents the fully qualified id of an object in the model tree, returns the value of that object.

Accessor contains a map with the "root" objects in the hierarchy to resolve properties from. This way, resolve(String fullId) assumes the fully qualified id provided refers to a property in one of the root objects.

Example: Suppose an Accessor has been initialized with the previous "a" object as the solely element in the map of root objects:

  Map<String, Object> rootObjects = new HashMap<String, Object>();
  rootObjects.put("a", a1);
  Accessor accessor = new Accessor(rootObjects, entitiesLoader);

This way, accessor would expect any fullId provided to start with one of the keys in the root object map, which in this case contains only key "a". Admitted call in this example: accessor.resolve("a.bs[0].cs<\"c1\">.c"). However, the next call would not be admitted: accessor.resolve("b.cs<\"c1"\>.c"), since "b" is not the key of an entry in the root objects map.

resolve(Object parent, String fullId) is similar, but does not use the root objects map. It just assumes that fullId represents a property in the parent Object.

Using the [] operator for accessing elements in lists

[] can be used to access elements in lists, where the index of the element to be retrieved is passed among the brackets (only numbers accepted). But the operator is not limited to objects implementing the java.util.List interface, since it can also be used on objects of type com.badlogic.gdx.utils.Array, since these are used a lot in the eAdventure engine. Native Java arrays are not supported right now, although they could be added easily.

Using the <> operator for accessing elements in maps.

<> can be used to access elements in maps, where the key of the entry is passed between < and >. <> can be used over any element implementing java.util.Map, but also on instances of com.badlogic.gdx.utils.IntMap and com.badlogic.gdx.utils.ObjectMap which are used a lot in the eAdventure engine.

Examples:

Map<String, Object> map;
...
// map is placed into root objects
...
accessor.resolve("map<\"a key\">"); // returns element in map with the given key.
ObjectMap<Class, Object> map;
map.put(Integer.class, object1);
map.put(Float.class, object2);
...
// map is placed into root objects
...
accessor.resolve("map<java.lang.Integer>"); // returns object1

Limitations

Not all types of maps are supported. Keys can only be String, Class, Integer or Float. Otherwise an exception is thrown.

Accessing Component maps

There is also a very convenient feature in maps. If the map's keys are of Class type, where the those classes are subclasses of the engine's Component class, then it is possible to use their corresponding model component aliases among < and >. Example: The Visibility model component has the alias "visibility", which is a short name for xxx, gets converted to the VisibilityComponent runtime component dynamically.

Map<Class<? extends Component>, Object> components;
components.put(VisibilityComponent.class, object1);
...
accessor.resolve("map<visibility>"); // returns object1
accessor.resolve("map<es.eucm.ead.engine.components.VisibilityComponent>"); // Also returns object1
accessor.resolve("map<es.eucm.ead.schema.components.Visibility>"); //Another way to retrieve object.
⚠️ **GitHub.com Fallback** ⚠️