/*
* Copyright 2003-2015 JetBrains s.r.o.
*
* Licensed 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 jetbrains.mps.reloading;
import jetbrains.mps.util.FlattenIterable;
import jetbrains.mps.util.iterable.IterableEnumeration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class CompositeClassPathItem extends AbstractClassPathItem {
private List<IClassPathItem> myChildren = new ArrayList<IClassPathItem>();
public void add(IClassPathItem item) {
assert item != null;
myChildren.add(item);
}
@Override
public boolean hasClass(String name) {
for (IClassPathItem item : myChildren) {
if (item.hasClass(name)) {
return true;
}
}
return false;
}
@Override
public boolean hasPackage(@NotNull String name) {
for (IClassPathItem item : myChildren) {
if (item.hasPackage(name)) {
return true;
}
}
return false;
}
@Nullable
@Override
public ClassBytes getClassBytes(String name) {
for (IClassPathItem item : myChildren) {
ClassBytes result = item.getClassBytes(name);
if (result != null) return result;
}
return null;
}
@Override
public URL getResource(String name) {
for (IClassPathItem item : myChildren) {
URL resource = item.getResource(name);
if (resource != null) {
return resource;
}
}
return null;
}
@Override
public Enumeration<URL> getResources(String name) {
List<URL> result = new ArrayList<URL>();
for (IClassPathItem item : myChildren) {
Enumeration<URL> resources = item.getResources(name);
while (resources.hasMoreElements()) {
result.add(resources.nextElement());
}
}
return new IterableEnumeration<URL>(result);
}
@Override
public Iterable<String> getAvailableClasses(String namespace) {
FlattenIterable<String> result = new FlattenIterable<String>();
for (IClassPathItem item : myChildren) {
//todo rewrite using mapping iterable
result.add(item.getAvailableClasses(namespace));
}
return result;
}
@Override
public Iterable<String> getSubpackages(String namespace) {
FlattenIterable<String> result = new FlattenIterable<String>();
for (IClassPathItem item : myChildren) {
//todo rewrite using mapping iterable
result.add(item.getSubpackages(namespace));
}
return result;
}
public List<IClassPathItem> getChildren() {
return new ArrayList<IClassPathItem>(myChildren);
}
@Override
public List<RealClassPathItem> flatten() {
List<RealClassPathItem> result = new ArrayList<RealClassPathItem>();
for (IClassPathItem child : myChildren) {
result.addAll(child.flatten());
}
return result;
}
@Override
public CompositeClassPathItem optimize() {
List<RealClassPathItem> flattenedItems = flatten();
Iterator<RealClassPathItem> it = flattenedItems.iterator();
Set<String> alreadyVisited = new HashSet<String>();
while (it.hasNext()) {
IClassPathItem item = it.next();
if (item instanceof FileClassPathItem) {
FileClassPathItem fcp = (FileClassPathItem) item;
if (alreadyVisited.contains(fcp.getPath())) {
it.remove();
} else {
alreadyVisited.add(fcp.getPath());
}
}
if (item instanceof JarFileClassPathItem) {
JarFileClassPathItem jfcp = (JarFileClassPathItem) item;
String path = jfcp.getFile().getAbsolutePath();
if (alreadyVisited.contains(path)) {
it.remove();
} else {
alreadyVisited.add(path);
}
}
}
CompositeClassPathItem result = new CompositeClassPathItem();
for (IClassPathItem item : flattenedItems) {
result.add(item);
}
return result;
}
@Override
public void accept(IClassPathItemVisitor visitor) {
visitor.visit(this);
}
public String toString() {
StringBuilder result = new StringBuilder("classpath {\n");
for (IClassPathItem child : myChildren) {
for (String s : child.toString().split("/[\n]/")) {
result.append('\t').append(s).append("\n");
}
}
result.append("}");
return result.toString();
}
}