package org.yamcs.xtce;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A type definition used as the base type for a CommandDefinition
*
*
* @author nm
*
*/
public class MetaCommand extends NameDescription {
private static final long serialVersionUID = 5L;
/**
* From XTCE:
* Many commands have one or more options. These are called command arguments. Command arguments may be of any of the standard data types.
* MetaCommand arguments are local to the MetaCommand. Arguments are the visible to the user or processing software.
* This can be somewhat subjective -- for example a checksum that is always part of the command format is probably not an argument.
*/
List<Argument> argumentList = new ArrayList<Argument>();
/**
* From XTCE:
* Tells how to package this command.
* May not be referred to in the EntryList of a SequenceContainer, CommandContainerSet/CommandContainer or another MetaCommandContainer.
* May be extended by another MetaCommand/CommandContainer.
*/
MetaCommandContainer commandContainer;
/** Command inheritance
*
* From XTCE:
* The rules for MetaCommand inheritance as follows:
* A MetaCommand may extend another using the BaseMetaCommand element --- BaseMetaCommands that form loops are illegal
* --- Its CommandContainer is only inherited if the BaseContainer is explicitly set between the child and parent.
* The same rules apply to MetaCommand/CommandContainer inheritance as described in SequenceContainer/BaseContainer.
* Specific rules by element and attribute are:
* BaseMetaCommand/ArgumentAssignment Child’s content will override parent’s content if present, otherwise child gets parent’s content if it is specified.
* If argument is the same name, it overrides the parent’s ArgumentAssignment. ---
*
* ArgumentList Child’s content prefixed to parent’s content if present --
* CommandContainer Special Case: inherited like other containers if CommandContainer/BaseContainer set. Otherwise it is not inherited. ---
*
*
* Below, nothing is implemented TODO:
* AncillaryDataSet Child’s content prefixed to parent’s content if present ---
* TransmissionConstraintList Child’s content prefixed to parent’s content if present --
* DefaultSignificance Child’s content will override parent’s content if present, otherwise child gets parent’s content if specified ---
* ContextSignificanceList Child’s content prefixed to parent’s content if present ---
* Interlock Child’s content will override parent’s content if present, otherwise child gets parent’s content if specified ---
* VerifierSet Child’s content prefixed to parent’s content if present but: - Same verifiers are overridden by the child -
* CommandCompletes are accrued (child elements prefixed to parent’s). - If the child’s CommandComplete has the same @name as parent’s, the child overrides it ---
* ParameterToSetList Child’s content prefixed to parent’s content if present. If the @parameterRef is the same, the child overrides the parent’s ---
* ParameterToSuspendAlarmsOnSet Child’s content prefixed to parent’s content if present. If the @parameterRef is the same, the child overrides the parent’s.
*
* DIFFERS_FROM_XTCE: the prefixing of base attributes by child does not make sense to me. We instead implement appending - that is the argument of the parent come first, then the child.
* Note that if argument entries are specified by absolute positions, it doesn't matter whichever comes first except maybe the order in the user interface.
*/
MetaCommand baseMetaCommand;
//assignment for inheritance
List<ArgumentAssignment> argumentAssignmentList;
/**
* From XTCE:
* Some Command and Control Systems may require special user access or confirmations before transmitting commands with certain levels.
* The level is inherited from the Base MetaCommand, or it overrides any in the parent-chain if given here, however it should not go down in consequenceLevel.
*/
private Significance defaultSignificance = null;
/**
* if command is abstract, it cannot be instantiated
*/
boolean abstractCmd = false;
List<TransmissionConstraint> transmissionContstraintList = new ArrayList<TransmissionConstraint>();
/**
* From XTCE
* A Command Verifier is a conditional check on the telemetry from a SpaceSystem that that provides positive indication on the processing state of a command.
* There are eight different verifiers each associated with difference states in command processing:
* TransferredToRange, TransferredFromRange, Received, Accepted, Queued, Execution, Complete, and Failed.
* There may be multiple ‘complete’ verifiers. ‘Complete’ verifiers are added to the Base MetaCommand ‘Complete’ verifier list.
* All others will override a verifier defined in a Base MetaCommand
*
*
* In Yamcs the verifier type is specified in the stage field.
*/
private List<CommandVerifier> verifierList = new ArrayList<CommandVerifier>();
public MetaCommand(String name) {
super(name);
}
/**
* Set the command as abstract or non abstract.
* Abstract commands cannot be instantiated
* @param a
*/
public void setAbstract(boolean a) {
abstractCmd = a;
}
public boolean isAbstract() {
return abstractCmd;
}
public void setMetaCommandContainer(MetaCommandContainer mcc) {
this.commandContainer = mcc;
}
public MetaCommandContainer getCommandContainer() {
return commandContainer;
}
public void setBaseMetaCommand(MetaCommand mc) {
this.baseMetaCommand = mc;
}
public MetaCommand getBaseMetaCommand() {
return baseMetaCommand;
}
/**
* returns the argument assignment list in relation to the inheritance
* - this is the list of arguments of the parent(s) which are assigned when the inheritance takes place
*
* returns null if there is no such argument
* @return
*/
public List<ArgumentAssignment> getArgumentAssignmentList() {
if(argumentAssignmentList==null) return null;
return Collections.unmodifiableList(argumentAssignmentList);
}
/**
* returns the list of arguments of this command
* can be empty if the command doesn't have arguments
* @return
*/
public List<Argument> getArgumentList() {
if(argumentList==null) return null;
return Collections.unmodifiableList(argumentList);
}
/**
* returns an argument based on name or null if it doesn't exist
* @param argumentName
* @return
*/
public Argument getArgument(String argumentName) {
for(Argument a: argumentList) {
if(a.getName().equals(argumentName)) {
return a;
}
}
return null;
}
public void addArgument(Argument arg) {
argumentList.add(arg);
}
public void addTransmissionConstrain(TransmissionConstraint constraint) {
transmissionContstraintList.add(constraint);
}
public List<TransmissionConstraint> getTransmissionConstraintList() {
return transmissionContstraintList;
}
public void addArgumentAssignment(ArgumentAssignment aa) {
if(argumentAssignmentList==null) {
argumentAssignmentList = new ArrayList<ArgumentAssignment>();
}
argumentAssignmentList.add(aa);
}
public boolean hasTransmissionConstraints() {
return !transmissionContstraintList.isEmpty();
}
public Significance getDefaultSignificance() {
return defaultSignificance;
}
public void setDefaultSignificance(Significance defaultSignificance) {
this.defaultSignificance = defaultSignificance;
}
public void addVerifier(CommandVerifier cmdVerifier) {
verifierList.add(cmdVerifier);
}
public boolean hasCommandVerifiers() {
return (!verifierList.isEmpty()) || ((baseMetaCommand!=null) && baseMetaCommand.hasCommandVerifiers());
}
public List<CommandVerifier> getCommandVerifiers() {
return Collections.unmodifiableList(verifierList);
}
public void print(PrintStream out) {
out.print("MetaCommand name: "+name+" abstract:"+abstractCmd);
if(getAliasSet()!=null) out.print(", aliases: "+getAliasSet());
if(!transmissionContstraintList.isEmpty()) {
out.print(", TransmissionConstraints: ");
out.print(transmissionContstraintList.toString());
}
if(defaultSignificance!=null) {
out.print(", defaultSignificance: ");
out.print(defaultSignificance.toString());
}
if(!verifierList.isEmpty()) {
out.print(", Verifiers: ");
out.print(verifierList.toString());
}
out.println();
if(baseMetaCommand!=null) {
out.println("\t baseMetaCommand: "+baseMetaCommand.getName()+" with argument assignment:" +argumentAssignmentList);
}
commandContainer.print(out);
}
}