Merge "Start of the COPS message refactoring to make all of these classes more semant...
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / messages / impl / COPSDecisionMsgEX.java
1 /**
2  @header@
3  */
4 package org.pcmm.messages.impl;
5
6 import org.umu.cops.stack.*;
7
8 import java.io.IOException;
9 import java.io.OutputStream;
10 import java.net.Socket;
11 import java.util.Enumeration;
12 import java.util.Hashtable;
13 import java.util.Vector;
14
15 /**
16  * COPS Decision Message
17  *
18  *
19  */
20
21 public class COPSDecisionMsgEX extends COPSMsg {
22
23     /* COPSHeader coming from base class */
24     private COPSHandle _clientHandle;
25     private COPSError _error;
26     private Hashtable _decisions;
27     private COPSIntegrity _integrity;
28     private COPSContext _decContext;
29     private COPSClientSI clientSI;
30
31     // /
32     public COPSDecisionMsgEX() {
33         _clientHandle = null;
34         _error = null;
35         _decisions = new Hashtable(20);
36         _integrity = null;
37         _decContext = null;
38         clientSI = null;
39     }
40
41     /**
42      * Checks the sanity of COPS message and throw an COPSBadDataException when
43      * data is bad.
44      */
45     public void checkSanity() throws COPSException {
46         if ((_hdr == null) || (_clientHandle == null)
47                 || ((_error == null) && (_decisions.size() == 0))) {
48             throw new COPSException("Bad message format");
49         }
50     }
51
52     // /
53     protected COPSDecisionMsgEX(byte[] data) throws COPSException {
54         _decisions = new Hashtable(20);
55         _clientHandle = null;
56         _error = null;
57         _integrity = null;
58         _decContext = null;
59         clientSI = null;
60         parse(data);
61     }
62
63     /**
64      * Parses the data and fills COPSDecisionMsg with its constituents
65      *
66      * @param data
67      *            a byte[]
68      *
69      * @throws COPSException
70      *
71      */
72     protected void parse(byte[] data) throws COPSException {
73         super.parseHeader(data);
74
75         while (_dataStart < _dataLength) {
76             byte[] buf = new byte[data.length - _dataStart];
77             System.arraycopy(data, _dataStart, buf, 0, data.length - _dataStart);
78
79             COPSObjHeader objHdr = COPSObjHeader.parse(buf);
80             switch (objHdr.getCNum()) {
81                 case HANDLE:
82                     _clientHandle = new COPSHandle(buf) {
83                     };
84                     _dataStart += _clientHandle.getDataLength();
85                     break;
86                 case CONTEXT:
87                     // dec context
88                     _decContext = new COPSContext(buf) {
89                     };
90                     _dataStart += _decContext.getDataLength();
91                     break;
92                 case ERROR:
93                     _error = new COPSError(buf) {
94                     };
95                     _dataStart += _error.getDataLength();
96                     break;
97                 case DEC:
98                     COPSDecision decs = new COPSDecision(buf) {
99                     };
100                     _dataStart += decs.getDataLength();
101                     addDecision(decs, _decContext);
102                     break;
103                 case MSG_INTEGRITY:
104                     _integrity = new COPSIntegrity(buf);
105                     _dataStart += _integrity.getDataLength();
106                     break;
107                 case CSI:
108                     clientSI = new COPSClientSI(buf) {
109                     };
110                     _dataStart += clientSI.getDataLength();
111                     break;
112                 default:
113                     throw new COPSException(
114                         "Bad Message format, unknown object type");
115             }
116         }
117         checkSanity();
118     }
119
120     /**
121      * Parses the data and fills that follows the header hdr and fills
122      * COPSDecisionMsg
123      *
124      * @param hdr
125      *            a COPSHeader
126      * @param data
127      *            a byte[]
128      *
129      * @throws COPSException
130      *
131      */
132     protected void parse(COPSHeader hdr, byte[] data) throws COPSException {
133         _hdr = hdr;
134         parse(data);
135         setMsgLength();
136     }
137
138     /**
139      * Add message header
140      *
141      * @param hdr
142      *            a COPSHeader
143      *
144      * @throws COPSException
145      *
146      */
147     public void add(COPSHeader hdr) throws COPSException {
148         if (hdr == null)
149             throw new COPSException("Null Header");
150         if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)
151             throw new COPSException("Error Header (no COPS_OP_DEC)");
152         _hdr = hdr;
153         setMsgLength();
154     }
155
156     /**
157      * Add client handle to the message
158      *
159      * @param handle
160      *            a COPSHandle
161      *
162      * @throws COPSException
163      *
164      */
165     public void add(COPSHandle handle) throws COPSException {
166         if (handle == null)
167             throw new COPSException("Null Handle");
168         _clientHandle = handle;
169         setMsgLength();
170     }
171
172     /**
173      * Add an Error object
174      *
175      * @param error
176      *            a COPSError
177      *
178      * @throws COPSException
179      *
180      */
181     public void add(COPSError error) throws COPSException {
182         if (_decisions.size() != 0)
183             throw new COPSException("No null decisions");
184         if (_error != null)
185             throw new COPSException("No null error");
186         // Message integrity object should be the very last one
187         // If it is already added
188         if (_integrity != null)
189             throw new COPSException("No null integrity");
190         _error = error;
191         setMsgLength();
192     }
193
194     /**
195      * Add one or more local decision object for a given decision context the
196      * context is optional, if null all decision object are tided to message
197      * context
198      *
199      * @param decision
200      *            a COPSDecision
201      * @param context
202      *            a COPSContext
203      *
204      * @throws COPSException
205      *
206      */
207     public void addDecision(COPSDecision decision, COPSContext context)
208     throws COPSException {
209         // Either error or decision can be added
210         // If error is aleady there assert
211         if (_error != null)
212             throw new COPSException("No null error");
213
214         if (decision.isLocalDecision())
215             throw new COPSException("Is local decision");
216
217         Vector v = (Vector) _decisions.get(context);
218         if (v == null)
219             v = new Vector();
220
221         if (decision.isFlagSet()) {// Commented out as advised by Felix
222             // if (v.size() != 0)
223             // {
224             // Only one set of decision flags is allowed
225             // for each context
226             // throw new COPSException
227             // ("Bad Message format, only one set of decision flags is allowed.");
228             // }
229         } else {
230             if (v.size() == 0) {
231                 // The flags decision must precede any other
232                 // decision message, since the decision is not
233                 // flags throw exception
234                 throw new COPSException(
235                     "Bad Message format, flags decision must precede any other decision object.");
236             }
237         }
238         v.add(decision);
239         _decisions.put(context, v);
240
241         setMsgLength();
242     }
243
244     /**
245      * Add integrity object
246      *
247      * @param integrity
248      *            a COPSIntegrity
249      *
250      * @throws COPSException
251      *
252      */
253     public void add(COPSIntegrity integrity) throws COPSException {
254         if (integrity == null)
255             throw new COPSException("Null Integrity");
256         if (!integrity.isMessageIntegrity())
257             throw new COPSException("Error Integrity");
258         _integrity = integrity;
259         setMsgLength();
260     }
261
262     /**
263      * Add a client specific informations
264      *
265      * @param clientSI
266      *            a COPSClientSI
267      *
268      * @throws COPSException
269      *
270      */
271     public void add(COPSClientSI clientSI) throws COPSException {
272         if (clientSI == null)
273             throw new COPSException("Null ClientSI");
274         this.clientSI = clientSI;
275         setMsgLength();
276     }
277
278     /**
279      * Writes data to given socket
280      *
281      * @param id
282      *            a Socket
283      *
284      * @throws IOException
285      *
286      */
287     public void writeData(Socket id) throws IOException {
288         // checkSanity();
289         if (_hdr != null)
290             _hdr.writeData(id);
291         if (_clientHandle != null)
292             _clientHandle.writeData(id);
293         if (_error != null)
294             _error.writeData(id);
295
296         // Display decisions
297         // Display any local decisions
298         for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
299
300             COPSContext context = (COPSContext) e.nextElement();
301             Vector v = (Vector) _decisions.get(context);
302             context.writeData(id);
303
304             for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
305                 COPSDecision decision = (COPSDecision) ee.nextElement();
306                 decision.writeData(id);
307             }
308         }
309         if (clientSI != null)
310             clientSI.writeData(id);
311         if (_integrity != null)
312             _integrity.writeData(id);
313     }
314
315     /**
316      * Method getHeader
317      *
318      * @return a COPSHeader
319      *
320      */
321     public COPSHeader getHeader() {
322         return _hdr;
323     }
324
325     /**
326      * Method getClientHandle
327      *
328      * @return a COPSHandle
329      *
330      */
331     public COPSHandle getClientHandle() {
332         return _clientHandle;
333     }
334
335     public COPSClientSI getClientSI() {
336         return clientSI;
337     }
338
339     /**
340      * Returns true if it has error object
341      *
342      * @return a boolean
343      *
344      */
345     public boolean hasError() {
346         return (_error != null);
347     };
348
349     /**
350      * Should check hasError() before calling
351      *
352      * @return a COPSError
353      *
354      */
355     public COPSError getError() {
356         return _error;
357     };
358
359     /**
360      * Returns a map of decision for which is an arry of context and vector of
361      * associated decision object.
362      *
363      * @return a Hashtable
364      *
365      */
366     public Hashtable getDecisions() {
367         return _decisions;
368     };
369
370     /**
371      * Returns true if it has integrity object
372      *
373      * @return a boolean
374      *
375      */
376     public boolean hasIntegrity() {
377         return (_integrity != null);
378     };
379
380     /**
381      * Should check hasIntegrity() before calling
382      *
383      * @return a COPSIntegrity
384      *
385      */
386     public COPSIntegrity getIntegrity() {
387         return _integrity;
388     };
389
390     /**
391      * Method setMsgLength
392      *
393      * @throws COPSException
394      *
395      */
396     protected void setMsgLength() throws COPSException {
397         short len = 0;
398         if (_clientHandle != null)
399             len += _clientHandle.getDataLength();
400         if (_error != null)
401             len += _error.getDataLength();
402
403         // Display any local decisions
404         for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
405
406             COPSContext context = (COPSContext) e.nextElement();
407             Vector v = (Vector) _decisions.get(context);
408             len += context.getDataLength();
409
410             for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
411                 COPSDecision decision = (COPSDecision) ee.nextElement();
412                 len += decision.getDataLength();
413             }
414         }
415         if (clientSI != null)
416             len += clientSI.getDataLength();
417         if (_integrity != null) {
418             len += _integrity.getDataLength();
419         }
420
421         _hdr.setMsgLength((int) len);
422     }
423
424     /**
425      * Write an object textual description in the output stream
426      *
427      * @param os
428      *            an OutputStream
429      *
430      * @throws IOException
431      *
432      */
433     public void dump(OutputStream os) throws IOException {
434         _hdr.dump(os);
435
436         if (_clientHandle != null)
437             _clientHandle.dump(os);
438         if (_error != null)
439             _error.dump(os);
440
441         // Display any local decisions
442         for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
443
444             COPSContext context = (COPSContext) e.nextElement();
445             Vector v = (Vector) _decisions.get(context);
446             context.dump(os);
447
448             for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
449                 COPSDecision decision = (COPSDecision) ee.nextElement();
450                 decision.dump(os);
451             }
452         }
453         if (clientSI != null)
454             clientSI.dump(os);
455         if (_integrity != null) {
456             _integrity.dump(os);
457         }
458     }
459 }