PersistenceOfPluginTypes

From SeSAm-Wiki

Jump to: navigation, search

Contents

Motivation

You've implemented some types of your own in some Plugin you've written for SeSAm. You'd like to save instances of these types with the SeSAm-model file. If there are Create -primitives for these types you don't need to read on. These primitives function as constructors to the types. So instances can be created from the xml-Types by using these primitives. Sometimes you don't have such primitives. Why? Because you want an Editor to pop up when some instance of that type is needed. E.g. there are editors for Numbers or Strings. If there would be a create -primitive this editor wouldn't not show.

So:

if editor then better no create . if create then surely no editor . ;-)

Note

The approach described on the current page won't create a connection to your types. That's because this approach does not store references to the instances of your types (more correctly in SeSAm-speech: TypeValue). So if you are planning to store actual values for arguements e.g., you'd have to use a different approach. That other approach is described on PersistenceOfPluginTypesWithIDREFS. Please read the current page first, though, since PersistenceOfPluginTypesWithIDREFS will only extend the information contained here.

Concept

We use a generic type that wraps your type. You can add the fields (i.e. variables in your java-object) of your type to that generic type. These fields can be one of the core-types already implemented in SeSAm (integer, string, simobject, etc.). Even other types of your own can be included (These are again wrapped in another generic type).

Image:genericPluginType.png

Ok, that's that.

Example

The type

Suppose you have the following type:

public class RoleType extends AbstractSpecificType {
private static RoleType_instance = new RoleType();
private RoleType() {
super();
ObjectType.getInstance().addSubType(this);
}
public String getName() {
return "Role";
}
public static RoleType getInstance() {
return _instance;
}
public boolean isArgumentDeclarationValueOk(Object value) {
return (value == null) || (value instanceof Role);
}
}

The type-value

Instances of the role -type will look like:

public class Role {
private String _role;
public Role() {
this(" ");
}
public Role(String role) {
_role = role;
}
public String getValue() {
return _role;
}
public void setValue(String value) {
_role = value;
}
}

You don't have a create -primitive for this type since you'd like to create instances of this type via an editor (e.g. a dialog where the modeller can choose between existing roles ).

Saving and loading your types

You'll have to implement a reader - and a writer -class to be able to store instances of that type.

The writer

The writer will have to extend IXMLTypeWriter and could look like:

public classXMLRoleTypeWriter implementsIXMLTypeWriter {
public boolean isResponsibleFor (ISpecificType specificType) {
return specificType instanceofRoleType ;
}
publicXMLTypeGroup createXMLTypeGroup (XMLModelWriter writer,ISpecificType specificType)
throwsXMLWriteException {
RoleType roleType = (RoleType ) specificType;
XMLGenericPluginType genericPluginType = newXMLGenericPluginType ();
genericPluginType.setName(roleType.getName());
XMLTypeGroup group = newXMLTypeGroup ();
group.setGenericPluginType(genericPluginType);
return group;
}
publicXMLTypeValueGroup createXMLTypeValueGroup (ISpecificType type, Object value,
XMLModelWriter modelWriter) {
RoleType roleType = (RoleType ) type;
Role role = (Role) value;
XMLGenericPluginTypeValue pluginValue = newXMLGenericPluginTypeValue ();
pluginValue.setGenericPluginTypeName(roleType.getName());
try {
pluginValue.addXMLTypeValueGroup(0, modelWriter.createXMLTypeValueGroup( StringType .getInstance(),
role.getValue()));
} catch (XMLWriteException e) {
e.printStackTrace();
}
XMLTypeValueGroup group = newXMLTypeValueGroup ();
group.setGenericPluginTypeValue(pluginValue);
return group;
}
}
  • isResponsibleFor will check whether this writer can be used to generate xml-objects to be included in the model-file.
  • createXMLTypeGroup is used to store the type.
  • createXMLTypeValueGroup is used to store instances of the type. This is the most interesting method of the writer:

The type and the actual instance (value) are given. The latter should be cast to the specific class for ease of access. Then the wrapper is instanciated ( XMLGenericPluginTypeValue ) and the name of the type is set (This is to enable recognition by the reader later on - see there). Each field of the actual java-object - _role in the current example - must be wrapped in an XMLTypeValueGroup , again. This can be achieved by using the createXMLTypeValueGroup -method of the XMLModelWriter which is a parameter to this method. As first argument to this method you'll have to provide the type of the object you'd like to wrap. The rest is managed by createXMLTypeValueGroup.

The reader

Ok, you should now be able to store your types and instances thereof into a model-file. Now for the reading... The reader will have to extend IXMLTypeReader . Like so:

public classXMLRoleTypeReader implementsIXMLTypeReader {
public boolean isResponsibleForType (XMLTypeGroup xmlType) {
return xmlType.getGenericPluginType() != null
and xmlType.getGenericPluginType().getName().equals("Role");
}
public boolean isResponsibleForValue (XMLTypeValueGroup xmlTypeValue) {
return xmlTypeValue.getGenericPluginTypeValue() != null
and xmlTypeValue.getGenericPluginTypeValue().getGenericPluginTypeName().equals("Role");
}
publicISpecificType createSpecificTypeFromTypeGroup (XMLTypeGroup xmlTypeGroup,XMLModelReader modelReader)
throwsXMLReadException {
returnRoleType .getInstance();
}
publicISpecificType createSpecificTypeFromValueGroup (XMLTypeValueGroup xmlTypeValueGroup,
XMLModelReader modelReader) throwsXMLReadException {
returnRoleType .getInstance();
}
public Object createSpecificTypeValue(XMLTypeValueGroup xmlTypeValue,XMLModelReader modelReader) {
XMLGenericPluginTypeValue typeValue = xmlTypeValue.getGenericPluginTypeValue();
Role role = new Role();
role.setValue(typeValue.getXMLTypeValueGroup(0).getString().getValue());
return role;
}
}

The reader announces its preference for a given type by first checking whether that type is a GenericPluginType ( xmlType.getGenericPluginType() != null ) and then checks if the name of that type is the right one ( xmlType.getGenericPluginType().getName().equals("Role") ). The actual reading (creating instances of the type) is done in createSpecificTypeValue . Pay attention to use the correct order for writing ( pluginValue.addXMLTypeValueGroup ) and reading values ( typeValue.getXMLTypeValueGroup ).

Engage!

To enable the writers you'll have to overwrite two methods in your implementation of AbstractSeSAmPlugin :

public Iterator getXmlTypeWriters() {
returnCollectionsHelper .createIterator(newXMLRoleTypeWriter ());
}

and

public Iterator getXmlTypeReaders() {
returnCollectionsHelper .createIterator(newXMLRoleTypeReader ());
}

Do the above steps for each type you'd like to be persistent. Done.

Personal tools