package org.opendaylight.protocol.pcep.impl.object;
import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import org.opendaylight.protocol.concepts.AbstractMetric;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.TEMetric;
import org.opendaylight.protocol.pcep.PCEPDeserializerException;
-import org.opendaylight.protocol.pcep.PCEPDocumentedException;
-import org.opendaylight.protocol.pcep.spi.AbstractObjectParser;
-import org.opendaylight.protocol.pcep.spi.HandlerRegistry;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
+import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPHopCountMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPIGPMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPTEMetric;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
import org.opendaylight.protocol.util.ByteArray;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ieee754.rev130819.Float32;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.MetricObject;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.ObjectHeader;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.svec.Metric;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.svec.MetricBuilder;
/**
- * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPMetricObject PCEPMetricObject}
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPMetricObject
+ * PCEPMetricObject}
*/
-public class PCEPMetricObjectParser extends AbstractObjectParser<MetricBuilder> {
-
- public static final int CLASS = 6;
-
- public static final int TYPE = 1;
+public class PCEPMetricObjectParser implements PCEPObjectParser {
/*
* lengths of fields in bytes
public static final int SIZE = METRIC_VALUE_F_OFFSET + METRIC_VALUE_F_LENGTH;
- public PCEPMetricObjectParser(final HandlerRegistry registry) {
- super(registry);
+ /**
+ * Bidirectional mapping for metrics. Maps metric class to integer and
+ * integer to metrics instantiable.
+ */
+ public static class PCEPMetricsMapping {
+ private static final PCEPMetricsMapping instance = new PCEPMetricsMapping();
+
+ private final Map<Class<?>, Integer> metricsMap = new HashMap<Class<?>, Integer>();
+ private final Map<Integer, InstantiableMetric> metrictTypesMap = new HashMap<Integer, InstantiableMetric>();
+
+ private interface InstantiableMetric {
+ public AbstractMetric<?> getMetric(long metric);
+ }
+
+ private PCEPMetricsMapping() {
+ this.fillIn();
+ }
+
+ private void fillIn() {
+ this.fillIn(1, IGPMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new IGPMetric(metric);
+ }
+
+ });
+ this.fillIn(2, TEMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new TEMetric(metric);
+ }
+
+ });
+ this.fillIn(4, AggregateBandwidthConsumptionMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new AggregateBandwidthConsumptionMetric(metric);
+ }
+
+ });
+ this.fillIn(5, MostLoadedLinkLoadMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new MostLoadedLinkLoadMetric(metric);
+ }
+
+ });
+ this.fillIn(6, CumulativeIGPCostMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new CumulativeIGPCostMetric(metric);
+ }
+
+ });
+ this.fillIn(7, CumulativeTECostMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new CumulativeTECostMetric(metric);
+ }
+
+ });
+ this.fillIn(8, P2MPIGPMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPIGPMetric(metric);
+ }
+
+ });
+ this.fillIn(9, P2MPTEMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPHopCountMetric(metric);
+ }
+
+ });
+ this.fillIn(10, P2MPHopCountMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPHopCountMetric(metric);
+ }
+
+ });
+ }
+
+ private void fillIn(int type, Class<?> metricClazz, InstantiableMetric instantiable) {
+ this.metricsMap.put(metricClazz, type);
+ this.metrictTypesMap.put(type, instantiable);
+ }
+
+ public int getFromMetricClass(Class<? extends AbstractMetric<?>> clazz) {
+ final Integer mi = this.metricsMap.get(clazz);
+ if (mi == null)
+ throw new NoSuchElementException("Unknown Metric: " + clazz);
+ return mi;
+ }
+
+ public AbstractMetric<?> getFromMetricTypeIdentifier(int identifier, long metric) {
+ final InstantiableMetric e = this.metrictTypesMap.get(identifier);
+ if (e == null)
+ throw new NoSuchElementException("Unknown metric type identifier. Passed: " + identifier);
+ return e.getMetric(metric);
+ }
+
+ public static PCEPMetricsMapping getInstance() {
+ return instance;
+ }
}
@Override
- public MetricObject parseObject(final ObjectHeader header, final byte[] bytes) throws PCEPDeserializerException,
- PCEPDocumentedException {
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
if (bytes == null || bytes.length == 0)
throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
if (bytes.length != SIZE)
throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
+
final byte[] flagBytes = { bytes[FLAGS_F_OFFSET] };
final BitSet flags = ByteArray.bytesToBitSet(flagBytes);
-
- final MetricBuilder builder = new MetricBuilder();
-
- builder.setIgnore(header.isIgnore());
- builder.setProcessingRule(header.isProcessingRule());
-
- builder.setBound(flags.get(B_FLAG_OFFSET));
- builder.setComputed(flags.get(C_FLAG_OFFSET));
- builder.setMetricType((short) (bytes[TYPE_F_OFFSET] & 0xFF));
- builder.setValue(new Float32(ByteArray.subByte(bytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH)));
-
- return builder.build();
+ try {
+ return new PCEPMetricObject(flags.get(B_FLAG_OFFSET), flags.get(C_FLAG_OFFSET), PCEPMetricsMapping.getInstance().getFromMetricTypeIdentifier(
+ (short) (bytes[TYPE_F_OFFSET] & 0xFF),
+ (long) ByteArray.bytesToFloat(ByteArray.subByte(bytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH))), processed, ignored);
+ } catch (final NoSuchElementException e) {
+ throw new PCEPDeserializerException(e, "Metric object has unknown identifier.");
+ }
}
@Override
- public void addTlv(final MetricBuilder builder, final Tlv tlv) {
- // No tlvs defined
- }
-
- @Override
- public byte[] serializeObject(final Object object) {
- if (!(object instanceof MetricObject))
- throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + object.getClass() + ". Needed MetricObject.");
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPMetricObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPMetricObject.");
- final MetricObject mObj = (MetricObject) object;
+ final PCEPMetricObject mObj = (PCEPMetricObject) obj;
final byte[] retBytes = new byte[SIZE];
final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
- flags.set(C_FLAG_OFFSET, ((Metric) mObj).isComputed());
+ flags.set(C_FLAG_OFFSET, mObj.isComputedMetric());
flags.set(B_FLAG_OFFSET, mObj.isBound());
ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
- System.arraycopy(mObj.getValue().getValue(), 0, retBytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH);
+ final AbstractMetric<?> metric = mObj.getMetric();
+ @SuppressWarnings("unchecked")
+ final Class<? extends AbstractMetric<?>> metricClazz = (Class<? extends AbstractMetric<?>>) metric.getClass();
+ retBytes[TYPE_F_OFFSET] = (byte) PCEPMetricsMapping.getInstance().getFromMetricClass(metricClazz);
- return retBytes;
- }
+ System.arraycopy(ByteArray.floatToBytes(mObj.getMetric().getValue()), 0, retBytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH);
- @Override
- public int getObjectType() {
- return TYPE;
+ return retBytes;
}
- @Override
- public int getObjectClass() {
- return CLASS;
- }
}