blob: bc101edb6ce0080636fdc64a46f525c821b24197 [file] [log] [blame]
/*
* 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.myfaces.extensions.scripting.core.engine.dependencyScan.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* class dependency maps
* note this class is thread save
*/
public class ClassDependencies {
/**
* reverse index which shows which
* a class name and which classes in the system depend on that
* classname
* <p/>
* <p/>
* the key is a dependency a class has the _value is a set of classes which depend on the current class
*/
private Map<String, Set<String>> reverseIndex = new ConcurrentHashMap<String, Set<String>>();
public void addDependency(String referencingClass, String referencedClass) {
Set<String> reverseDependencies = getReverseDependencies(referencedClass);
reverseDependencies.add(referencingClass);
}
/**
* adds a set of dependencies to the
* reverse lookup index
*
* @param referencingClass the referencing class of this dependency
* @param referencedClasses the referenced class of this dependency
*/
public void addDependencies(String referencingClass, Collection<String> referencedClasses) {
for (String referencedClass : referencedClasses) {
addDependency(referencingClass, referencedClass);
}
}
/**
* removes a referenced class an all its referencing classes!
*
* @param clazz the referenced class to be deleted
*/
public void removeReferenced(String clazz) {
reverseIndex.remove(clazz);
}
/**
* removes a referencing class
* and deletes the referenced
* entry if it is not referenced anymore
*
* @param clazz the referencing class to delete
*/
@SuppressWarnings("unused")
public void removeReferrer(String clazz) {
List<String> emptyReferences = new ArrayList<String>(reverseIndex.size());
for (Map.Entry<String, Set<String>> entry : reverseIndex.entrySet()) {
Set<String> entrySet = entry.getValue();
entrySet.remove(clazz);
if (entrySet.isEmpty()) {
emptyReferences.add(entry.getKey());
}
}
for (String toDelete : emptyReferences) {
removeReferenced(toDelete);
}
}
public Set<String> getReferringClasses(String referencedClass) {
return reverseIndex.get(referencedClass);
}
private Set<String> getReverseDependencies(String dependency) {
Set<String> dependencies = reverseIndex.get(dependency);
if (dependencies == null) {
dependencies = Collections.synchronizedSet(new HashSet<String>());
reverseIndex.put(dependency, dependencies);
}
return dependencies;
}
}