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