Skip to content
Java library holding a generic model intended as the underlying model of an Eclipse GEF editor.
Java Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Modelstore: a typless modeling framework

What is this?

This is a small Java library intended to hold a model consisting of objects and relations in memory.

The main use case for this library is to be used as a generic model container for an Eclipse GEF editor. Because of this, and because it does no harm, and because I kind of like OSGi, this library is packaged as an OSGi bundle.

The API is meant to be as clutter-free as possbile in use: it should throw no exceptions, and it should return no nulls (instead of null it will return the empty string, empty collections and zero values for the numeric types).

The PropertySet interface defines the API of objects that forms both objects and relationships of the model.

This library is licensed under the Eclipse Public License. See the file LICENSE for the terms and specifics of the license.

Development stuff

Installing on karaf

The modelstore can’t be used for anything, yet. But it can be installed on apache karaf:

  1. Clone and build the project (requires git, java >= 1.8 and maven installed):
    git clone
    cd modelstore
    mvn clean install
  2. Install apache karaf using the karaf quick start
  3. In the karaf console give the following commands:
    feature:repo-add mvn:no.priv.bang.modeling.modelstore/modelstore.backend/LATEST/xml/features
    feature:install modelstore.backend

Roadmap [18/55]

Fix the test coverage of all property values (hashCode, equals and toString ruined coverage)

Put javadoc from travis builds on the web

Add javadocs to everything

Rename “propertyvalue” to “value” in type names

Having “property” in the name doesn’t make sense for the list of values, and make the type names longer than they have to be.

Refactor the propertyvalue creation into something that makes sense for a library bundle

  • Maybe a static method on the PropertyValue interface, if that’s possible?
  • Or make that creation methods on the interface, backed by a class with static methods?

Create typespecific add and set operations to the ValueList interface

Create primitive-value setters for Propertyset

Change “propertyName” to “propertyname” in arguments

Add clone or copy constructor operation to Propertyset

Add clone or copy constructor to ValueList

Add copy-on-set for complex properties and list values

  • Primitives and lists are immutable and can be shared
  • Lists and complex properties should not be shared
    • For complex properties this can be accomplished with a clone operation
    • For list properties, probably a clone here as well

Add list creation method on the PropertysetManager interface, to make it possible to create ValueList instances outside of the bundle

Put some basic aspects in place (object, relationship, model, aspectcontainer)

Split off ModelContext [5/5]

  • Modelstore will be the access point for creating and saving ModelContext instances
  • This is an approach at making the system multithreaded and performant
    • Minimal locking on the propertysets themselves, because there is only on thread using them at a time
    • No need to copy the property values, because they are immutable (except for complexproperty and listproperty, that is…)
      • Use shallow copy on list and complex object property get, perhaps?

Persist and instantiation should use PropertysetContext

Extract an interface for PropertysetContext

Add methods to the PropertysetManager to store and receive PropertysetContexts

Store metadata (last modification time, at first)

Create a merge operation that will merge all aspects and propertysets

  • Merge will not touch the id property so merging with an empty object with a different id will be to effectively make a copy with a different id
    • This may be useful

Rename the PropertysetManager interface to Modelstore

Rename PropertysetContext to ModelContext

Store exception errors in the Modelstore

  • The parsing and file/stream operations give a lot of possible error situation that right now go untracked
  • Add a logError method to the ModelContext
  • Let the ModelContext pass the error to the Modelstore
  • Create an ErrorBean with getters only and a constructor initializing the fields:
    • Date when the error occurred
    • ModelContext where the error occurred
    • Errormessage
    • Exception caught
  • Create an interface with methods
    • reportError(String message, Exception e)
    • boolean hasErrors()
    • Collection<ErrorBean> listErrors()
  • Let the ModelContext and Modelstore interfaces inherit this interface
  • Should be thread safe with a minimal locked critical region
    • Wrap the error list in a synchronized list
    • Synchronize on the list before doing a shallow copy in getErrors()

Add UUIDs of built-in aspects to Modelstore

  • Create an interface with the getters for these IDs (a “protocol”)
  • Let Modelstore inherit this interface
  • Try the following implementation: create a class implementing this interface and let ModelstoreBase inherit it, as well as implementing the Modelstore
  • Can use the same approach for value creation if of interest

Switch from Jsr330Activator to OSGi Declarative Service (DS)

  • <2019-08-12 man. 11:54> The single jar was split into defining the OSGi services and a modelstore.backend containing the DS component
  • <2019-08-12 man. 11:56> The gogoshell stuff was deleted and karaf features were created instead

Replace logging to ErrorBean with the OSGi LogService

Separate the modelstore implementation holding model in memory into an OSGi library bundle (maybe)

  • <2019-08-12 man. 20:54> modelstore.backend is to become a DS component that initially saves to and restores from disk
  • <2019-08-12 man. 20:56> need a good name for the model-in-memory library before I can create the model
  • <2019-08-12 man. 21:02> The serialization/deserialization code doesn’t need to be part of this library
  • <2019-08-12 man. 21:03> modelstore.model is probably a good name for the library,
  • <2019-08-12 man. 21:20> classes that should be migrated to modelstore.model, are:
    1. Aspects
    2. BooleanValue
    3. BuiltinAspectsBase
    4. ComplexValue
    5. DoubleValue
    6. EmptyValue
    7. EmptyValueList
    8. IdValue
    9. ListValue
    10. LongValue
    11. NilValue
    12. PropertysetImpl
    13. PropertysetNil
    14. Propertysets
    15. PropertysetValueBase
    16. ReferenceValue
    17. StringValue
    18. ValueArrayList
    19. ValueBase
    20. Values
  • <2019-08-12 man. 21:21> classes that should not be migrated to modelstore.model, are:
    1. JsonGeneratorWithReferences
    2. JsonPropertysetPersister
    3. ModelstoreProvider (this is the DS component)
  • <2019-08-12 man. 21:24> classes I’m unsure of should be migrated to modelstore.model, are:
    1. ModelContextImpl
    2. ModelContextRecordingMetadata
    3. ModelContexts
    4. ModelstoreBase
    5. PropertysetRecordingSaveTime
  • <2019-08-12 man. 21:38> Looks like not all classes in modelstore.model should be visible
  • <2019-08-12 man. 21:39> A static creator class and/or singleton is not a good pattern for OSGi: then it’s better to create a DS component
  • <2019-08-12 man. 21:49> What should the inteface exposed by the DS component be called?
    • <2019-08-12 man. 21:50> Some name candidates for the interface:
      1. Model (probably wrong. Model should be a parent object containing other objects)
      2. ModelFactory (more correct, but suffixing with “Factory” is overused, and suffixing is bad practice anyway)
      3. ObjectFactory (most correct. However, maybe too “overused”…?)
      4. ModelBuilder (sounds good, but might make people expect the builder pattern…?)
      5. ModelProducer
      6. ObjectProducer

create an OSGi bundle modelstore.client

  • <2019-08-12 man. 21:27> This is a to be a convenient starting point for using modelstore
  • <2019-08-12 man. 21:30> Design:
    1. Create an interface in called ModelstoreClient (maybe just a subtype of Modelstore?)
    2. in modelstore.client create a DS component that receives a Modelstore service and exposes a ModelstoreClient service
    3. This allows for having an in-process modelstore or a modelstore accessed through a REST API
    4. For an in-process modelstore this should be a thin wrapper
    5. For a remote modelstore this library should maintain the in-memory model

Create modelstore.db.liquibase bundle to define the JDBC schema

  • <2019-08-12 man. 22:14> The objects themselves should be stored to disk and/or a git blob store
  • <2019-08-12 man. 22:15> The schema should define object interconnection and metadata (but I don’t have clear vision of how it should look)

use the Modelstore DatabaseService in modelstore.backend

create a OSGi bundle (connect with shiro and authservice)

create a modelstore.web.api OSGi bundle providing a REST API

Create a modelstore-specific DatabaseService interface in

Create modelstore.db.derbytest OSGi bundle

Create modelstore.db.postgresql OSGi bundle

Connect a minimal hardcoded model to eclipse GEF

Implement JSON storage for eclipse GEF models

Split ModelContext objects

  • Separate out a propertyset and all the propertysets it depends on to a separate ModelContext
  • Should be thread safe before it is set to complete

Add version information to the metadata object

  • Since the metadata object will be first in all files, it is a good place to put machine and human readable version information

Add local and modified flags to the metadata object

  • The idea is that objects that aren’t created locally, and have been locally modified are the ones that needs to be saved back to a remote server

Order propertysets by dependency when serializing

  • Aspects should come before propertysets referencing them
  • Base aspects should come before aspects inheriting them
  • Propertysets being referenced should come before propertysets referencing them
    • Contents of a container should come before the container
    • Endpoints of a relationship should come before the
    • Propertyset fronted by graphical proxy propertyset should come before the proxies

Introduce a DateTime primitive type in value

  • Not so easy, since JSON doesn’t have a syntactic marker for this
  • The metadata object stores and restores Date objects with millisecond accuracy, but the values are stored as JSON strings with a custom format (human readable)
  • This could be something on the aspect, but I don’t see how to do this cleanly during parsing
    • It could be parsed as a string value, and then converted to a DateTime value on access or when an aspect is applied

Add verification code for aspects

  • Check a propertyset to see if it has the required propertysets for an aspect
  • Check the propertyset to see if it brings anything meaningful to the table (ie. property definitions)

Add AspectViwer (connected to aspect container and used as a filter)

Create a read-only propertyset wrapper with defensive copy-on-read for complex properties and lists

  • Use this with the built-in aspects

Create a proxy aspect

  • Contains a single property that is a reference to a different propertyset
  • Think about how a proxy should be handled in an aspect container
    • It would be nice if the actual application of the aspect could “pass through” to the proxied propertyset
    • The graphical information (position, symbol) should be added to the proxy

Test serialization/deserialization using YAML (YAML has object id and object reference)

Storage based on SQL for relationships and references and individual JSON files

Individual Propertyset files git versioned

Metatada into the RDBMS

  • Per propertyset load time
  • Per propertyset last modified time
  • Propertyset delete time

Storage based on PostgreSQL with native JSON support

Get PropertysetManager with storage running in Karaf

Move interface definitions to a separate bundle

  • This may be necessary when creating more components in a server setting (servlet component, and SQL server component)

Move Jackson serialization to a separate bundle (maybe a library bundle?)

  • The functionality of JsonPropertysetPersister must be available in some fashion from the Modelstore
  • JsonPropertysetPersister parsing and unparsing will be needed for:
    • parsing JSON messages from clients (REST requests)
    • Creating JSON messages to send to clients (REST responses)
    • Loading and saving individual objects in a jgit based versioned storage

Create a RESTful API and a storage/persist mechanism on top of it

Create a query language (or find something usable and implement/use)

  • Possibilities
    • I like s-expressions
    • Is there something in JSON that could be used
    • Just implement something as nested complex objects and let its JSON representation be the wire format

Make an s-expression-factory for jackson

Maybe actually two separate:

  • S-expression directly on jackson
  • sxml on top of the existing XML serialization/deserialization

Make merge operation thread safe

  • <2015-07-25 lør 15:44> Not doing this for now, too hard to be certain with the current implementation

Add propertyvalue creation methods on the ModelStore interface, to make them accessible to the world

  • Not sure if this is necessary with the primitive value setters in place for both Propertyset and Valuelist?

Decide if the PropertysetRecordingSaveTime should compare equal to a PropertysetRecordingSaveTime from a different ModelContext

  • <2015-07-14 tir 17:49> I couldn’t compare two propertsets that should have been equal with assertEquals() in a test
    • I can’t decide what’s the correct thing to do here, so I compared the unwrapped propertysets instead

Switch to defensive copy on read for list and complex properties (have to think about this)

  • This is the only (practical) way to track changes to list and complex properties
    • Wrap the complex properties and the lists will be just too much work

Rename Propertyset to Valueset

  • Don’t know if I will go through with this…?

Wrap the propertysets and aspects returned from the metadata-setting ModelContext

  • What was this about? Is this something other than the current wrapping?
You can’t perform that action at this time.