//Supporting operation aliases for OCL
operation Any oclIsUndefined() : Boolean {
	return self.isUndefined();
}

operation Any oclIsTypeOf(t:Any) : Boolean {
	return self.isTypeOf(t);
}

operation Any oclIsKindOf(t:Any) : Boolean {
	return self.isKindOf(t);
}


operation Any oclAsType(t:Any) : Any {
	return self;
}

operation Any notEmpty() : Boolean {
	return not self.isEmpty();
}


operation Any container() : Any {
	return self.eContainer;
}

operation String size() : Integer {
	return self.length();
}


//Supporting operations
operation Any getTestDescription() : Any {
	if (self.eContainer.isDefined()) {
		if (not self.eContainer.isKindOf(TestDescription)) {
			return self.eContainer.getTestDescription();
		} else {
			return self.eContainer;
		}
	} 
}

operation Any getTestObjective() : Any {
	if (self.eContainer.isDefined()) {
		if (not self.eContainer.isKindOf(StructuredTestObjective)) {
			return self.eContainer.getTestObjective();
		} else {
			return self.eContainer;
		}
	} 
}

operation Any contains(object : Any) : Boolean {
	return self.eAllContents().includes(object);
}

operation TDL!StructuredTestObjective indexOf(object : Any) : Integer {
	return self.eAllContents().indexOf(object);
}


//QualifiedNames
operation Any qualifiedName() : String {
	var p = self.getNamedParent();
	if (p.isDefined()) {
		return p.qualifiedName()+"::"+self.name;
	} else {
		return self.name;
	}
}

operation Any getNamedParent() : Any {
	if (self.eContainer.isDefined()) {
		if (not self.eContainer.isKindOf(NamedElement)) {
			return self.eContainer.getNamedParent();
		} else {
			return self.eContainer;
		}
	}
}


//Get Data Type
//TODO: add support for reduction..
//TODO: check for reduction too once support is added
operation TDL!DataInstanceUse getDataType() : Any {
	if (not self.dataInstance.oclIsUndefined()) {
		return self.dataInstance.dataType;
	} else if (not self.dataType.oclIsUndefined()) {
		return self.dataType;
	} else {
		if (self.container().oclIsTypeOf(MemberAssignment)) {
			return self.container().member.dataType;
		} else if (self.container().oclIsTypeOf(ParameterBinding)) {
			return self.container().parameter.dataType;
		} else {
			(self.container().type.name+".getDataType() not yet defined").println();
		}
	}
}

operation TDL!FunctionCall getDataType() : Any {
	return self.`function`.returnType;
}

operation TDL!VariableUse getDataType() : Any {
	return self.variable.dataType;
}

operation TDL!TimeLabelUse getDataType() : Any {
	return Time.allInstances().first();
}

operation TDL!FormalParameterUse getDataType() : Any {
	return self.parameter.dataType;
}

operation TDL!SpecialValueUse getDataType() : Any {
	var t;
	if (self.eContainer.isTypeOf(MemberAssignment)) {
		t = self.eContainer.member.dataType;
	} else if (self.eContainer.isTypeOf(ParameterBinding)) {
		t = self.eContainer.parameter.dataType;
	} else if (self.eContainer.isTypeOf(Interaction) and 
				self.isTypeOf(AnyValue)) {
		t = self.dataType;
	}
	return t;
}

//Check if Behaviour is tester input event
operation TDL!Behaviour isTesterInputEvent() : Boolean {
    return	self.oclIsKindOf(TimeOut)
       	 or	self.oclIsKindOf(Quiescence)
   		or (self.oclIsKindOf(Interaction)
  		and self.sourceGate.component.role.name = 'SUT'
   		and self.target->exists(t | t.targetGate.component.role.name = 'Tester'));
}

