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