/* * Copyright (c) 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.nic.compiler; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Set; import org.opendaylight.nic.compiler.api.Action; import org.opendaylight.nic.compiler.api.Endpoint; import org.opendaylight.nic.compiler.api.IntentCompilerException; import org.opendaylight.nic.compiler.api.Policy; import com.google.common.collect.Sets; public class Transform { public Collection<Policy> resolve(Policy p1, Policy p2) throws IntentCompilerException { Collection<Policy> policies = new LinkedList<>(); Sets.SetView<Endpoint> src; Sets.SetView<Endpoint> dst; // All the possible cases below src = Sets.difference(p1.src(), p2.src()); if (!src.isEmpty()) { // Case: S1 and not S2 , D1 and not D2 dst = Sets.difference(p1.dst(), p2.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p1.action())); } // Case: S1 and not S2 , D1 and D2 dst = Sets.intersection(p1.dst(), p2.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p1.action())); } } src = Sets.intersection(p1.src(), p2.src()); if (!src.isEmpty()) { // Case: S1 and S2 , D1 and D2 dst = Sets.intersection(p1.dst(), p2.dst()); if (!dst.isEmpty()) { Set<Action> mergedActions = merge(p1.action(), p2.action()); if (mergedActions == null) { throw new IntentCompilerException("Unable to merge exclusive actions", Arrays.asList(p1, p2)); } policies.add(new PolicyImpl(src, dst, mergedActions)); } // Case: S1 and S2 , D1 and not D2 dst = Sets.difference(p1.dst(), p2.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p1.action())); } // Case: S1 and S2 , D2 and not D1 dst = Sets.difference(p2.dst(), p1.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p2.action())); } } src = Sets.difference(p2.src(), p1.src()); if (!src.isEmpty()) { // Case: S2 and not S1 , D1 and D2 dst = Sets.intersection(p1.dst(), p2.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p2.action())); } // Case: S2 and not S1 , D2 and not D1 dst = Sets.difference(p2.dst(), p1.dst()); if (!dst.isEmpty()) { policies.add(new PolicyImpl(src, dst, p2.action())); } } return policies; } private Set<Action> merge(Set<Action> a1, Set<Action> a2) throws IntentCompilerException { Set<Action> composebleActions = new LinkedHashSet<>(); Set<Action> observableActions = new LinkedHashSet<>(); Set<Action> exclusiveActions = new LinkedHashSet<>(); for (Action action : Sets.union(a1, a2)) { switch (action.getType()) { case COMPOSABLE: composebleActions.add(action); break; case OBSERVER: observableActions.add(action); break; case EXCLUSIVE: exclusiveActions.add(action); break; default: return null; } } if (!exclusiveActions.isEmpty()) { if (exclusiveActions.size() == 1) { return Sets.union(exclusiveActions, observableActions); } else { return null; } } return Sets.union(composebleActions, observableActions); } }