| 1 | package de.uka.ipd.sdq.pipesandfilters.framework; |
| 2 | |
| 3 | import java.util.Vector; |
| 4 | |
| 5 | import de.uka.ipd.sdq.pipesandfilters.framework.exceptions.PipesAndFiltersException; |
| 6 | |
| 7 | /** |
| 8 | * |
| 9 | * A PipesAndFilterManager should be used to build and organize the pipes and |
| 10 | * filters structure. Filters and Recorders can be added and connected. The |
| 11 | * Manager will make sure that all pipe elements are connected in a valid way |
| 12 | * and that data is transmitted correctly through the pipes. |
| 13 | * |
| 14 | * @author Baum |
| 15 | * |
| 16 | */ |
| 17 | |
| 18 | public class PipesAndFiltersManager { |
| 19 | private Vector<PipeElement> elements = new Vector<PipeElement>(); |
| 20 | private PipeElement startElement; |
| 21 | |
| 22 | /** |
| 23 | * The constructor of the PipesAndFiltersManager. A first pipe element hast |
| 24 | * to be passed to the constructor and will be set as front element of the |
| 25 | * pipe. |
| 26 | * |
| 27 | * @param startElement |
| 28 | * An element of the pipes and filters structure. It will be set |
| 29 | * as default start element. |
| 30 | */ |
| 31 | public PipesAndFiltersManager(PipeElement startElement) { |
| 32 | elements.add(startElement); |
| 33 | this.startElement = startElement; |
| 34 | } |
| 35 | |
| 36 | /** |
| 37 | * Adds any pipe element to the pipes and filters structure. |
| 38 | * |
| 39 | * @param e |
| 40 | * The element to be added. |
| 41 | * @throws PipesAndFiltersException |
| 42 | */ |
| 43 | public void addElement(PipeElement e) throws PipesAndFiltersException { |
| 44 | if (!elements.contains(e)) { |
| 45 | elements.add(e); |
| 46 | } else { |
| 47 | throw new PipesAndFiltersException( |
| 48 | "Pipe element has already been added before."); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | /** |
| 53 | * Adds a directed connection (pipe) from the element in the first argument |
| 54 | * to that one in the second argument. The method will check that neither |
| 55 | * the maximum out-degree of the first element nor the maximum in-degree of |
| 56 | * the second element are exceeded. |
| 57 | * |
| 58 | * @param from |
| 59 | * The element of the pipes and filters structure sending data |
| 60 | * through this connection. |
| 61 | * @param to |
| 62 | * The element of the pipes and filters structure receiving data |
| 63 | * through this connection. |
| 64 | * @throws PipesAndFiltersException |
| 65 | */ |
| 66 | public void addConnection(PipeElement from, PipeElement to) |
| 67 | throws PipesAndFiltersException { |
| 68 | if (elements.contains(from) && elements.contains(to)) { |
| 69 | if (from.outDegree + 1 > from.MAX_OUT_DEGREE) { |
| 70 | throw new PipesAndFiltersException( |
| 71 | "Elements cannot be connected because the element \"from\" has reached maximum number of outputs."); |
| 72 | } else if (to.inDegree + 1 > to.MAX_IN_DEGREE) { |
| 73 | throw new PipesAndFiltersException( |
| 74 | "Elements cannot be connected because the element \"to\" has reached maximum number of inputs."); |
| 75 | } else { |
| 76 | from.outDegree++; |
| 77 | to.inDegree++; |
| 78 | from.addObserver(to); |
| 79 | } |
| 80 | } else { |
| 81 | throw new RuntimeException( |
| 82 | "At least one element has not been added to the Manager."); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Sets the start element of the pipes and filters structure, i.e. the |
| 88 | * element the processed data is directly passed to. |
| 89 | * |
| 90 | * @param e |
| 91 | * The new start element of the pipes and filters structure. |
| 92 | */ |
| 93 | public void setStartElement(PipeElement e) { |
| 94 | if (elements.contains(e)) { |
| 95 | this.startElement = e; |
| 96 | } else { |
| 97 | throw new RuntimeException( |
| 98 | "Element has not been added to the Manager."); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Returns the start element of the filter chain. |
| 104 | * |
| 105 | * @return The start element of the pipes and filters structure. |
| 106 | */ |
| 107 | public PipeElement getStartElement() { |
| 108 | return startElement; |
| 109 | } |
| 110 | |
| 111 | /** |
| 112 | * Initializes all pipe elements |
| 113 | * |
| 114 | * @param metaData |
| 115 | * The initializing meta data |
| 116 | */ |
| 117 | public void initialize(MetaDataInit metaData) { |
| 118 | for (PipeElement e : elements) { |
| 119 | e.initialize(metaData); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * Injects data into the pipes and filters structure. The data is passed to |
| 125 | * the start element. |
| 126 | * |
| 127 | * @param data |
| 128 | * The data to be processed by the pipes and filters. |
| 129 | */ |
| 130 | public void processData(PipeData data) { |
| 131 | startElement.processData(data); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Tells all pipe elements to stop operating data. |
| 136 | */ |
| 137 | public void flush() { |
| 138 | startElement.flush(); |
| 139 | } |
| 140 | |
| 141 | } |