Building Complexes

BStructs vs BComponents

BComplex is the base class for both BStruct and BComponent. Classes never subclass BComplex directly (it doesn't support any public or protected constructors). Rather developers subclass from BStruct or BComponent depending on their needs. In general structs are used as complex data types. BStructs can be built only using frozen properties. BComponents support much more flexibility and are built using frozen and dynamic slots of all types:

 BStructBComponent
Frozen PropertyXX
Frozen Action X
Frozen Topic X
Dynamic Property X
Dynamic Action X
Dynamic Topic X

As you will learn, BComponents are also the basis for many other features such as BOrds, links, and the event model. You may wonder why you would use a BStruct? There are two main reasons. The first is that because of its limited feature set, it is more memory efficient. The other reason is that properties containing BComponents cannot be linked, but BStructs can be (see Links).

Building BComplexes

All concrete subclasses of BComplex must meet the following requirements:

Introspection Patterns

We have discussed how frozen slots are defined at compile time. Let's take a look at how the framework knows when frozen slots have been declared. Every slot is composed of two or three Java members. A member is the technical term for a Java field, method, or constructor. At runtime the framework uses Java reflection to examine the members of each class, looking for patterns to self-discover slots. These patterns are based on the patterns used by JavaBeans, with significant extensions. Remember introspection is used only to define frozen slots, dynamic slots are not specified in the classfile itself. There is a different pattern for each slot type.

These introspection patterns require a fair amount of boiler plate code. Although it is not too painful to write this code by hand, you may use Slot-o-matic to generate the boiler plate code for you.

Frozen Properties

Rules

Every frozen property must follow these rules:

Semantics

The introspection rules map Property meta-data as follows:

Example

The following illustrates an example for different property types:

  
  // boolean property: fooBar
  public static final Property fooBar = newProperty(0, true);
  public boolean getFooBar() { return getBoolean(fooBar); }
  public void setFooBar(boolean v) { setBoolean(fooBar, v); }
  
  // int property: cool
  public static final Property cool = newProperty(0, 100);
  public int getCool() { return getInt(cool); }
  public void setCool(int v) { setInt(cool, v); }

  // double property: analog
  public static final Property analog = newProperty(0, 75.0);
  public double getAnalog() { return getDouble(analog); }
  public void setAnalog(double v) { setDouble(analog, v); }

  // float property: description
  public static final Property description = newProperty(0, "describe me");
  public String getDescription() { return getString(description); }
  public void setDescription(String x) { setString(description, v); }

  // BObject property: timestamp
  public static final Property timestamp = newProperty(0, BAbsTime.DEFAULT);
  public BAbsTime getTimestamp() { return (BAbsTime)get(timestamp); }
  public void setTimestamp(BAbsTime v) { set(timestamp, v); }
  

Frozen Actions

Rules

Every frozen action must follow these rules:

Semantics

The introspection rules map Action meta-data as follows:

Example

The following illustrates two examples. The first action contains neither a return value nor an argument value. The second declares both a return and argument value:

  
  // action: makeMyDay
  public static final Action makeMyDay = newAction(0);
  public void makeMyDay() { invoke(makeMyDay, null, null); }
  public void doMakeMyDay() {  System.out.println("Make my day!"); }

  // action: increment
  public static final Action increment = newAction(0, new BInteger(1));
  public BInteger increment(BInteger v) 
    { return (BInteger)invoke(increment, v, null); }
  public BInteger doIncrement(BInteger i) 
    { return new BInteger(i.getInt()+1); }
  

Frozen Topics

Rules

Every frozen topic must follow these rules:

Semantics

The introspection rules map Topic meta-data as follows:

Example

The following code example illustrates declaring a frozen topic:

  
  // topic: exploded
  public static final Topic exploded = newTopic(0);
  public void fireExploded(BString event) { fire(exploded, event, null); }
  

Dynamic Slots

Dynamic slots are not declared as members in the classfile, but rather are managed at runtime using a set of methods on BComponent. These methods allow you to add, remove, rename, and reorder dynamic slots. A small sample of these methods follows:

  
  Property add(String name, BValue value, int flags);
  void remove(Property property);
  void rename(Property property, String newName);
  void reorder(Property[] properties);
  

Note: You will notice that methods dealing with dynamic slots take a Property, not a Slot. This is because all dynamic slots including dynamic Actions and Topics are also Properties. Dynamic Actions and Topics are implemented by subclassing BAction and BTopic respectively.