[ONOS-2356] Implementation for PCEP label update message.

Change-Id: I510a9a7c7c868da1fc3d6e2625501f094faf8115
diff --git a/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelObjectVer1.java b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelObjectVer1.java
new file mode 100644
index 0000000..834054b
--- /dev/null
+++ b/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelObjectVer1.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright 2015 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.pcepio.protocol.ver1;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepLabelObject;
+import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
+import org.onosproject.pcepio.types.NexthopIPv6addressTlv;
+import org.onosproject.pcepio.types.NexthopUnnumberedIPv4IDTlv;
+import org.onosproject.pcepio.types.PcepObjectHeader;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/*
+ *   ref : draft-zhao-pce-pcep-extension-for-pce-controller-01 , section : 7.4.
+
+        0                   1                   2                   3
+           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       | Reserved                      | Flags                       |O|
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                            Label                              |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                                                               |
+       //                        Optional TLV                          //
+       |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                     The LABEL Object format
+ */
+public class PcepLabelObjectVer1 implements PcepLabelObject {
+
+    protected static final Logger log = LoggerFactory.getLogger(PcepLspObjectVer1.class);
+
+    public static final byte LABEL_OBJ_TYPE = 1;
+    public static final byte LABEL_OBJ_CLASS = 35; //TBD : to be defined
+    public static final byte LABEL_OBJECT_VERSION = 1;
+    public static final byte OBJECT_HEADER_LENGTH = 4;
+    public static final boolean DEFAULT_OFLAG = false;
+
+    // LSP_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ LspObjectHeaderLen(8)
+    public static final short LABEL_OBJ_MINIMUM_LENGTH = 12;
+
+    public static final int OFLAG_SET = 1;
+    public static final int OFLAG_RESET = 0;
+    public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
+
+    static final PcepObjectHeader DEFAULT_LABEL_OBJECT_HEADER = new PcepObjectHeader(LABEL_OBJ_CLASS, LABEL_OBJ_TYPE,
+            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, LABEL_OBJ_MINIMUM_LENGTH);
+
+    private PcepObjectHeader labelObjHeader;
+    private boolean bOFlag;
+    private int label;
+    // Optional TLV
+    private LinkedList<PcepValueType> llOptionalTlv;
+
+    /**
+     * Constructor to initialize parameters for PCEP label object.
+     *
+     * @param labelObjHeader label object header
+     * @param bOFlag O flag
+     * @param label label
+     * @param llOptionalTlv list of optional tlvs
+     */
+    public PcepLabelObjectVer1(PcepObjectHeader labelObjHeader, boolean bOFlag, int label,
+            LinkedList<PcepValueType> llOptionalTlv) {
+        this.labelObjHeader = labelObjHeader;
+        this.bOFlag = bOFlag;
+        this.label = label;
+        this.llOptionalTlv = llOptionalTlv;
+    }
+
+    @Override
+    public LinkedList<PcepValueType> getOptionalTlv() {
+        return this.llOptionalTlv;
+    }
+
+    @Override
+    public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
+        this.llOptionalTlv = llOptionalTlv;
+    }
+
+    @Override
+    public boolean getOFlag() {
+        return this.bOFlag;
+    }
+
+    @Override
+    public void setOFlag(boolean value) {
+        this.bOFlag = value;
+    }
+
+    @Override
+    public int getLabel() {
+        return this.label;
+    }
+
+    @Override
+    public void setLabel(int value) {
+        this.label = value;
+    }
+
+    /**
+     * Reads form channel buffer and returns objects of PcepLabelObject.
+     *
+     * @param cb of type channel buffer
+     * @return objects of PcepLabelObject
+     * @throws PcepParseException when fails to read from channel buffer
+     */
+    public static PcepLabelObject read(ChannelBuffer cb) throws PcepParseException {
+
+        PcepObjectHeader labelObjHeader;
+
+        boolean bOFlag;
+        int label;
+
+        // Optional TLV
+        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+        labelObjHeader = PcepObjectHeader.read(cb);
+
+        //take only LspObject buffer.
+        ChannelBuffer tempCb = cb.readBytes(labelObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
+
+        int iTemp = tempCb.readInt();
+        bOFlag = (iTemp & (byte) 0x01) == 1 ? true : false;
+        label = tempCb.readInt();
+
+        // parse optional TLV
+        llOptionalTlv = parseOptionalTlv(tempCb);
+        return new PcepLabelObjectVer1(labelObjHeader, bOFlag, label, llOptionalTlv);
+    }
+
+    @Override
+    public int write(ChannelBuffer cb) throws PcepParseException {
+
+        //write Object header
+        int objStartIndex = cb.writerIndex();
+        int objLenIndex = labelObjHeader.write(cb);
+
+        if (objLenIndex <= 0) {
+            throw new PcepParseException(" ObjectLength Index is " + objLenIndex);
+        }
+
+        byte oFlag;
+
+        oFlag = (byte) ((bOFlag) ? OFLAG_SET : OFLAG_RESET);
+        cb.writeInt(oFlag);
+        cb.writeInt(label);
+
+        // Add optional TLV
+        packOptionalTlv(cb);
+
+        //Update object length now
+        int length = cb.writerIndex() - objStartIndex;
+
+        //will be helpful during print().
+        labelObjHeader.setObjLen((short) length);
+        cb.setShort(objLenIndex, (short) length);
+        return cb.writerIndex();
+    }
+
+    /**
+     * Returns list of optional tlvs.
+     *
+     * @param cb of type channel buffer
+     * @return list of optional tlvs.
+     * @throws PcepParseException when fails to parse list of optional tlvs
+     */
+    protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {
+
+        LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<PcepValueType>();
+
+        while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {
+
+            PcepValueType tlv;
+            short hType = cb.readShort();
+            short hLength = cb.readShort();
+            int iValue = 0;
+
+            switch (hType) {
+
+            case NexthopIPv4addressTlv.TYPE:
+                iValue = cb.readInt();
+                tlv = new NexthopIPv4addressTlv(iValue);
+                break;
+            case NexthopIPv6addressTlv.TYPE:
+                byte[] ipv6Value = new byte[NexthopIPv6addressTlv.VALUE_LENGTH];
+                cb.readBytes(ipv6Value, 0, NexthopIPv6addressTlv.VALUE_LENGTH);
+                tlv = new NexthopIPv6addressTlv(ipv6Value);
+                break;
+            case NexthopUnnumberedIPv4IDTlv.TYPE:
+                tlv = NexthopUnnumberedIPv4IDTlv.read(cb);
+                break;
+            default:
+                throw new PcepParseException("Unsupported TLV type :" + hType);
+            }
+
+            // Check for the padding
+            int pad = hLength % 4;
+            if (0 < pad) {
+                pad = 4 - pad;
+                if (pad <= cb.readableBytes()) {
+                    cb.skipBytes(pad);
+                }
+            }
+
+            llOutOptionalTlv.add(tlv);
+        }
+
+        if (0 < cb.readableBytes()) {
+
+            throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
+        }
+        return llOutOptionalTlv;
+    }
+
+    /**
+     * Returns the writer index.
+     *
+     * @param cb of channel buffer.
+     * @return writer index
+     */
+    protected int packOptionalTlv(ChannelBuffer cb) {
+
+        ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
+
+        while (listIterator.hasNext()) {
+            PcepValueType tlv = listIterator.next();
+
+            if (null == tlv) {
+                log.debug("tlv is null from OptionalTlv list");
+                continue;
+            }
+            tlv.write(cb);
+        }
+        return cb.writerIndex();
+    }
+
+    /**
+     * Builder class for PCEP label object.
+     */
+    public static class Builder implements PcepLabelObject.Builder {
+
+        private boolean bIsHeaderSet = false;
+        private boolean bIsOFlagSet = false;
+        private boolean bIsLabelSet = false;
+
+        private PcepObjectHeader labelObjHeader;
+        private boolean bOFlag;
+        private int label;
+
+        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+
+        private boolean bIsPFlagSet = false;
+        private boolean bPFlag;
+
+        private boolean bIsIFlagSet = false;
+        private boolean bIFlag;
+
+        @Override
+        public PcepLabelObject build() throws PcepParseException {
+            PcepObjectHeader labelObjHeader = this.bIsHeaderSet ? this.labelObjHeader : DEFAULT_LABEL_OBJECT_HEADER;
+            boolean bOFlag = this.bIsOFlagSet ? this.bOFlag : DEFAULT_OFLAG;
+
+            if (!this.bIsLabelSet) {
+                throw new PcepParseException(" Label NOT Set while building PcepLabelObject.");
+            }
+            if (bIsPFlagSet) {
+                labelObjHeader.setPFlag(bPFlag);
+            }
+            if (bIsIFlagSet) {
+                labelObjHeader.setIFlag(bIFlag);
+            }
+            return new PcepLabelObjectVer1(labelObjHeader, bOFlag, this.label, this.llOptionalTlv);
+        }
+
+        @Override
+        public PcepObjectHeader getLabelObjHeader() {
+            return this.labelObjHeader;
+        }
+
+        @Override
+        public Builder setLabelObjHeader(PcepObjectHeader obj) {
+            this.labelObjHeader = obj;
+            this.bIsHeaderSet = true;
+            return this;
+        }
+
+        @Override
+        public boolean getOFlag() {
+            return this.bOFlag;
+        }
+
+        @Override
+        public Builder setOFlag(boolean value) {
+            this.bOFlag = value;
+            this.bIsOFlagSet = true;
+            return this;
+        }
+
+        @Override
+        public int getLabel() {
+            return this.label;
+        }
+
+        @Override
+        public Builder setLabel(int value) {
+            this.label = value;
+            this.bIsLabelSet = true;
+            return this;
+        }
+
+        @Override
+        public LinkedList<PcepValueType> getOptionalTlv() {
+            return this.llOptionalTlv;
+        }
+
+        @Override
+        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
+            this.llOptionalTlv = llOptionalTlv;
+            return this;
+        }
+
+        @Override
+        public Builder setPFlag(boolean value) {
+            this.bPFlag = value;
+            this.bIsPFlagSet = true;
+            return this;
+        }
+
+        @Override
+        public Builder setIFlag(boolean value) {
+            this.bIFlag = value;
+            this.bIsIFlagSet = true;
+            return this;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).add("OFlag", bOFlag).add("label", label)
+                .add("OptionalTlvList", llOptionalTlv).toString();
+    }
+}