blob: b9f9871f811bc6afeeeb5bb5219bf81b0401e490 [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.impl;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomCollectionChildDescription;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author peter
*/
public class CollectionChildDescriptionImpl extends DomChildDescriptionImpl implements DomCollectionChildDescription, AbstractCollectionChildDescription {
private final Collection<JavaMethod> myGetterMethods;
private final NotNullFunction<DomInvocationHandler, List<XmlTag>> myTagsGetter = new NotNullFunction<DomInvocationHandler, List<XmlTag>>() {
@Override
@NotNull
public List<XmlTag> fun(final DomInvocationHandler handler) {
XmlTag tag = handler.getXmlTag();
if (tag == null) {
return Collections.emptyList();
}
return DomImplUtil.findSubTags(tag, handler.createEvaluatedXmlName(getXmlName()), handler.getFile());
}
};
public CollectionChildDescriptionImpl(final XmlName tagName, final Type type, final Collection<JavaMethod> getterMethods) {
super(tagName, type);
myGetterMethods = getterMethods;
}
@Override
public String toString() {
return "CollectionChildDescription:" + getXmlName();
}
public NotNullFunction<DomInvocationHandler, List<XmlTag>> getTagsGetter() {
return myTagsGetter;
}
@Override
public DomElement addValue(@NotNull DomElement element) {
assert element.getGenericInfo().getCollectionChildrenDescriptions().contains(this);
return addChild(element, getType(), Integer.MAX_VALUE);
}
private DomElement addChild(final DomElement element, final Type type, final int index) {
try {
final DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
assert handler != null;
return handler.addCollectionChild(this, type, index);
}
catch (IncorrectOperationException e) {
throw new RuntimeException(e);
}
}
@Override
public DomElement addValue(@NotNull DomElement element, int index) {
return addChild(element, getType(), index);
}
@Override
public DomElement addValue(@NotNull DomElement parent, Type type) {
return addValue(parent, type, Integer.MAX_VALUE);
}
@Override
public final DomElement addValue(@NotNull DomElement parent, Type type, int index) {
return addChild(parent, type, index);
}
@Override
@Nullable
public final JavaMethod getGetterMethod() {
final Collection<JavaMethod> methods = myGetterMethods;
return methods.isEmpty() ? null : methods.iterator().next();
}
@Override
@NotNull
public List<? extends DomElement> getValues(@NotNull final DomElement element) {
final DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
if (handler != null) {
return handler.getCollectionChildren(this, myTagsGetter);
}
final JavaMethod getterMethod = getGetterMethod();
if (getterMethod == null) {
final Collection<DomElement> collection = ModelMergerUtil.getFilteredImplementations(element);
return ContainerUtil.concat(collection, new Function<DomElement, Collection<? extends DomElement>>() {
@Override
public Collection<? extends DomElement> fun(final DomElement domElement) {
final DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(domElement);
assert handler != null : domElement;
return handler.getCollectionChildren(CollectionChildDescriptionImpl.this, myTagsGetter);
}
});
}
return (List<? extends DomElement>)getterMethod.invoke(element, ArrayUtil.EMPTY_OBJECT_ARRAY);
}
@Override
@NotNull
public String getCommonPresentableName(@NotNull DomNameStrategy strategy) {
String words = strategy.splitIntoWords(getXmlElementName());
return StringUtil.capitalizeWords(words.endsWith("es") ? words: StringUtil.pluralize(words), true);
}
@Override
@Nullable
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
final JavaMethod method = getGetterMethod();
if (method != null) {
final T annotation = method.getAnnotation(annotationClass);
if (annotation != null) return annotation;
}
final Type elemType = getType();
return elemType instanceof AnnotatedElement ? ((AnnotatedElement)elemType).getAnnotation(annotationClass) : super.getAnnotation(annotationClass);
}
@Override
public List<XmlTag> getSubTags(final DomInvocationHandler handler, final XmlTag[] subTags, final XmlFile file) {
return DomImplUtil.findSubTags(subTags, handler.createEvaluatedXmlName(getXmlName()), file);
}
@Override
public EvaluatedXmlName createEvaluatedXmlName(final DomInvocationHandler parent, final XmlTag childTag) {
return parent.createEvaluatedXmlName(getXmlName());
}
}