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