Entity, Entitease

Entities are the way Knownspace represents persistent, arbitrary, pieces of data. Persistent Entities reside in the Knownspace Pool, lazing about, sipping martinis, and generally waiting to be fondled by interested Simpletons. For a more thorough treatment of Entities, please refer to the Javadocs or the [insert link to EntityDescriptionInTheDesignDocument]

Note: Currently, persistence is being implemented with Java's Serializable implementation - this means that "persisted objects may not be compatible with future releases". In other words, a persisted Entity might not be usable in future releases of the Knownspace framework. There are plans in the works for moving to a more robust XML-based persistence.

Simpletons create Entities by directly invoking the static Entity.create(String name) method or by delegating to the KernelProxy and invoking its createEntity(String name) method. The reason for these duplicate points of access is a tutorial in and of itself, but the basic idea revolves around the Knownspace kernel's treatment of non-DataManagerWorker threads. Part of the Knownspace kernel's security model feels the need to throw a DataManagerException when it finds a non-DataManagerWorker thread poking around in its internals. Why is this information relevant? Well, occasionally, a GUI-based Simpleton might like to create an Entity and add it to the Pool to be persisted. Now, this is all fine and good, so long as the Entity creation is occurring as part of the Simpleton's process() method. If, however, the Entity is created on demand and via an AWT event handler (e.g., if we create an Entity when the user clicks a button), then we must use the KernelProxy to ensure that our Simpleton's probing requests into the bowels of Knownspace do not fall upon unhospitable ears. The KernelProxy is the preferred way of hiding away the complexity of converting a request made by an AWTEventThread into a request made by a DataManagerWorker thread. The KernelProxy class resides in the org.datamanager.tools.kernelproxy package and follows the Singleton pattern - it would be a good idea to familiarize yourself with this class file when writing GUI-based Simpletons. You should be using the KernelProxy if AWT Events are triggering any of the following actions (see the Javadocs for KernelProxy for a complete list):

In general, it may be easier to remember to just deal with the KernelProxy's methods.
So let's create a simple Entity representing a Face Eating Alien and lay some attributes and values on it. Remember to import the Entity class (from the org.datamanager.kernel package).
try {
    Entity faceEatingAlien = Entity.create("Huggies");
    faceEatingAlien.setValue(new StringEntityValue("Cuddles"));
    Entity humanoidVictim = Entity.create("Host Cell");
    humanoidVictim.setValue(new StringEntityValue("Breathing"));
    humanoidVictim.attach(faceEatingAlien);
    humanoidVictim.setValue(new StringEntityValue("Not Breathing"));
    humanoidVictim.detach(faceEatingAlien);
    ...
} catch (DataManagerException exception) {
    exception.printStackTrace();
    throw new RuntimeException(exception);
}
This code isn't incredibly useful, however, as there isn't really much need in creating Entities in Knownspace without adding them to the shared Pool and letting other Simpletons revel in their data. Entities are intended to be shared - otherwise, you might have been better served with a private-to-the-Simpleton data structure. Entities can be added to the Pool in two ways, via a direct call to Pool.getDefaultPool().add(Entity entity), or via the KernelProxy's addEntity(Entity entity) method.

So the code above might be transformed to:
try {
    Entity faceEatingAlien = Entity.create("Huggies");
    faceEatingAlien.setValue(new StringEntityValue("Cuddles"));

// share this Entity with any other interested Simpletons
    Pool.getDefaultPool().add(faceEatingAlien);

    Entity humanoidVictim = Entity.create("Host Cell");
    humanoidVictim.setValue(new StringEntityValue("Uninfestered"));
    humanoidVictim.attach(faceEatingAlien);

    humanoidVictim.setValue(new StringEntityValue("Infestered"));
    humanoidVictim.detach(faceEatingAlien);
    ...
} catch (DataManagerException exception) {
    exception.printStackTrace();
    throw new RuntimeException(exception);
}

Events

Simpletons can talk to each other by sharing common knowledge of Entities Now that we know how to create some simple Entities, let's create a simple example of a AlienSpawningSimpleton that spawns Face Eating Alien Entities and dumps them in the Pool, and a VictimSpawningSimpleton that spawns Humanoid Victim Entities and dumps them in the Pool. Finally, we'll need a

Constraints

When we add the entity into pool, the AddEntityEvent will be fired. Entity entity = Entity.create("test Entity source"); entity.setValue(new StringEntityValue("test Entity source")); Entity entity2 = Entity.create("test Entity attr2"); entity2.setValue(new StringEntityValue("test Entity sattr2")); entity.attach(entity2); pool.add(entity); Section 3: This section will show how to create Enity, EntityProxy, Pool and Event. Create an entity is very straightforward, but we can't create Entity in other thread such AWT thread except the DataManagerWorker (thread). If we have to create Entity in other thread, we have to use EntityProxy: Entity entity = Entity.create("abracadabra"); KernelProxy kernelProxy = KernelProxy.getInstance(); kernelProxy.setEntityValue(entity, new StringEntityValue("frizzuit")); kernelProxy.addEntity(entity); In side the KernelProxy’s addEntity() method, it will create a DataManagerWorker thread to add entity into pool. At this time, the AddEntityEvent will fire into Pool too. Section 4: This section will show you how to use knownspace’s Pool, Event and Constraint We take a look the EntityViewerSimpleton as example. First, we need to get the pool instance. Pool pool = Pool.getDefaultPool(); After we get the pool instance, we subscribe the Event. Certainly, we need to implement the EventHandler interface. In this example, the EntityViewerSimpleton want to listen every AddEntityEvent, so we need to build the event constraint and subscribe it. EventConstraint eventConstraint = new EventTypeIsConstraint (AddEntityPoolEvent.class); pool.subscribe(this, eventConstraint); When other simpleton fire the AddEntity Event into pool, which will cause EntityViewerSimpleton’s handle() method to be invoked. public void handle(DataManagerEvent dataManagerEvent) { try { Entity entity = ((AddEntityPoolEvent) dataManagerEvent).getEntity(); defaultTreeModel.insertNodeInto(buildEntityAttributes(entity), root, root.getChildCount()); defaultTreeModel.nodeChanged(root); updateLabelText(); } catch (Exception everything) { everything.printStackTrace(); throw new RuntimeException(everything); } } We can get the entity instance from the AddEntityPoolEvent by calling its getEntity() method. Section 5: This section will show you know to use complex constraint to do search in pool. The essence of knownspace is to put data into pool. We can fire the constraint into pool to search entity even recursive. After we get the search result, the simpletion’s handle() method will be called to handle the result. final EntityConstraint emailConstraint = new AttributeStringMatchConstraint( EmailMessageEntityHelper.EMAIL_ATTRIBUTE_NAME, EmailMessageEntityHelper.EMAIL_ATTRIBUTE_VALUE); Entity[] entityArray = Pool.getDefaultPool() .search(emailConstraint); In this example, we first build the EnityConstraint, then we can use that constraint to search the pool for result for entity with specifiy name/value pair. Entity[] entities = pool.search(EntityConstraint.NONE); In the example, we search all entity in the pool.
Go back to part one Go to part three: EmailGuiCollector Challenge