Adding demo yang models and working on yang model packaging.

Change-Id: Ief674880920cf6165c863909298eb4fa6dd3fb64
diff --git a/apps/yang/src/main/java/org/onosproject/yang/AbstractYangModelRegistrator.java b/apps/yang/src/main/java/org/onosproject/yang/AbstractYangModelRegistrator.java
new file mode 100644
index 0000000..55e2a06
--- /dev/null
+++ b/apps/yang/src/main/java/org/onosproject/yang/AbstractYangModelRegistrator.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.yang.model.YangModel;
+import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
+import org.onosproject.yang.runtime.ModelRegistrationParam;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.getYangModel;
+
+/**
+ * Abstract base for self-registering YANG models.
+ */
+@Component
+public abstract class AbstractYangModelRegistrator {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final Class<?> loaderClass;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected YangModelRegistry modelRegistry;
+
+    private YangModel model;
+    private ModelRegistrationParam registrationParam;
+
+    /**
+     * Creates a model registrator primed with the class-loader of the specified
+     * class.
+     *
+     * @param loaderClass class whose class loader is to be used for locating schema data
+     */
+    protected AbstractYangModelRegistrator(Class<?> loaderClass) {
+        this.loaderClass = loaderClass;
+    }
+
+    @Activate
+    protected void activate() {
+        model = getYangModel(loaderClass);
+        registrationParam = DefaultModelRegistrationParam.builder()
+                .setYangModel(model).build();
+        modelRegistry.registerModel(registrationParam);
+        log.info("Started");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        modelRegistry.unregisterModel(registrationParam);
+        log.info("Stopped");
+    }
+}
diff --git a/buck-tools/BUCK b/buck-tools/BUCK
index afc1815..6d05f9e 100644
--- a/buck-tools/BUCK
+++ b/buck-tools/BUCK
@@ -41,3 +41,14 @@
   visibility = ['PUBLIC'],
 )
 
+export_file(
+  name = 'yang-registrator',
+  src = 'yang-registrator',
+  visibility = [ 'PUBLIC' ],
+)
+
+export_file(
+  name = 'yang-schema',
+  src = 'yang-schema',
+  visibility = [ 'PUBLIC' ],
+)
diff --git a/buck-tools/yang-registrator b/buck-tools/yang-registrator
new file mode 100755
index 0000000..56dc54a
--- /dev/null
+++ b/buck-tools/yang-registrator
@@ -0,0 +1,32 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Generates YANG Model registrator component.
+# -----------------------------------------------------------------------------
+
+output=$1
+package=$2
+shift 2
+
+aux=/tmp/yr-$$
+
+trap "rm -fr $aux" EXIT
+
+pkgDir=$aux/${package//./\/}
+rm -fr $aux $output
+mkdir -p $pkgDir
+cd $aux
+
+cat <<EOF >$output
+// Auto-generated code
+package $package;
+
+import org.onosproject.yang.AbstractYangModelRegistrator;
+import org.apache.felix.scr.annotations.Component;
+
+@Component(immediate = true)
+public class YangModelRegistrator extends AbstractYangModelRegistrator {
+    public YangModelRegistrator() {
+        super(YangModelRegistrator.class);
+    }
+}
+EOF
diff --git a/buck-tools/yang-schema b/buck-tools/yang-schema
new file mode 100755
index 0000000..bcb6e1b
--- /dev/null
+++ b/buck-tools/yang-schema
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Extracts YANG model schema and YANG sources from a YANG model jar.
+# -----------------------------------------------------------------------------
+
+output=$1
+jar=$2
+
+aux=/tmp/ys-$$
+trap "rm -fr $aux" EXIT
+
+rm -fr $aux
+mkdir -p $aux $output
+
+cd $aux
+jar xf $jar
+mv yang/* $output
\ No newline at end of file
diff --git a/bucklets/onos.bucklet b/bucklets/onos.bucklet
index f6f7e9b..4db1738 100644
--- a/bucklets/onos.bucklet
+++ b/bucklets/onos.bucklet
@@ -140,6 +140,8 @@
     resources = NONE,
     resources_root = None,
     tests = None,
+    do_javadocs = True,
+    do_checkstyle = True,
     **kwargs
     ):
 
@@ -188,22 +190,24 @@
   )
 
   ### Checkstyle
-  checkstyle(
-      name = name + '-checkstyle-files',
-      srcs = srcs,
-      jar_target = ':'+ name,
-  )
+  if do_checkstyle:
+      checkstyle(
+          name = name + '-checkstyle-files',
+          srcs = srcs,
+          jar_target = ':'+ name,
+      )
 
-  java_doc(
-       name = name + '-javadoc',
-       title = 'Java Docs',
-       pkgs = [ package_name_root ],
-       paths = [ 'src/main/java' ],
-       srcs = srcs,
-       deps = deps,
-       visibility = visibility,
-       do_it_wrong = False,
-  )
+  if do_javadocs:
+      java_doc(
+           name = name + '-javadoc',
+           title = 'Java Docs',
+           pkgs = [ package_name_root ],
+           paths = [ 'src/main/java' ],
+           srcs = srcs,
+           deps = deps,
+           visibility = visibility,
+           do_it_wrong = False,
+      )
 
   # TODO add project config for intellij
   # project_config(
diff --git a/models/demo/BUCK b/models/demo/BUCK
new file mode 100644
index 0000000..6b4456a
--- /dev/null
+++ b/models/demo/BUCK
@@ -0,0 +1,57 @@
+COMPILE_DEPS = [
+  '//lib:CORE_DEPS',
+]
+
+
+# The following will be wrapped into a macro to be used something like this:
+#
+# yang_model (
+#   app_name = 'org.onosproject.models.foobar',
+#   title = 'Demo YANG Model',
+#   url = 'http://onosproject.org',
+# )
+
+
+YANG_TOOLS = [
+  '//apps/yang:onos-apps-yang',
+  '//lib:onos-yang-runtime',
+]
+
+yang_library(
+  name = 'yang',
+  srcs = glob(['src/**/*.yang']),
+)
+
+genrule(
+  name = 'schema',
+  srcs = [ ':yang#srcs' ],
+  cmd = '$(location //buck-tools:yang-schema) $OUT $SRCS',
+  out = 'yang'
+)
+
+genrule(
+  name = 'registrator',
+  srcs = glob(['src/**/*.yang']),
+  cmd = '$(location //buck-tools:yang-registrator) $OUT org.onosproject.models.demo $SRCS',
+  out = 'YangModelRegistrator.java'
+)
+
+osgi_jar(
+  name = 'onos-models-demo',
+  # srcs = [ ':registrator' ],
+  srcs = [ ':yang#srcs', ':registrator' ],
+  deps = COMPILE_DEPS + YANG_TOOLS,
+  resources = [ ':schema' ],
+  resources_root = ".",
+  do_checkstyle = False,
+  do_javadocs = False,
+)
+
+onos_app (
+  app_name = 'org.onosproject.models.demo',
+  title = 'Demo YANG Model',
+  category = 'Model',
+  url = 'http://onosproject.org',
+  description = 'Demo YANG model extension.',
+  required_apps = [ 'org.onosproject.yang' ],
+)
diff --git a/models/demo/src/ne-l3vpn-api.yang b/models/demo/src/ne-l3vpn-api.yang
new file mode 100644
index 0000000..5b0181c
--- /dev/null
+++ b/models/demo/src/ne-l3vpn-api.yang
@@ -0,0 +1,82 @@
+/*
+WARNING:
+This yang model is just for fuction ONOS opensource project demo purpose only,
+And is subject to change in future, Huawei does not commit provide compatibilty
+in commercial product.
+*/
+module ne-l3vpn-api {
+    namespace "ne-l3vpn-api";
+    prefix l3vpn-api;
+    import ne-l3vpncomm-type {
+        prefix l3vpncomm-type;
+    }
+    import ne-l3vpncomm {
+        prefix l3vpncomm;
+    }
+    organization "Huawei Technologies Co., Ltd";
+    contact "Huawei Industrial Base
+        Bantian, Longgang
+        Shenzhen 518129
+        People's Republic of China
+        Website: http://www.huawei.com
+        Email: support@huawei.com";
+    description "VRP V800R010 Schema";
+    revision "2014-12-25" {
+        reference "Huawei VRPV8 Schema";
+    }
+    container devices {
+        list device {
+            key deviceid;
+            leaf deviceid {
+                type string;
+            }
+            container l3vpn {
+                container l3vpncomm {
+                    container l3vpnInstances {
+                    description "";
+                        list l3vpnInstance {
+                            key "vrfName";
+                            leaf vrfName {
+                                type string;
+                            }
+                            leaf vrfDescription {
+                                type string;
+                            }
+                            uses l3vpncomm:l3vpnIfs;
+                            container vpnInstAFs {
+                                description "";
+                                list vpnInstAF {
+                                    key "afType";
+                                    description "Address family";
+                                    leaf afType {
+                                        type "l3vpncomm-type:l3vpncommonL3vpnPrefixType";
+                                        description "Address family";
+                                    }
+                                    leaf vrfRD {
+                                        when "vrfName != '_public_'";
+                                        type "string";
+                                        description "route-distinguisher.";
+                                    }
+                                    container vpnTargets {
+                                        description "";
+                                        list vpnTarget {
+                                            must "vrfName != '_public_' and vpnTarget = '0'";
+                                            key "vrfRTValue vrfRTType";
+                                            description "L3vpn vpntarget configure class";
+                                            leaf vrfRTValue {
+                                                type "string";
+                                            }
+                                            leaf vrfRTType {
+                                                type "l3vpncomm-type:l3vpncommonVrfRtType";
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/models/demo/src/ne-l3vpncomm-type.yang b/models/demo/src/ne-l3vpncomm-type.yang
new file mode 100644
index 0000000..3e4e10c
--- /dev/null
+++ b/models/demo/src/ne-l3vpncomm-type.yang
@@ -0,0 +1,54 @@
+/*
+WARNING:
+This yang model is just for fuction ONOS opensource project demo purpose only,
+And is subject to change in future, Huawei does not commit provide compatibilty
+in commercial product.
+*/
+module ne-l3vpncomm-type {
+    namespace "l3vpn-comm-type";
+    prefix l3vpncomm-type;
+    organization "Huawei Technologies Co., Ltd";
+    contact "Huawei Industrial Base
+        Bantian, Longgang
+        Shenzhen 518129
+        People's Republic of China
+        Website: http://www.huawei.com
+        Email: support@huawei.com";
+    description "";
+    revision "2014-12-25" {
+        description "Initial version";
+    }
+    typedef l3vpncommonL3vpnPrefixType {
+        type enumeration {
+            enum "ipv4uni" {
+                value 0;
+                description "ipv4uni:";
+            }
+            enum "ipv6uni" {
+                value 1;
+                description "ipv6uni:";
+            }
+        }
+        description "";
+        }
+        typedef l3vpncommonVrfRtType {
+            type enumeration {
+                enum "export_extcommunity" {
+                    value 0;
+                    description "export-extcommunity:";
+                }
+                enum "import_extcommunity" {
+                    value 1;
+                    description "import-extcommunity:";
+                }
+            }
+            description "";
+        }
+        typedef ipv4Address {
+        type string {
+            length "0..255";
+            pattern "((([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}
+            ([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))";
+        }
+    }
+}
diff --git a/models/demo/src/ne-l3vpncomm.yang b/models/demo/src/ne-l3vpncomm.yang
new file mode 100644
index 0000000..b03c382
--- /dev/null
+++ b/models/demo/src/ne-l3vpncomm.yang
@@ -0,0 +1,49 @@
+/*
+WARNING:
+This yang model is just for fuction ONOS opensource project demo purpose only,
+And is subject to change in future, Huawei does not commit provide compatibilty
+in commercial product.
+*/
+module ne-l3vpncomm {
+    namespace "ne-l3vpn-comm";
+    prefix "l3vpncomm";
+    import ne-l3vpncomm-type {
+        prefix l3vpncomm-type;
+    }
+    organization "Huawei Technologies Co., Ltd";
+    contact "Huawei Industrial Base
+        Bantian, Longgang
+        Shenzhen 518129
+        People's Republic of China
+        Website: http://www.huawei.com
+        Email: support@huawei.com";
+    description "";
+    revision "2014-12-25" {
+        description "Initial version";
+    }
+    grouping l3vpnIfs {
+        container l3vpnIfs {
+        description "";
+            list l3vpnIf {
+                key "ifName";
+                description "interface Name.";
+                leaf ifName {
+                    type string;
+                    description "interface Name";
+                }
+                leaf ipv4Addr {
+                    when "subnetMask != null";
+                    mandatory "true";
+                    type "l3vpncomm-type:ipv4Address";
+                    description "Interface Address.";
+                }
+                leaf subnetMask {
+                    when "ipv4Addr != null";
+                    mandatory "true";
+                    type "l3vpncomm-type:ipv4Address";
+                    description "Interface address mask.";
+                }
+            }
+        }
+    }
+}
diff --git a/modules.defs b/modules.defs
index 05beed6..161bd25 100644
--- a/modules.defs
+++ b/modules.defs
@@ -193,6 +193,10 @@
     '//apps/l3vpn:onos-apps-l3vpn-oar',
 ]
 
+MODELS = [
+    '//models/demo:onos-models-demo-oar',
+]
+
 APP_JARS = [
     '//apps/cpman/api:onos-apps-cpman-api',
     '//apps/routing-api:onos-apps-routing-api',
@@ -209,5 +213,5 @@
     '//apps/vtn/vtnweb:onos-apps-vtn-vtnweb',
 ]
 
-APPS = ONOS_DRIVERS + ONOS_PROVIDERS + ONOS_APPS
+APPS = ONOS_DRIVERS + ONOS_PROVIDERS + ONOS_APPS + MODELS
 
diff --git a/tools/build/conf/src/main/java/org/onosproject/checkstyle/CheckstyleRunner.java b/tools/build/conf/src/main/java/org/onosproject/checkstyle/CheckstyleRunner.java
index 65023b1..e6638be 100644
--- a/tools/build/conf/src/main/java/org/onosproject/checkstyle/CheckstyleRunner.java
+++ b/tools/build/conf/src/main/java/org/onosproject/checkstyle/CheckstyleRunner.java
@@ -82,6 +82,7 @@
 
             // run Checker
             List<File> fileList = input.subList(2, input.size() - 1).stream()
+                    .filter(s -> !s.contains("/:"))  // Yes, fighting a hack with a hack.
                     .map(File::new)
                     .collect(Collectors.toList());
             int errorCounter = checker.process(fileList);