/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.brooklyn.core.mgmt.rebind.transformer.impl; import java.util.Collection; import java.util.List; import java.util.Set; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMemento; import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento; import org.apache.brooklyn.api.mgmt.rebind.mementos.LocationMemento; import org.apache.brooklyn.core.mgmt.rebind.dto.BrooklynMementoImpl; import org.apache.brooklyn.core.mgmt.rebind.transformer.BrooklynMementoTransformer; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.collections.MutableSet; import com.google.common.annotations.Beta; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @Beta public class DeleteOrphanedLocationsTransformer implements BrooklynMementoTransformer { // TODO Work in progress; untested code! public BrooklynMemento transform(BrooklynMemento input) throws Exception { Set<String> referencedLocationIds = findReferencedLocationIds(input); Set<String> unreferencedLocationIds = Sets.newLinkedHashSet(); List<String> toCheck = Lists.newLinkedList(input.getLocationIds()); while (!toCheck.isEmpty()) { String locationId = toCheck.remove(0); List<String> locationsInHierarchy = MutableList.<String>builder() .add(locationId) .addAll(findLocationAncestors(input, locationId)) .addAll(findLocationDescendents(input, locationId)) .build(); if (containsAny(referencedLocationIds, locationsInHierarchy)) { // keep them all } else { unreferencedLocationIds.addAll(locationsInHierarchy); } toCheck.removeAll(locationsInHierarchy); } // TODO What about brooklyn version? return BrooklynMementoImpl.builder() .applicationIds(input.getApplicationIds()) .topLevelLocationIds(MutableSet.<String>builder() .addAll(input.getTopLevelLocationIds()) .removeAll(unreferencedLocationIds) .build()) .entities(input.getEntityMementos()) .locations(MutableMap.<String, LocationMemento>builder() .putAll(input.getLocationMementos()) .removeAll(unreferencedLocationIds) .build()) .policies(input.getPolicyMementos()) .enrichers(input.getEnricherMementos()) .catalogItems(input.getCatalogItemMementos()) .build(); } public boolean containsAny(Collection<?> container, Iterable<?> contenders) { for (Object contender : contenders) { if (container.contains(contender)) return true; } return false; } public Set<String> findReferencedLocationIds(BrooklynMemento input) { Set<String> result = Sets.newLinkedHashSet(); for (EntityMemento entity : input.getEntityMementos().values()) { result.addAll(entity.getLocations()); } return result; } public Set<String> findLocationAncestors(BrooklynMemento input, String locationId) { Set<String> result = Sets.newLinkedHashSet(); String parentId = null; do { LocationMemento memento = input.getLocationMemento(locationId); parentId = memento.getParent(); if (parentId != null) result.add(parentId); } while (parentId != null); return result; } public Set<String> findLocationDescendents(BrooklynMemento input, String locationId) { Set<String> result = Sets.newLinkedHashSet(); List<String> tovisit = Lists.newLinkedList(); tovisit.add(locationId); while (!tovisit.isEmpty()) { LocationMemento memento = input.getLocationMemento(tovisit.remove(0)); List<String> children = memento.getChildren(); result.addAll(children); tovisit.addAll(children); }; return result; } }