Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Creating a combined metadata type

...

Different metadata types can be used together. For this, in the best case, a single class should be provided, that combines this data. Typically, this class just delegates to the base classes. In the following is an example with trust and timeinterval:

Code Block
languagejava
linenumberstrue
public class IntervalTrust extends AbstractCombinedMetaAttribute implements ITimeInterval, ITrust {

	private static final long serialVersionUID = 1599620389994530920L;

	@SuppressWarnings("unchecked")
	public final static Class<? extends IMetaAttribute>[] classes = new Class[] { ITimeInterval.class, ITrust.class };

	@Override
	public Class<? extends IMetaAttribute>[] getClasses() {
		return classes;
	}

	public static final List<SDFMetaSchema> schema = new ArrayList<>(classes.length);

	static {
		schema.addAll(TimeInterval.schema);
		schema.addAll(Trust.schema);
	}

	@Override
	public List<SDFMetaSchema> getSchema() {
		return schema;
	}

	@Override
	public String getName() {
		return "IntervalTrust";
	}

The new class must extend AbstractCombinedMetaAttribute and implements the base interfaces for this combination.

The classes for this metadata is the same set of interfaces, and should be in lexical order.

The schema is simply a list containing the subschema of the containing metadata.

Code Block
languagejava
linenumberstrue
	private final ITrust trust;
	private final ITimeInterval timeInterval;

	public IntervalTrust() {
		this.trust = new Trust();
		this.timeInterval = new TimeInterval();
	}

	public IntervalTrust(IntervalTrust other) {
		this.trust = (ITrust) other.trust.clone();
		this.timeInterval = (ITimeInterval) other.timeInterval.clone();
	}

	@Override
	public IntervalTrust clone() {
		return new IntervalTrust(this);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		} else if (!(obj instanceof IntervalTrust)) {
			return false;
		}
		IntervalTrust other = (IntervalTrust) obj;
		return this.trust.equals(other.trust) && this.timeInterval.equals(other.timeInterval);
	}

Also similiar to the basetypes, there must be a default constructor, a copy constructor a clone-method and an equals method.

Code Block
languagejava
linenumberstrue
	// ------------------------------------------------------------------------------
	// Methods that need to merge different types
	// ------------------------------------------------------------------------------

	@Override
	public void retrieveValues(List<Tuple<?>> values) {
		this.timeInterval.retrieveValues(values);
		this.trust.retrieveValues(values);
	}

	@Override
	public void writeValues(List<Tuple<?>> values) {
		this.timeInterval.writeValue(values.get(0));
		this.trust.writeValue(values.get(1));
	}

	@Override
	public List<IInlineMetadataMergeFunction<? extends IMetaAttribute>> getInlineMergeFunctions() {
		List<IInlineMetadataMergeFunction<? extends IMetaAttribute>> list = new ArrayList<>();
		list.addAll(this.timeInterval.getInlineMergeFunctions());
		list.addAll(this.trust.getInlineMergeFunctions());
		return list;
	}

	@Override
	public <K> K getValue(int subtype, int index) {
		switch (subtype) {
		case 0:
			return this.timeInterval.getValue(0, index);
		case 1:
			return this.trust.getValue(0, index);
		default:
			return null;
		}
	}

	@Override
	public String toString() {
		return "( i= " + this.timeInterval.toString() + " | " + " l=" + this.trust + ")";
	}

The next block contains methods to retrieve and set the combined values and merge functions. As you can see, here is always delegated to the base metadata. Important here is to keep the right order!

In getValue, the subtype, says from which metadata the value should be retrieved.

The last block just contains the getter and setter for the metadata and is always delegated to the base types:


Code Block
languagejava
linenumberstrue
	// ------------------------------------------------------------------------------
	// Delegates for timeInterval
	// ------------------------------------------------------------------------------

	@Override
	public PointInTime getStart() {
		return this.timeInterval.getStart();
	}

	@Override
	public PointInTime getEnd() {
		return this.timeInterval.getEnd();
	}

	@Override
	public void setStart(PointInTime point) {
		this.timeInterval.setStart(point);
	}

	@Override
	public void setEnd(PointInTime point) {
		this.timeInterval.setEnd(point);
	}

	@Override
	public void setStartAndEnd(PointInTime start, PointInTime end) {
		this.timeInterval.setStartAndEnd(start, end);
	}

	@Override
	public int compareTo(ITimeInterval o) {
		return this.timeInterval.compareTo(o);
	}

	// ------------------------------------------------------------------------------
	// Delegates for trust
	// ------------------------------------------------------------------------------

	@Override
	public double getTrust() {
		return this.trust.getTrust();
	}

	@Override
	public void setTrust(double trustValue) {
		this.trust.setTrust(trustValue);
	}

When Odysseus at Runtime does not find such a combined metadata it will create a new one and compile it. This is slower and does not always work. So it is better to create a combination.

You could use:

GenerateMetadataClassCode (https://git.swl.informatik.uni-oldenburg.de/projects/ODY/repos/odysseus_core/browse/common/core/src/de/uniol/inf/is/odysseus/core/metadata/GenerateMetadataClassCode.java) as a generator for the combined metadata. 

Remark: Typically, it is best to put each combination of metadata to an own bundle to avoid to many dependencies.

Finally, this class need to be registered as metadata, too:

Code Block
languagexml
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="de.uniol.inf.is.odysseus.interval_trust.IntervalTrust">
   <implementation class="de.uniol.inf.is.odysseus.interval_trust.IntervalTrust"/>
   <service>
      <provide interface="de.uniol.inf.is.odysseus.core.metadata.IMetaAttribute"/>
   </service>
</scr:component>