2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.pcep.impl.object;
10 import java.util.BitSet;
11 import java.util.HashMap;
13 import java.util.NoSuchElementException;
15 import org.opendaylight.protocol.concepts.AbstractMetric;
16 import org.opendaylight.protocol.concepts.IGPMetric;
17 import org.opendaylight.protocol.concepts.TEMetric;
18 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
19 import org.opendaylight.protocol.pcep.PCEPObject;
20 import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
21 import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
22 import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
23 import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
24 import org.opendaylight.protocol.pcep.concepts.P2MPHopCountMetric;
25 import org.opendaylight.protocol.pcep.concepts.P2MPIGPMetric;
26 import org.opendaylight.protocol.pcep.concepts.P2MPTEMetric;
27 import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
28 import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
29 import org.opendaylight.protocol.util.ByteArray;
32 * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPMetricObject
35 public class PCEPMetricObjectParser implements PCEPObjectParser {
38 * lengths of fields in bytes
40 private static final int FLAGS_F_LENGTH = 1;
41 private static final int TYPE_F_LENGTH = 1;
42 private static final int METRIC_VALUE_F_LENGTH = 4;
45 * offsets of fields in bytes
47 public static final int FLAGS_F_OFFSET = 2;
48 public static final int TYPE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
49 public static final int METRIC_VALUE_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
52 * flags offsets inside flags field in bits
54 private static final int C_FLAG_OFFSET = 6;
55 private static final int B_FLAG_OFFSET = 7;
57 public static final int SIZE = METRIC_VALUE_F_OFFSET + METRIC_VALUE_F_LENGTH;
60 * Bidirectional mapping for metrics. Maps metric class to integer and
61 * integer to metrics instantiable.
63 public static class PCEPMetricsMapping {
64 private static final PCEPMetricsMapping instance = new PCEPMetricsMapping();
66 private final Map<Class<?>, Integer> metricsMap = new HashMap<Class<?>, Integer>();
67 private final Map<Integer, InstantiableMetric> metrictTypesMap = new HashMap<Integer, InstantiableMetric>();
69 private interface InstantiableMetric {
70 public AbstractMetric<?> getMetric(long metric);
73 private PCEPMetricsMapping() {
77 private void fillIn() {
78 this.fillIn(1, IGPMetric.class, new InstantiableMetric() {
81 public AbstractMetric<?> getMetric(long metric) {
82 return new IGPMetric(metric);
86 this.fillIn(2, TEMetric.class, new InstantiableMetric() {
89 public AbstractMetric<?> getMetric(long metric) {
90 return new TEMetric(metric);
94 this.fillIn(4, AggregateBandwidthConsumptionMetric.class, new InstantiableMetric() {
97 public AbstractMetric<?> getMetric(long metric) {
98 return new AggregateBandwidthConsumptionMetric(metric);
102 this.fillIn(5, MostLoadedLinkLoadMetric.class, new InstantiableMetric() {
105 public AbstractMetric<?> getMetric(long metric) {
106 return new MostLoadedLinkLoadMetric(metric);
110 this.fillIn(6, CumulativeIGPCostMetric.class, new InstantiableMetric() {
113 public AbstractMetric<?> getMetric(long metric) {
114 return new CumulativeIGPCostMetric(metric);
118 this.fillIn(7, CumulativeTECostMetric.class, new InstantiableMetric() {
121 public AbstractMetric<?> getMetric(long metric) {
122 return new CumulativeTECostMetric(metric);
126 this.fillIn(8, P2MPIGPMetric.class, new InstantiableMetric() {
129 public AbstractMetric<?> getMetric(long metric) {
130 return new P2MPIGPMetric(metric);
134 this.fillIn(9, P2MPTEMetric.class, new InstantiableMetric() {
137 public AbstractMetric<?> getMetric(long metric) {
138 return new P2MPHopCountMetric(metric);
142 this.fillIn(10, P2MPHopCountMetric.class, new InstantiableMetric() {
145 public AbstractMetric<?> getMetric(long metric) {
146 return new P2MPHopCountMetric(metric);
152 private void fillIn(int type, Class<?> metricClazz, InstantiableMetric instantiable) {
153 this.metricsMap.put(metricClazz, type);
154 this.metrictTypesMap.put(type, instantiable);
157 public int getFromMetricClass(Class<? extends AbstractMetric<?>> clazz) {
158 final Integer mi = this.metricsMap.get(clazz);
160 throw new NoSuchElementException("Unknown Metric: " + clazz);
164 public AbstractMetric<?> getFromMetricTypeIdentifier(int identifier, long metric) {
165 final InstantiableMetric e = this.metrictTypesMap.get(identifier);
167 throw new NoSuchElementException("Unknown metric type identifier. Passed: " + identifier);
168 return e.getMetric(metric);
171 public static PCEPMetricsMapping getInstance() {
177 public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
178 if (bytes == null || bytes.length == 0)
179 throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
181 if (bytes.length != SIZE)
182 throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
184 final byte[] flagBytes = { bytes[FLAGS_F_OFFSET] };
185 final BitSet flags = ByteArray.bytesToBitSet(flagBytes);
187 return new PCEPMetricObject(flags.get(B_FLAG_OFFSET), flags.get(C_FLAG_OFFSET), PCEPMetricsMapping.getInstance().getFromMetricTypeIdentifier(
188 (short) (bytes[TYPE_F_OFFSET] & 0xFF),
189 (long) ByteArray.bytesToFloat(ByteArray.subByte(bytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH))), processed, ignored);
190 } catch (final NoSuchElementException e) {
191 throw new PCEPDeserializerException(e, "Metric object has unknown identifier.");
196 public byte[] put(PCEPObject obj) {
197 if (!(obj instanceof PCEPMetricObject))
198 throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPMetricObject.");
200 final PCEPMetricObject mObj = (PCEPMetricObject) obj;
202 final byte[] retBytes = new byte[SIZE];
203 final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
204 flags.set(C_FLAG_OFFSET, mObj.isComputedMetric());
205 flags.set(B_FLAG_OFFSET, mObj.isBound());
207 ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
209 final AbstractMetric<?> metric = mObj.getMetric();
210 @SuppressWarnings("unchecked")
211 final Class<? extends AbstractMetric<?>> metricClazz = (Class<? extends AbstractMetric<?>>) metric.getClass();
212 retBytes[TYPE_F_OFFSET] = (byte) PCEPMetricsMapping.getInstance().getFromMetricClass(metricClazz);
214 System.arraycopy(ByteArray.floatToBytes(mObj.getMetric().getValue()), 0, retBytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH);