The provider module for the Arris designed APIs.
[packetcable.git] / packetcable-policy-server / src / main / java / org / opendaylight / controller / packetcable / provider / ValidateInstanceData.java
1 /**
2  * Validate all instance data received from the config datastore via the onDataChange() notification.
3  *
4  * N.B. that yang typedefs are not validated when a PUT operation places them into the config datastore.
5  * This means that they can arrive at onDataChange() with invalid values.
6  *
7  * In particular integer range values and string patterns (such as IP prefix/len) are not checked
8  * and accessing these values via any object.getValue() method call will cause an exception (as yang
9  * finally gets around to actually enforcing the typedef).
10  */
11 package org.opendaylight.controller.packetcable.provider;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
15 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
16 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
17 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
18 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
19 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsBuilder;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
22 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmIdBuilder;
23 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
24 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.ConnectionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
26 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.ClassifierBuilder;
27 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifier;
28 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifierBuilder;
29 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
30 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpecBuilder;
31 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
32 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesBuilder;
33 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6Classifier;
34 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6ClassifierBuilder;
35 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
36 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfileBuilder;
37 import org.opendaylight.yangtools.yang.binding.DataObject;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import java.lang.reflect.Method;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.concurrent.ConcurrentHashMap;
46 import java.util.concurrent.ExecutorService;
47 import java.util.concurrent.Executors;
48
49 public class ValidateInstanceData {
50
51         private final static Logger logger = LoggerFactory.getLogger(ValidateInstanceData.class);
52
53         // Final members
54         private final DataBroker dataBroker;
55         private final ExecutorService executor;
56
57         // Gate Identities
58         private final Map<InstanceIdentifier<Gates>, Gates> gateIidMap;
59
60         // CCAP Identity
61         private transient Ccaps ccap;
62         private transient InstanceIdentifier<Ccaps> ccapIID;
63
64         public ValidateInstanceData(final DataBroker dataBroker, final Map<InstanceIdentifier<?>, DataObject> thisData) {
65                 executor = Executors.newCachedThreadPool();
66                 this.dataBroker = dataBroker;
67                 getCcap(thisData);
68                 // TODO FIXME - this value is always null???
69                 if (ccap == null) {
70                         getGates(thisData);
71                 }
72                 gateIidMap = new ConcurrentHashMap<>();
73         }
74         public boolean isResponseEcho() {
75                 // see if there is a response object in the updated data
76                 // if so this is an echo of the response message insertion so our caller can exit right away
77                 if (ccap != null && ccap.getResponse() != null) {
78                         return true;
79                 } else if (! gateIidMap.isEmpty() && gateIidMap.values().iterator().next().getResponse() != null) {
80                         return true;
81                 }
82                 return false;
83         }
84         public boolean validateYang() {
85                 final String badText = "400 Bad Request - Invalid Element Values in json object - ";
86                 if (isResponseEcho()) {
87                         // don't validiate the echo again
88                         return true;
89                 }
90                 if (ccap != null) {
91                         Response response = new Response(dataBroker, ccapIID, ccap, badText);
92                         if (! validateCcap(ccap, response)) {
93                                 logger.error("Validate CCAP {} failed - {}", ccap.getCcapId(), response.getMessage());
94                                 executor.execute(response);
95                                 return false;
96                         }
97                 } else if (! gateIidMap.isEmpty()) {
98                         for (Map.Entry<InstanceIdentifier<Gates>, Gates> entry : gateIidMap.entrySet()) {
99                                 InstanceIdentifier<Gates> gateIID = entry.getKey();
100                                 Gates gate = entry.getValue();
101                                 Response response = new Response(dataBroker, gateIID, gate, badText);
102                                 if (! validateGate(gate, response)) {
103                                         logger.error("Validate Gate {} failed - {}", gate.getGateId(), response.getMessage());
104                                         executor.execute(response);
105                                         return false;
106                                 }
107                         }
108                 }
109                 return true;
110         }
111
112         private void getCcap(final Map<InstanceIdentifier<?>, DataObject> thisData) {
113                 for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
114                         if (entry.getValue() instanceof Ccaps) {
115                     ccap = (Ccaps)entry.getValue();
116                                 // TODO FIXME - ClassCastException waiting to occur here!!!
117                     ccapIID = (InstanceIdentifier<Ccaps>) entry.getKey();
118                 }
119             }
120         }
121
122         private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
123                 for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
124                         if (entry.getValue() instanceof Gates) {
125                                 final Gates gate = (Gates)entry.getValue();
126                                 // TODO FIXME - ClassCastException waiting to occur here!!!
127                                 final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
128                                 gateIidMap.put(gateIID, gate);
129                         }
130             }
131         }
132         private String validateMethod(final Class<?> thisClass, final Object thisObj, final String methodName) {
133                 try {
134                         final Method method = thisClass.getMethod(methodName);
135                         method.invoke(thisObj);
136                 } catch (IllegalArgumentException e) {
137                         return e.getMessage();
138                 } catch (Exception e) {
139                         return " ";
140 //                      error = String.format("%s.%s(): Method failed: %s ", thisClass.getSimpleName(), methodName, e.getMessage());
141                 }
142                 return null;
143         }
144
145         private boolean validateGateSpec(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
146                 // gate-spec
147                 String message = "";
148                 String error;
149                 boolean valid = true;
150                 GateSpec gateSpec = gate.getGateSpec();
151                 if (gateSpec != null) {
152                         final ServiceFlowDirection dir;
153                         error = validateMethod(GateSpec.class, gateSpec, "getDirection");
154                         if (error == null) {
155                                 dir = gateSpec.getDirection();
156                                 if (dir != null) {
157                                         if (gate.getTrafficProfile().getServiceClassName() != null) {
158                                                 message += " gate-spec.direction not allowed for traffic-profile.SCN;";
159                                                 valid = false;
160                                         }
161                                 }
162                         } else {
163                                 message += " gate-spec.direction invalid: must be 'us' or 'ds' -" + error;
164                                 dir = null;
165                                 valid = false;
166                         }
167                         final TosByte tosByte;
168                         error = validateMethod(GateSpec.class, gateSpec, "getDscpTosOverwrite");
169                         if (error == null) {
170                                 tosByte = gateSpec.getDscpTosOverwrite();
171                         } else {
172                                 message += " gate-spec.dscp-tos-overwrite invalid: " + error;
173                                 tosByte = null;
174                                 valid = false;
175                         }
176                         final TosByte tosMask;
177                         error = validateMethod(GateSpec.class, gateSpec, "getDscpTosMask");
178                         if (error == null) {
179                                 tosMask = gateSpec.getDscpTosMask();
180                                 if (tosByte != null && tosMask == null) {
181                                         message += " gate-spec.dscp-tos-mask missing;";
182                                         valid = false;
183                                 }
184                         } else {
185                                 message += " gate-spec.dscp-tos-mask invalid: " + error;
186                                 tosMask = null;
187                                 valid = false;
188                         }
189                         if (! valid) {
190                                 // rebuild the gateSpec with nulls replacing bad values
191                                 final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
192                                 gateSpecBuilder.setDirection(dir);
193                                 gateSpecBuilder.setDscpTosOverwrite(tosByte);
194                                 gateSpecBuilder.setDscpTosMask(tosMask);
195                                 gateSpec = gateSpecBuilder.build();
196                                 // update the gate
197                                 gateBuilder.setGateSpec(gateSpec);
198                         }
199                 }
200                 if (! valid) {
201                         response.addMessage(message);
202                 }
203                 return valid;
204         }
205
206         private boolean validateTrafficProfile(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
207                 // traffic-profile
208                 String message = "";
209                 boolean valid = true;
210                 TrafficProfile profile = gate.getTrafficProfile();
211                 if (profile == null) {
212                         message += " traffic-profile is required;";
213                         valid = false;
214                 } else {
215                         final ServiceClassName scn;
216                         final String error = validateMethod(TrafficProfile.class, profile, "getServiceClassName");
217                         if (error == null) {
218                                 scn = profile.getServiceClassName();
219                                 if (scn == null) {
220                                         message += " traffic-profile.service-class-name missing;";
221                                         valid = false;
222                                 }
223                         } else {
224                                 message += " traffic-profile.service-class-name invalid: must be 2-16 characters " + error;
225                                 scn = null;
226                                 valid = false;
227                         }
228                         if (! valid) {
229                                 final TrafficProfileBuilder profileBuilder = new TrafficProfileBuilder();
230                                 // TODO FIXME - scn is always null???
231                                 profileBuilder.setServiceClassName(scn);
232                                 profile = profileBuilder.build();
233                                 // update the gate
234                                 gateBuilder.setTrafficProfile(profile);
235                         }
236                 }
237                 if (! valid) {
238                         response.addMessage(message);
239                 }
240                 return valid;
241         }
242
243         // TODO FIXME - Break this method apart
244         private boolean validateClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
245                 // validate classifier
246                 String message = "";
247                 boolean valid = true;
248                 int count = 0;
249                 Classifier classifier = gate.getClassifier();
250                 // SIP
251                 final Ipv4Address sip;
252                 String error = validateMethod(Classifier.class, classifier, "getSrcIp");
253                 if (error == null) {
254                         sip = classifier.getSrcIp();
255                         count++;
256                 } else {
257                         message += " classifier.srcIp invalid: - " + error;
258                         sip = null;
259                         valid = false;
260                 }
261                 // DIP
262                 final Ipv4Address dip;
263                 error = validateMethod(Classifier.class, classifier, "getDstIp");
264                 if (error == null) {
265                         dip = classifier.getDstIp();
266                         count++;
267                 } else {
268                         message += " classifier.dstIp invalid: - " + error;
269                         dip = null;
270                         valid = false;
271                 }
272                 // Protocol
273                 final TpProtocol proto;
274                 error = validateMethod(Classifier.class, classifier, "getProtocol");
275                 if (error == null) {
276                         proto = classifier.getProtocol();
277                         count++;
278                 } else {
279                         message += " classifier.protocol invalid: - " + error;
280                         proto = null;
281                         valid = false;
282                 }
283                 // Source Port
284                 final PortNumber sport;
285                 error = validateMethod(Classifier.class, classifier, "getSrcPort");
286                 if (error == null) {
287                         sport = classifier.getSrcPort();
288                         count++;
289                 } else {
290                         message += " classifier.srcPort invalid: - " + error;
291                         sport = null;
292                         valid = false;
293                 }
294                 // Destination Port
295                 final PortNumber dport;
296                 error = validateMethod(Classifier.class, classifier, "getDstPort");
297                 if (error == null) {
298                         dport = classifier.getDstPort();
299                         count++;
300                 } else {
301                         message += " classifier.dstPort invalid: - " + error;
302                         dport = null;
303                         valid = false;
304                 }
305                 // TOS
306                 final TosByte tosByte;
307                 error = validateMethod(Classifier.class, classifier, "getTosByte");
308                 if (error == null) {
309                         tosByte = classifier.getTosByte();
310                         count++;
311                 } else {
312                         message += " classifier.tosByte invalid: " + error;
313                         tosByte = null;
314                         valid = false;
315                 }
316                 final TosByte tosMask;
317                 error = validateMethod(Classifier.class, classifier, "getTosMask");
318                 if (error == null) {
319                         tosMask = classifier.getTosMask();
320                         if (tosByte != null && tosMask == null) {
321                                 message += " classifier.tosMask missing;";
322                                 valid = false;
323                         }
324                 } else {
325                         message += " classifier.tosMask invalid: " + error;
326                         tosMask = null;
327                         valid = false;
328                 }
329                 if (count == 0) {
330                         message += " classifer must have at least one match field";
331                         valid = false;
332                 }
333                 if (! valid) {
334                         final ClassifierBuilder cBuilder = new ClassifierBuilder();
335                         cBuilder.setSrcIp(sip);
336                         cBuilder.setDstIp(dip);
337                         cBuilder.setProtocol(proto);
338                         cBuilder.setSrcPort(sport);
339                         cBuilder.setDstPort(dport);
340                         cBuilder.setTosByte(tosByte);
341                         cBuilder.setTosMask(tosMask);
342                         classifier = cBuilder.build();
343                         gateBuilder.setClassifier(classifier);
344                         response.addMessage(message);
345                 }
346                 return valid;
347         }
348
349         // TODO FIXME - breakup this method
350         private boolean validateExtClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
351                 // validate ext-classifier
352                 String message = "";
353                 String error;
354                 boolean valid = true;
355                 int count = 0;
356                 ExtClassifier extClassifier = gate.getExtClassifier();
357                 // SIP & mask
358                 final Ipv4Address sip;
359                 error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIp");
360                 if (error == null) {
361                         sip = extClassifier.getSrcIp();
362                         count++;
363                 } else {
364                         message += " ext-classifier.srcIp invalid: - " + error;
365                         sip = null;
366                         valid = false;
367                 }
368                 final Ipv4Address sipMask;
369                 error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIpMask");
370                 if (error == null) {
371                         sipMask = extClassifier.getSrcIpMask();
372                         count++;
373                 } else {
374                         message += " ext-classifier.srcIpMask invalid: - " + error;
375                         sipMask = null;
376                         valid = false;
377                 }
378                 if (sip != null && sipMask == null) {
379                         message += " ext-classifier.srcIpMask missing";
380                         valid = false;
381                 }
382                 // DIP & mask
383                 final Ipv4Address dip;
384                 error = validateMethod(ExtClassifier.class, extClassifier, "getDstIp");
385                 if (error == null) {
386                         dip = extClassifier.getDstIp();
387                         count++;
388                 } else {
389                         message += " ext-classifier.dstIp invalid: - " + error;
390                         dip = null;
391                         valid = false;
392                 }
393                 final Ipv4Address dipMask;
394                 error = validateMethod(ExtClassifier.class, extClassifier, "getDstIpMask");
395                 if (error == null) {
396                         dipMask = extClassifier.getDstIpMask();
397                         count++;
398                 } else {
399                         message += " ext-classifier.srcIpMask invalid: - " + error;
400                         dipMask = null;
401                         valid = false;
402                 }
403                 if (dip != null && dipMask == null) {
404                         message += " ext-classifier.dstIpMask missing;";
405                         valid = false;
406                 }
407                 // Protocol
408                 final TpProtocol proto;
409                 error = validateMethod(ExtClassifier.class, extClassifier, "getProtocol");
410                 if (error == null) {
411                         proto = extClassifier.getProtocol();
412                         count++;
413                 } else {
414                         message += " ext-classifier.protocol invalid: - " + error;
415                         proto = null;
416                         valid = false;
417                 }
418                 // Source port range
419                 final PortNumber sportStart;
420                 error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortStart");
421                 if (error == null) {
422                         sportStart = extClassifier.getSrcPortStart();
423                         count++;
424                 } else {
425                         message += " ext-classifier.srcPortStart invalid: - " + error;
426                         sportStart = null;
427                         valid = false;
428                 }
429                 final PortNumber sportEnd;
430                 error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortEnd");
431                 if (error == null) {
432                         sportEnd = extClassifier.getSrcPortEnd();
433                         count++;
434                 } else {
435                         message += " ext-classifier.srcPortEnd invalid: - " + error;
436                         sportEnd = null;
437                         valid = false;
438                 }
439                 if (sportStart != null && sportEnd != null) {
440                         if (sportStart.getValue() > sportEnd.getValue()) {
441                                 message += " ext-classifier.srcPortStart greater than srcPortEnd";
442                                 valid = false;
443                         }
444                 }
445                 // Destination port range
446                 final PortNumber dportStart;
447                 error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortStart");
448                 if (error == null) {
449                         dportStart = extClassifier.getDstPortStart();
450                         count++;
451                 } else {
452                         message += " ext-classifier.dstPortStart invalid: - " + error;
453                         dportStart = null;
454                         valid = false;
455                 }
456                 final PortNumber dportEnd;
457                 error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortEnd");
458                 if (error == null) {
459                         dportEnd = extClassifier.getDstPortEnd();
460                         count++;
461                 } else {
462                         message += " ext-classifier.dstPortEnd invalid: - " + error;
463                         dportEnd = null;
464                         valid = false;
465                 }
466                 if (dportStart != null && dportEnd != null) {
467                         if (dportStart.getValue() > dportEnd.getValue()) {
468                                 message += " ext-classifier.dstPortStart greater than dstPortEnd";
469                                 valid = false;
470                         }
471                 }
472                 // TOS byte
473                 final TosByte tosByte;
474                 error = validateMethod(ExtClassifier.class, extClassifier, "getTosByte");
475                 if (error == null) {
476                         tosByte = extClassifier.getTosByte();
477                         count++;
478                 } else {
479                         message += " ext-classifier.tosByte invalid: " + error;
480                         tosByte = null;
481                         valid = false;
482                 }
483                 final TosByte tosMask;
484                 error = validateMethod(ExtClassifier.class, extClassifier, "getTosMask");
485                 if (error == null) {
486                         tosMask = extClassifier.getTosMask();
487                         if (tosByte != null && tosMask == null) {
488                                 message += " ext-classifier.tosMask missing;";
489                                 valid = false;
490                         }
491                 } else {
492                         message += " ext-classifier.tosMask invalid: " + error;
493                         tosMask = null;
494                         valid = false;
495                 }
496                 if (count == 0) {
497                         message += " ext-classifer must have at least one match field";
498                         valid = false;
499                 }
500                 if (! valid) {
501                         final ExtClassifierBuilder cBuilder = new ExtClassifierBuilder();
502                         cBuilder.setSrcIp(sip);
503                         cBuilder.setSrcIpMask(sipMask);
504                         cBuilder.setDstIp(dip);
505                         cBuilder.setDstIpMask(dipMask);
506                         cBuilder.setProtocol(proto);
507                         cBuilder.setSrcPortStart(sportStart);
508                         cBuilder.setSrcPortEnd(sportEnd);
509                         cBuilder.setDstPortStart(dportStart);
510                         cBuilder.setDstPortEnd(dportEnd);
511                         cBuilder.setTosByte(tosByte);
512                         cBuilder.setTosMask(tosMask);
513                         extClassifier = cBuilder.build();
514                         gateBuilder.setExtClassifier(extClassifier);
515                         response.addMessage(message);
516                 }
517                 return valid;
518         }
519
520         // TODO FIXME - break apart this method.
521         private boolean validateIpv6Classifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
522                 // validate ipv6-classifier
523                 String message = "";
524                 String error;
525                 boolean valid = true;
526                 int count = 0;
527                 Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
528                 // Source IPv6 prefix
529                 final Ipv6Prefix sip6;
530                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcIp6");
531                 if (error == null) {
532                         sip6 = ipv6Classifier.getSrcIp6();
533                         count++;
534                 } else {
535                         message += " ipv6-classifier.srcIp invalid: - " + error;
536                         sip6 = null;
537                         valid = false;
538                 }
539                 // Destination IPv6 prefix
540                 final Ipv6Prefix dip6;
541                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstIp6");
542                 if (error == null) {
543                         dip6 = ipv6Classifier.getDstIp6();
544                         count++;
545                 } else {
546                         message += " ipv6-classifier.dstIp invalid: - " + error;
547                         dip6 = null;
548                         valid = false;
549                 }
550                 // Flow label
551                 Long flowLabel;
552                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getFlowLabel");
553                 if (error == null) {
554                         flowLabel = ipv6Classifier.getFlowLabel();
555                         if (flowLabel > 1048575) {
556                                 message += " ipv6-classifier.flowLabel invalid: - must be 0..1048575";
557                                 flowLabel = null;
558                                 valid = false;
559                         } else {
560                                 count++;
561                         }
562                 } else {
563                         message += " ipv6-classifier.flowLabel invalid: - " + error;
564                         flowLabel = null;
565                         valid = false;
566                 }
567                 // Next Hdr
568                 final TpProtocol nxtHdr;
569                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getNextHdr");
570                 if (error == null) {
571                         nxtHdr = ipv6Classifier.getNextHdr();
572                         count++;
573                 } else {
574                         message += " ipv6-classifier.nextHdr invalid: - " + error;
575                         nxtHdr = null;
576                         valid = false;
577                 }
578                 // Source port range
579                 final PortNumber sportStart;
580                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortStart");
581                 if (error == null) {
582                         sportStart = ipv6Classifier.getSrcPortStart();
583                         count++;
584                 } else {
585                         message += " ipv6-classifier.srcPortStart invalid: - " + error;
586                         sportStart = null;
587                         valid = false;
588                 }
589                 final PortNumber sportEnd;
590                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortEnd");
591                 if (error == null) {
592                         sportEnd = ipv6Classifier.getSrcPortEnd();
593                         count++;
594                 } else {
595                         message += " ipv6-classifier.srcPortEnd invalid: - " + error;
596                         sportEnd = null;
597                         valid = false;
598                 }
599                 if (sportStart != null && sportEnd != null) {
600                         if (sportStart.getValue() > sportEnd.getValue()) {
601                                 message += " ipv6-classifier.srcPortStart greater than srcPortEnd";
602                                 valid = false;
603                         }
604                 }
605                 // Destination port range
606                 final PortNumber dportStart;
607                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortStart");
608                 if (error == null) {
609                         dportStart = ipv6Classifier.getDstPortStart();
610                         count++;
611                 } else {
612                         message += " ipv6-classifier.dstPortStart invalid: - " + error;
613                         dportStart = null;
614                         valid = false;
615                 }
616                 final PortNumber dportEnd;
617                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortEnd");
618                 if (error == null) {
619                         dportEnd = ipv6Classifier.getDstPortEnd();
620                         count++;
621                 } else {
622                         message += " ipv6-classifier.dstPortEnd invalid: - " + error;
623                         dportEnd = null;
624                         valid = false;
625                 }
626                 if (dportStart != null && dportEnd != null) {
627                         if (dportStart.getValue() > dportEnd.getValue()) {
628                                 message += " ipv6-classifier.dstPortStart greater than dstPortEnd";
629                                 valid = false;
630                         }
631                 }
632                 // TC byte
633                 final TosByte tcLow;
634                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcLow");
635                 if (error == null) {
636                         tcLow = ipv6Classifier.getTcLow();
637                         count++;
638                 } else {
639                         message += " ipv6-classifier.tc-low invalid: " + error;
640                         tcLow = null;
641                         valid = false;
642                 }
643                 final TosByte tcHigh;
644                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcHigh");
645                 if (error == null) {
646                         tcHigh = ipv6Classifier.getTcHigh();
647                         count++;
648                 } else {
649                         message += " ipv6-classifier.tc-high invalid: " + error;
650                         tcHigh = null;
651                         valid = false;
652                 }
653                 if (tcLow != null && tcHigh != null) {
654                         if (tcLow.getValue() > tcHigh.getValue()) {
655                                 message += " ipv6-classifier.tc-low is greater than tc-high";
656                                 valid = false;
657                         }
658                 }
659                 final TosByte tcMask;
660                 error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcMask");
661                 if (error == null) {
662                         tcMask = ipv6Classifier.getTcMask();
663                 } else {
664                         message += " ipv6-classifier.tc-mask invalid: " + error;
665                         tcMask = null;
666                         valid = false;
667                 }
668                 if (tcLow != null && tcHigh != null && tcMask == null) {
669                         message += " ipv6-classifier.tc-mask missing;";
670                         valid = false;
671                 }
672                 if (count == 0) {
673                         message += " ipv6-classifer must have at least one match field";
674                         valid = false;
675                 }
676                 // rebuild ?
677                 if (! valid) {
678                         final Ipv6ClassifierBuilder cBuilder = new Ipv6ClassifierBuilder();
679                         cBuilder.setSrcIp6(sip6);
680                         cBuilder.setDstIp6(dip6);
681                         cBuilder.setFlowLabel(flowLabel);
682                         cBuilder.setNextHdr(nxtHdr);
683                         cBuilder.setSrcPortStart(sportStart);
684                         cBuilder.setSrcPortEnd(sportEnd);
685                         cBuilder.setDstPortStart(dportStart);
686                         cBuilder.setDstPortEnd(dportEnd);
687                         cBuilder.setTcLow(tcLow);
688                         cBuilder.setTcHigh(tcHigh);
689                         cBuilder.setTcMask(tcMask);
690                         ipv6Classifier = cBuilder.build();
691                         gateBuilder.setIpv6Classifier(ipv6Classifier);
692                         response.addMessage(message);
693                 }
694                 return valid;
695         }
696
697         // TODO FIXME - Do we really want the gate parameter object to be muted by this method?
698         private boolean validateGate(Gates gate, final Response response) {
699                 // validate gate elements and null out invalid elements as we go
700                 final GatesBuilder gateBuilder = new GatesBuilder();
701                 String message = "";
702                 boolean rebuild = false;
703                 // gate-spec
704                 if (! validateGateSpec(gate, gateBuilder, response)) {
705                         rebuild = true;
706                 }
707                 // traffic-profile
708                 if (! validateTrafficProfile(gate, gateBuilder, response)) {
709                         rebuild = true;
710                 }
711                 // classifiers (one of legacy classifier, ext-classifier, or ipv6 classifier
712                 final Classifier classifier = gate.getClassifier();
713                 final ExtClassifier extClassifier = gate.getExtClassifier();
714                 final Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
715                 int count = 0;
716                 if (classifier != null) { count++; }
717                 if (extClassifier != null) { count++; }
718                 if (ipv6Classifier != null) { count++; }
719                 if (count < 1){
720                         response.addMessage(" Missing classifer: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
721                         rebuild = true;
722                 } else if (count > 1) {
723                         response.addMessage(" Multiple classifiers: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
724                         rebuild = true;
725                 } else if (count == 1) {
726                         if (classifier != null) {
727                                 // validate classifier
728                                 if (! validateClassifier(gate, gateBuilder, response)) {
729                                         rebuild = true;
730                                 }
731                         } else if (extClassifier != null) {
732                                 //validate ext-classifier
733                                 if (! validateExtClassifier(gate, gateBuilder, response)) {
734                                         rebuild = true;
735                                 }
736                         } else if (ipv6Classifier != null) {
737                                 // TODO FIXME - ipv6Classifier is always null???
738                                 // validate ipv6-classifier
739                                 if (! validateIpv6Classifier(gate, gateBuilder, response)) {
740                                         rebuild = true;
741                                 }
742                         }
743                 }
744                 // rebuild the gate object with valid data and set the response
745                 if (rebuild) {
746                         gateBuilder.setGateId(gate.getGateId());
747                         gateBuilder.setKey(gate.getKey());
748                         // TODO FIXME - the input parameter "gate" is being muted here???
749                         gate = gateBuilder.build();
750                         response.setGateBase(gate);
751                         response.addMessage(message);
752                 }
753                 return (! rebuild);
754         }
755
756         private boolean validateAmId(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
757                 // amId
758                 String message = "";
759                 String error;
760                 boolean valid = true;
761                 AmId amId = ccap.getAmId();
762                 if (amId == null) {
763                         message += " amId is required;";
764                         valid = false;
765                 } else {
766                         final Integer amTag;
767                         error = validateMethod(AmId.class, amId, "getAmTag");
768                         if (error == null) {
769                                 amTag = amId.getAmTag();
770                                 if (amTag == null) {
771                                         message += " amId.amTag missing;";
772                                         valid = false;
773                                 }
774                         } else {
775                                 message += " amId.amTag invalid: " + error;
776                                 amTag = null;
777                                 valid = false;
778                         }
779                         final Integer amType;
780                         error = validateMethod(AmId.class, amId, "getAmType");
781                         if (error == null) {
782                                 amType = amId.getAmType();
783                                 if (amType == null) {
784                                         message += " amId.amType missing;";
785                                         valid = false;
786                                 }
787                         } else {
788                                 message += " amId.amType invalid: " + error;
789                                 amType = null;
790                                 valid = false;
791                         }
792                         if (! valid) {
793                                 final AmIdBuilder amIdBuilder = new AmIdBuilder();
794                                 amIdBuilder.setAmTag(amTag);
795                                 amIdBuilder.setAmType(amType);
796                                 amId = amIdBuilder.build();
797                                 ccapBuilder.setAmId(amId);
798                         }
799                 }
800                 if (! valid) {
801                         response.addMessage(message);
802                 }
803                 return valid;
804         }
805
806         private boolean validateConnection(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
807                 // connection
808                 String message = "";
809                 String error;
810                 boolean valid = true;
811                 Connection conn = ccap.getConnection();
812                 if (conn == null) {
813                         message += " connection is required;";
814                         valid = false;
815                 } else {
816                         // IP address
817                         final IpAddress ipAddress;
818                         error = validateMethod(Connection.class, conn, "getIpAddress");
819                         if (error == null) {
820                                 ipAddress = conn.getIpAddress();
821                                 if (ipAddress == null) {
822                                         message += " connection.ipAddress missing;";
823                                         valid = false;
824                                 }
825                         } else {
826                                 message += " connection.ipAddress invalid: " + error;
827                                 ipAddress = null;
828                                 valid = false;
829                         }
830                         // Port number
831                         final PortNumber portNum;
832                         error = validateMethod(Connection.class, conn, "getPort");
833                         if (error == null) {
834                                 portNum = conn.getPort();
835                         } else {
836                                 message += " connection.port invalid: " + error;
837                                 portNum = null;
838                                 valid = false;
839                         }
840                         if (! valid) {
841                                 final ConnectionBuilder connBuilder = new ConnectionBuilder();
842                                 connBuilder.setIpAddress(ipAddress);
843                                 connBuilder.setPort(portNum);
844                                 conn = connBuilder.build();
845                                 ccapBuilder.setConnection(conn);
846                         }
847                 }
848                 if (! valid) {
849                         response.addMessage(message);
850                 }
851                 return valid;
852         }
853
854         private boolean validateSubscriberSubnets(final Ccaps ccap, final CcapsBuilder ccapBuilder,
855                                                                                           final Response response) {
856                 // subscriber-subnets
857                 String message = "";
858                 String error;
859                 boolean valid = true;
860                 List<IpPrefix> subnets = null;
861                 error = validateMethod(Ccaps.class, ccap, "getSubscriberSubnets");
862                 if (error == null) {
863                         subnets = ccap.getSubscriberSubnets();
864                         if (subnets == null) {
865                                 message += " subscriber-subnets is required;";
866                                 valid = false;
867                         }
868                 } else {
869                         message += " subscriber-subnets contains invalid IpPrefix - must be <ipaddress>/<prefixlen> format;" + error;
870                         valid = false;
871                 }
872                 if (! valid) {
873                         // TODO FIXME - subnets is always null???
874                         ccapBuilder.setSubscriberSubnets(subnets);
875                         response.addMessage(message);
876                 }
877                 return valid;
878         }
879
880         private boolean validateUpstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
881                 // upstream-scns
882                 String message = "";
883                 String error;
884                 boolean valid = true;
885                 List<ServiceClassName> usScns = null;
886                 error = validateMethod(Ccaps.class, ccap, "getUpstreamScns");
887                 if (error == null) {
888                         usScns = ccap.getUpstreamScns();
889                         if (usScns == null) {
890                                 message += " upstream-scns is required;";
891                                 valid = false;
892                         }
893                 } else {
894                         message += " upstream-scns contains invalid SCN - must be 2-16 characters;" + error;
895                         valid = false;
896                 }
897                 if (! valid) {
898                         // TODO FIXME - usScns is always null???
899                         ccapBuilder.setUpstreamScns(usScns);
900                         response.addMessage(message);
901                 }
902                 return valid;
903         }
904
905         private boolean validateDownstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
906                 // downstream-scns
907                 String message = "";
908                 boolean valid = true;
909                 List<ServiceClassName> dsScns = null;
910                 final String error = validateMethod(Ccaps.class, ccap, "getDownstreamScns");
911                 if (error == null) {
912                         dsScns = ccap.getDownstreamScns();
913                         if (dsScns == null) {
914                                 message += " downstream-scns is required;";
915                                 valid = false;
916                         }
917                 } else {
918                         message += " downstream-scns contains invalid SCN - must be 2-16 characters;" + error;
919                         valid = false;
920                 }
921                 if (! valid) {
922                         // TODO FIXME - dsScns is always null???
923                         ccapBuilder.setDownstreamScns(dsScns);
924                         response.addMessage(message);
925                 }
926                 return valid;
927         }
928
929
930         // TODO FIXME - Do we really want the ccap parameter object to be muted by this method?
931         private boolean validateCcap(Ccaps ccap, final Response response) {
932                 // validate ccap and null out invalid elements as we go
933                 final CcapsBuilder ccapBuilder = new CcapsBuilder();
934                 String message = "";
935                 boolean rebuild = false;
936                 // amId
937                 if ( ! validateAmId(ccap, ccapBuilder, response))        {
938                         rebuild = true;
939                 }
940                 // connection
941                 if ( ! validateConnection(ccap, ccapBuilder, response))        {
942                         rebuild = true;
943                 }
944                 // subscriber-subnets
945                 if ( ! validateSubscriberSubnets(ccap, ccapBuilder, response))        {
946                         rebuild = true;
947                 }
948                 // upstream-scns
949                 if ( ! validateUpstreamScns(ccap, ccapBuilder, response))        {
950                         rebuild = true;
951                 }
952                 // downstream-scns
953                 if ( ! validateDownstreamScns(ccap, ccapBuilder, response))        {
954                         rebuild = true;
955                 }
956                 // rebuild the ccap object with valid data and set the response
957                 if (rebuild) {
958                         ccapBuilder.setCcapId(ccap.getCcapId());
959                         ccapBuilder.setKey(ccap.getKey());
960                         // TODO FIXME - the input parameter "ccap" is being muted here???
961                         ccap = ccapBuilder.build();
962                         response.setCcapBase(ccap);
963                         response.addMessage(message);
964                 }
965                 return (! rebuild);
966         }
967 }
968