Commit 951cfc51 authored by Martti Käärik's avatar Martti Käärik
Browse files

Added Template interface to Data #114

parent ff03ea43
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ public class ArgumentImpl<T, V> extends DataImpl<T, V> {

	public ArgumentImpl(Data<T, V> data, String parameterName) {
		super(data.getType(), data.getValue());
		setTemplate(data.getTemplate());
		this.parameterName = parameterName;
	}

+13 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.execution.java.rt.core;

import org.etsi.mts.tdl.execution.java.tri.Data;
import org.etsi.mts.tdl.execution.java.tri.Template;

/**
 * In Java environment the <code>type</code> is a Java class and
@@ -13,6 +14,8 @@ public class DataImpl<T, V> implements Data<T, V> {

	private V value;

	private Template template = TemplateImpl.NONE;

	public DataImpl(T type, V value) {
		this.type = type;
		this.value = value;
@@ -26,4 +29,14 @@ public class DataImpl<T, V> implements Data<T, V> {
		return type;
	}

	@Override
	public Template getTemplate() {
		return template;
	}

	public DataImpl<T, V> setTemplate(Template template) {
		this.template = template != null ? template : TemplateImpl.NONE;
		return this;
	}

}
+24 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.execution.java.rt.core;

import org.etsi.mts.tdl.execution.java.tri.Template;

public class PojoData<V> extends DataImpl<Class<V>, V> {

	public PojoData(V value) {
		super(value != null ? (Class<V>) value.getClass() : null, value);
	}

	/**
	 * A POJO value with a template marking special values within it.
	 */
	public PojoData(V value, Template template) {
		this(value);
		if (value == null && template != null && template.getSpecialValue() != null)
			throw new IllegalArgumentException(
					"A root-level special value requires an explicit type, use PojoData(Class, Template)");
		setTemplate(template);
	}

	/**
	 * A root-level special value: there is no concrete value, so the type to be
	 * used for decoding incoming data must be provided explicitly.
	 */
	public PojoData(Class<V> type, Template template) {
		super(type, null);
		if (type == null)
			throw new IllegalArgumentException("A root-level special value requires an explicit type");
		setTemplate(template);
	}

}
+170 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.execution.java.rt.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.etsi.mts.tdl.execution.java.tri.SpecialValue;
import org.etsi.mts.tdl.execution.java.tri.Template;

/**
 * Builder-style {@link Template} implementation.
 */
public class TemplateImpl implements Template {

	/**
	 * The unspecified node: no marking, no treatment, no children. Navigation
	 * returns the node itself so recursion over an unspecified subtree stays
	 * unspecified. Used wherever the template carries no information.
	 */
	public static final Template NONE = new Template() {
		@Override
		public SpecialValue getSpecialValue() {
			return null;
		}

		@Override
		public SpecialValue getUnassignedMemberTreatment() {
			return null;
		}

		@Override
		public Template getMember(String name) {
			return this;
		}

		@Override
		public Template getItem(int index) {
			return this;
		}

		@Override
		public boolean isSpecified() {
			return false;
		}
	};

	private SpecialValue specialValue;

	private TemplateImpl parent;
	private SpecialValue unassignedMemberTreatment;
	/**
	 * Lazily created node returned for members/items this node has no template
	 * for: unspecified, but enclosed by this node so that it reports the treatment
	 * of unassigned members in effect.
	 */
	private TemplateImpl unassignedTemplate;
	/**
	 * Marks {@link #unassignedTemplate} nodes.
	 */
	private boolean specified = true;

	private Map<String, Template> members = new HashMap<String, Template>();
	private List<Template> items = new ArrayList<Template>();

	public TemplateImpl() {
	}

	public TemplateImpl(SpecialValue specialValue) {
		this.specialValue = specialValue;
	}

	/**
	 * Mark a member with a special value. Shorthand for
	 * <code>member(name, new TemplateImpl(value))</code>; the name is used as in
	 * {@link #member(String, Template)}.
	 */
	public TemplateImpl mark(String memberName, SpecialValue value) {
		return member(memberName, new TemplateImpl(value));
	}

	/**
	 * Attach the template of a structure member.
	 *
	 * @param name The member name as used in the value representation (see
	 *             {@link Template#getMember(String)}).
	 */
	public TemplateImpl member(String name, Template template) {
		this.members.put(name, template);
		adopt(template);
		return this;
	}

	/**
	 * Append the template of the next collection item. Items must be added in the
	 * same order as in the collection value.
	 */
	public TemplateImpl item(Template template) {
		this.items.add(template);
		adopt(template);
		return this;
	}

	private void adopt(Template child) {
		if (child instanceof TemplateImpl && child != NONE)
			((TemplateImpl) child).parent = this;
	}

	/**
	 * Set the treatment of members and items not assigned in the data. Once in
	 * effect, {@link #getMember(String)} and {@link #getItem(int)} return a node
	 * marked with the treatment for every member/item that has no template of its
	 * own.
	 */
	public TemplateImpl setUnassignedMemberTreatment(SpecialValue treatment) {
		if (treatment == SpecialValue.OmitValue)
			throw new IllegalArgumentException("OmitValue is not a valid unassigned member treatment");
		this.unassignedMemberTreatment = treatment;
		return this;
	}

	@Override
	public SpecialValue getUnassignedMemberTreatment() {
		for (TemplateImpl t = this; t != null; t = t.parent)
			if (t.unassignedMemberTreatment != null)
				return t.unassignedMemberTreatment;
		return null;
	}

	/**
	 * The node returned for members and items this node has no template for. If
	 * a treatment of unassigned members is in effect it is an unspecified node
	 * enclosed by this one (so that it reports the treatment, also when descending
	 * further into a concrete but unregistered subtree); otherwise {@link #NONE}.
	 */
	private Template getUnassignedTemplate() {
		if (getUnassignedMemberTreatment() == null)
			return NONE;
		if (unassignedTemplate == null) {
			unassignedTemplate = new TemplateImpl();
			unassignedTemplate.specified = false;
			unassignedTemplate.parent = this;
		}
		return unassignedTemplate;
	}

	@Override
	public SpecialValue getSpecialValue() {
		return specialValue;
	}

	@Override
	public Template getMember(String name) {
		Template t = this.members.get(name);
		return t != null ? t : getUnassignedTemplate();
	}

	@Override
	public Template getItem(int index) {
		if (index >= 0 && index < this.items.size())
			return this.items.get(index);
		return getUnassignedTemplate();
	}

	@Override
	public boolean isSpecified() {
		return specified;
	}

}
+11 −4
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ import java.util.Map;

import org.etsi.mts.tdl.execution.java.tri.Data;
import org.etsi.mts.tdl.execution.java.tri.Mapping;
import org.etsi.mts.tdl.execution.java.tri.SpecialValue;
import org.etsi.mts.tdl.execution.java.tri.Template;
import org.etsi.mts.tdl.execution.java.tri.Type;
import org.etsi.mts.tdl.execution.java.tri.Value;

@@ -24,6 +24,8 @@ public class ValueImpl extends NamedElementImpl implements Value, TriImpl<ValueI

	private MappingImpl mapping;

	private Template template = TemplateImpl.NONE;

	public ValueImpl() {
	}

@@ -31,8 +33,13 @@ public class ValueImpl extends NamedElementImpl implements Value, TriImpl<ValueI
		this.type = type;
	}

	public ValueImpl(SpecialValue specialValue) {
		this.value = specialValue;
	public ValueImpl setTemplate(Template template) {
		this.template = template != null ? template : TemplateImpl.NONE;
		return this;
	}

	public Template getTemplate() {
		return template;
	}

	public ValueImpl setType(TypeImpl type) {
@@ -125,7 +132,7 @@ public class ValueImpl extends NamedElementImpl implements Value, TriImpl<ValueI
	}

	public Data<Type, Value> asData() {
		return new DataImpl<Type, Value>(type, this);
		return new DataImpl<Type, Value>(type, this).setTemplate(template);
	}

}
Loading