MulticastDemand extends NetworkElement implements IMonitorizableElement { public void couple(Set<Link> links) { this.checkAttachedToNetPlanObject(); netPlan.checkIsModifiable(); if (links.size () != egressNodes.size ()) throw new Net2PlanException ("Multicast demands can be coupled to a set of links, starting in the demand ingress node, and ending in each of the multicast demand egress nodes"); final NetworkLayer lowerLayer = layer; final NetworkLayer upperLayer = links.iterator().next().layer; if (coupledUpperLayerLinks != null) throw new Net2PlanException("Demand " + id + " at layer " + lowerLayer.id + " is already associated to an upper layer demand"); if (upperLayer.equals(lowerLayer)) throw new Net2PlanException("Bad - Trying to couple links and demands in the same layer"); if (!upperLayer.linkCapacityUnitsName.equals(lowerLayer.demandTrafficUnitsName)) throw new Net2PlanException(String.format(netPlan.TEMPLATE_CROSS_LAYER_UNITS_NOT_MATCHING, upperLayer.id, upperLayer.linkCapacityUnitsName, lowerLayer.id, lowerLayer.demandTrafficUnitsName)); SortedMap<Node,Link> mapLink2EgressNode = new TreeMap<> (); for (Link link : links) { link.checkAttachedToNetPlanObject(netPlan); if ((link.coupledLowerOrThisLayerDemand!= null) || (link.coupledLowerLayerMulticastDemand != null)) throw new Net2PlanException("Link " + link + " at layer " + upperLayer.id + " is already associated to a lower layer demand"); if (!link.originNode.equals(ingressNode)) throw new Net2PlanException ("Multicast demands can be coupled to a set of links, starting in the demand ingress node, and ending in each of the multicast demand egress nodes"); if (!link.layer.equals(upperLayer)) throw new Net2PlanException ("Multicast demands can be coupled to a set of links, starting in the demand ingress node, and ending in each of the multicast demand egress nodes"); mapLink2EgressNode.put(link.destinationNode, link); } if (!mapLink2EgressNode.keySet().equals(egressNodes)) throw new Net2PlanException ("Multicast demands can be coupled to a set of links, starting in the demand ingress node, and ending in each of the multicast demand egress nodes"); DemandLinkMapping coupling_thisLayerPair = netPlan.interLayerCoupling.getEdge(lowerLayer, upperLayer); if (coupling_thisLayerPair == null) { coupling_thisLayerPair = new DemandLinkMapping(); boolean valid; try { valid = netPlan.interLayerCoupling.addEdge(lowerLayer, upperLayer, coupling_thisLayerPair); } catch (IllegalArgumentException ex) { valid = false; } if (!valid) throw new Net2PlanException("Coupling between link set " + links + " at layer " + upperLayer + " and multicast demand " + id + " at layer " + lowerLayer.id + " would induce a cycle between layers"); } coupledUpperLayerLinks = new TreeMap<> (); layer.cache_coupledMulticastDemands.add (this); for (Link link : links) { link.updateCapacityAndZeroCapacityLinksAndRoutesCaches(carriedTraffic); link.coupledLowerLayerMulticastDemand = this; link.layer.cache_coupledLinks.add (link); this.coupledUpperLayerLinks.put(link.destinationNode, link); link.updateWorstCasePropagationTraversingUnicastDemandsAndMaybeRoutes(); } coupling_thisLayerPair.put(this, new TreeSet<Link> (links)); if (ErrorHandling.isDebugEnabled()) netPlan.checkCachesConsistency(); } MulticastDemand(NetPlan netPlan , long id , int index , NetworkLayer layer , Node ingressNode , Set<Node> egressNodes , double offeredTraffic , AttributeMap attributes); void setMaximumAcceptableE2EWorstCaseLatencyInMs(double maxLatencyMs); double getMaximumAcceptableE2EWorstCaseLatencyInMs(); void setQoSType(String newQosType); String getQosType(); void setOfferedTrafficPerPeriodGrowthFactor(double growthFactor); double getOfferedTrafficPerPeriodGrowthFactor(); NetworkLayer getLayer(); double getWorseCasePropagationTimeInMs(); double getWorstCaseLengthInKm(); boolean isTraversingOversubscribedLinks(); Node getIngressNode(); SortedSet<Node> getEgressNodes(); double getOfferedTraffic(); double getCarriedTraffic(); double getBlockedTraffic(); Pair<SortedSet<MulticastTree>,Double> computeMinimumCostMulticastTrees(double [] costs); boolean isBifurcated(); boolean isBlocked(); SortedSet<MulticastTree> getMulticastTrees(); boolean isAllTreesReachingAllEgressNodes(); void couple(Set<Link> links); SortedSet<Link> coupleToNewLinksCreated(NetworkLayer newLinkLayer); SortedSet<Link> getCoupledLinks(); boolean isCoupled(); void decouple(); void remove(); void setOfferedTraffic(double offeredTraffic); String toString(); SortedMap<Link, Double> getTraversedLinksAndCarriedTraffic(final boolean normalizedToOfferedTraffic); SortedSet<Link> getLinksNoDownPropagationPotentiallyCarryingTraffic(Node egressNode); TrafficSeries getMonitoredOrForecastedOfferedTraffic(); void setMonitoredOrForecastedOfferedTraffic(TrafficSeries newTimeSeries); @Override TrafficSeries getMonitoredOrForecastedCarriedTraffic(); @Override void setMonitoredOrForecastedCarriedTraffic(TrafficSeries newTimeSeries); @Override double getCurrentTrafficToAddMonitSample(); @Override boolean isPossibleToSetCurrentTrafficAsGivenMonitSample(); @Override void setCurrentTrafficToGivenMonitSample(double traffic); @Override Optional<TrafficPredictor> getTrafficPredictor(); @Override void setTrafficPredictor(TrafficPredictor tp); @Override void removeTrafficPredictor();  }
@Test public void testCouple() { assertTrue (d123.isCoupled()); assertEquals(d123.getCoupledLinks() , new TreeSet<Link> (Arrays.asList(upperMdLink12 , upperMdLink13))); }