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 | } |