Expected behavior for save method for custom datatypes in core

Hi Darius,

What is the recommended implementation of the save method for our core datatype? E.g if i add a LocationDatatype, from the javadocs of CustomDatatype.save(), it is implied that the implementation logic should probably call LocationService.save, is this true?

Wyclif

Hi Wyclif,

That’s not what you need to do. Reading the javadoc, I see that things could be more clear, and the method doesn’t have the perfect name.

This is the relevant bit:

(Simple datatype implementations that don’t require external storage may just serialize their typedValue to a String and return that.)

The idea is that the framework will call CustomDatatype.save(T, String) giving you the opportunity to persist something to external/remote storage if you need to. The save() method should return a String, which the framework will then save to the database (e.g. in the xyz_attribute table). If you persisted something to external storage, the String you return should be some sort of reference to the externally-stored value (and that’s why the code and documentation use “valueReference” everywhere). If the datatype is simple, and nothing got saved to remote storage, you can just return a simple String that represents the serialized value of the “T typedValue” that was passed in.

The LocationDatatype is a simple case, and you would just return the uuid of the location.

But even better in this case is to use the SerializingCustomDatatype base class, which already takes care of all the bookkeeping.

I think we need to update the documentation to be clear on this point, and to suggest that people use SerializingCustomDatatype in the common/simple case. (Also, SerializingCustomDatatype needs class-level javadoc.)

Serializing is a reasonable default; however, if the custom data type has a value that will always fit within the 64k of value_reference, then it can simply store the raw value itself – i.e., if you have a location datatype, you could just store the location’s id or, better yet, uuid.

Serialization makes things easier in Java; however, if the serialization puts a bunch of Java metadata into the field, it could make the data harder to use via SQL (e.g., for someone exporting data or running custom SQL queries against the database).

So, for complex datatypes with multiple properties, serializing is probably the most robust approach instead of coming up with custom representations in the database; however, for very simple datatypes (e.g., a uuid), storing the raw value has advantages.

BTW… I notice that we are [inconsistent in our attributes](file:///Users/burke/Documents/OpenMRS/data%20model/openmrs-data-model-1.11.html#.*attribute%24.value): person_attribute has a value (50), while location_attribute, provider_attribute, and visit_attribute all have value_reference (64k).

I assume that’s because location_attribute, like complex observations, preceded CustomDatatype. We should probably have some design discussions on how to merge the capabilities of complex obs into CustomDatatype so a single pattern for custom datatypes could be used throughout OpenMRS (including location attributes and complex observations). I believe CustomDatatype is missing views and both custom datatypes and complex observations handlers are missing the ability to do bulk operations (e.g., search).