package org.yamcs.xtce;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* SpaceSystem is a collection of SpaceSystem(s) including space assets, ground assets,
* multi-satellite systems and sub-systems. A SpaceSystem is the root element for the set of data
* necessary to monitor and command an arbitrary space device - this includes the binary decomposition the
* data streams going into and out of a device.
*
*
* @author nm
*
*/
public class SpaceSystem extends NameDescription {
private static final long serialVersionUID = 6L;
private SequenceContainer rootSequenceContainer;
public SpaceSystem(String name) {
super(name);
}
Header header;
private Map<String, SequenceContainer> containers=new LinkedHashMap<>();
private Map<String, Parameter> parameters = new LinkedHashMap<>();
private HashMap<String, ParameterType> parameterTypes = new HashMap<>();
private HashMap<String, Algorithm> algorithms = new HashMap<>();
private HashMap<String, MetaCommand> commands = new HashMap<>();
private HashMap<Class<?>, NonStandardData> nonStandardDatas = new HashMap<>();
private HashMap<String, SpaceSystem> subsystems = new HashMap<String, SpaceSystem>();
static Logger log = LoggerFactory.getLogger(SpaceSystem.class.getName());
transient List<NameReference> unresolvedReferences = new ArrayList<NameReference>();
SpaceSystem parent;
public void setHeader(Header h) {
this.header = h;
}
/**
* Register the container
*
* @param container Container to be registered
*/
public void addSequenceContainer(SequenceContainer container) {
if(containers.containsKey(container.getName()))
throw new IllegalArgumentException("there is already a container with name "+container.getName());
containers.put(container.getName(), container);
}
public void addParameter(Parameter parameter) throws IllegalArgumentException{
if(parameters.containsKey(parameter.getName()))
throw new IllegalArgumentException("there is already a parameter with name "+parameter.getName()+" in space system "+(qualifiedName==null?name:qualifiedName));
parameters.put(parameter.getName(), parameter);
}
public void addParameterType(ParameterType parameterType) {
String ptn=((NameDescription)parameterType).getName();
if(parameterTypes.containsKey(ptn))
throw new IllegalArgumentException("there is already a parameter type with name "+ptn);
parameterTypes.put(ptn, parameterType);
}
public void addAlgorithm(Algorithm algorithm) {
if(algorithms.containsKey(algorithm.getName()))
throw new IllegalArgumentException("there is already an algorithm with name "+algorithm.getName());
algorithms.put(algorithm.getName(), algorithm);
}
public void addMetaCommand(MetaCommand command) {
if(commands.containsKey(command.getName()))
throw new IllegalArgumentException("there is already a command with name "+command.getName());
commands.put(command.getName(), command);
}
public MetaCommand getMetaCommand(String refName) {
return commands.get(refName);
}
public ParameterType getParameterType(String typeName) {
return parameterTypes.get(typeName);
}
public SequenceContainer getSequenceContainer(String refName) {
return containers.get(refName);
}
public Algorithm getAlgorithm(String algoName) {
return algorithms.get(algoName);
}
public Parameter getParameter(String refName) {
return parameters.get(refName);
}
public void addSpaceSystem(SpaceSystem ss) throws IllegalArgumentException {
if(subsystems.containsKey(ss.getName()))
throw new IllegalArgumentException("there is already a subsystem with name "+ss.getName());
subsystems.put(ss.getName(), ss);
ss.setParent(this);
}
public void addUnresolvedReference(NameReference nr) {
unresolvedReferences.add(nr);
}
public Collection<SequenceContainer> getSequenceContainers() {
return containers.values();
}
public int getSequenceContainerCount(boolean recurse) {
if (!recurse) return containers.size();
int total = containers.size();
for (SpaceSystem sub : getSubSystems()) {
total += sub.getSequenceContainerCount(recurse);
}
return total;
}
/**
* Returns the direct sub parameters of this space system
*/
public Collection<Parameter> getParameters() {
return parameters.values();
}
/**
* Returns the parameters defined in this space system, or under any
* of its sub space systems
*/
public Collection<Parameter> getParameters(boolean recurse) {
if (!recurse) return getParameters();
List<Parameter> res = new ArrayList<>();
res.addAll(parameters.values());
for (SpaceSystem sub : getSubSystems()) {
res.addAll(sub.getParameters(recurse));
}
return res;
}
public int getParameterCount(boolean recurse) {
if (!recurse) return parameters.size();
int total = parameters.size();
for (SpaceSystem sub : getSubSystems()) {
total += sub.getParameterCount(recurse);
}
return total;
}
public Collection<ParameterType> getParameterTypes() {
return parameterTypes.values();
}
public Collection<SpaceSystem> getSubSystems() {
return subsystems.values();
}
public Collection<Algorithm> getAlgorithms() {
return algorithms.values();
}
public int getAlgorithmCount(boolean recurse) {
if (!recurse) return algorithms.size();
int total = algorithms.size();
for (SpaceSystem sub : getSubSystems()) {
total += sub.getAlgorithmCount(recurse);
}
return total;
}
public Collection<MetaCommand> getMetaCommands() {
return commands.values();
}
/**
* remove parameter from SpaceSystem - only used during loading or from XtceDb
* XtceDb has several maps pointing to these parameters.
*
* @param p parameter to remove
*/
public void removeParameter(Parameter p) {
parameters.remove(p.getName());
}
public int getMetaCommandCount(boolean recurse) {
if (!recurse) return commands.size();
int total = commands.size();
for (SpaceSystem sub : getSubSystems()) {
total += sub.getMetaCommandCount(recurse);
}
return total;
}
public List<NameReference> getUnresolvedReferences() {
return unresolvedReferences;
}
public void setParent(SpaceSystem parent) {
this.parent=parent;
}
public SpaceSystem getParent() {
return parent;
}
public SpaceSystem getSubsystem(String sname) {
return subsystems.get(sname);
}
public SequenceContainer getRootSequenceContainer() {
return rootSequenceContainer;
}
public void setRootSequenceContainer(SequenceContainer sc) {
this.rootSequenceContainer=sc;
}
public Header getHeader() {
return header;
}
/**
* Add non-standard data to this SpaceSystem. This enables loading any kind
* of data from within custom SpaceSystemLoaders and making it available
* through the XtceDb.
* <p>
* Non-standard data is distinguished from each other using the classname.
* Only one object is allowed for each classname.
*/
public void addNonStandardData(NonStandardData data) {
if(nonStandardDatas.containsKey(data.getClass()))
throw new IllegalArgumentException("there is already non-standard data of type "+data.getClass());
nonStandardDatas.put(data.getClass(), data);
}
@SuppressWarnings("unchecked")
public <T extends NonStandardData> T getNonStandardDataOfType(Class<T> clazz) {
if(nonStandardDatas.containsKey(clazz))
return (T) nonStandardDatas.get(clazz);
else
return null;
}
public Collection<NonStandardData> getNonStandardData() {
return nonStandardDatas.values();
}
@Override
public String toString() {
return "SpaceSystem["+getName()+"]";
}
}