blob: 2b38c6a965e5db2f1e1aca1f64702c9f63162137 [file] [log] [blame]
/*
* Copyright 2000-2014 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 com.intellij.util.xml;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author peter
*/
public class ModelMergerUtil {
@Nullable
public static <T> T getFirstImplementation(final T t) {
T cur = t;
while (cur instanceof MergedObject) {
final List<T> implementations = ((MergedObject<T>)cur).getImplementations();
cur = implementations.isEmpty()? null : implementations.get(0);
}
return cur;
}
@Nullable
public static <T, V> V getImplementation(final Class<V> clazz, final Collection<T> elements) {
for (final T element : elements) {
final V implementation = getImplementation(element, clazz);
if (implementation != null) {
return implementation;
}
}
return null;
}
@Nullable
public static <T, V> V getImplementation(final Class<V> clazz, final T... elements) {
return getImplementation(clazz, Arrays.asList(elements));
}
@Nullable
public static <T, V> V getImplementation(final T element, final Class<V> clazz) {
if (element == null) return null;
CommonProcessors.FindFirstProcessor<T> processor = new CommonProcessors.FindFirstProcessor<T>() {
@Override
public boolean process(final T t) {
return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
}
};
new ImplementationProcessor<T>(processor, true).process(element);
return (V)processor.getFoundValue();
}
@NotNull
public static <T, V> Collection<V> getImplementations(final T element, final Class<V> clazz) {
if (element == null) return Collections.emptyList();
CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>() {
@Override
public boolean process(final T t) {
return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
}
};
new ImplementationProcessor<T>(processor, true).process(element);
return (Collection<V>)processor.getResults();
}
@NotNull
public static <T> List<T> getImplementations(T element) {
if (element instanceof MergedObject) {
final MergedObject<T> mergedObject = (MergedObject<T>)element;
return mergedObject.getImplementations();
}
else if (element != null) {
return Collections.singletonList(element);
}
else {
return Collections.emptyList();
}
}
@NotNull
public static <T> List<T> getFilteredImplementations(final T element) {
if (element == null) return Collections.emptyList();
final CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>(new ArrayList<T>());
new ImplementationProcessor<T>(processor, false).process(element);
return (List<T>)processor.getResults();
}
@NotNull
public static <T> Processor<T> createFilteringProcessor(final Processor<T> processor) {
return new ImplementationProcessor<T>(processor, false);
}
public static class ImplementationProcessor<T> implements Processor<T> {
private final Processor<T> myProcessor;
private final boolean myProcessMerged;
public ImplementationProcessor(Processor<T> processor, final boolean processMerged) {
myProcessor = processor;
myProcessMerged = processMerged;
}
@Override
public boolean process(final T t) {
final boolean merged = t instanceof MergedObject;
if ((!merged || myProcessMerged) && !myProcessor.process(t)) {
return false;
}
if (merged && !ContainerUtil.process(((MergedObject<T>)t).getImplementations(), this)) {
return false;
}
return true;
}
}
}