@Nullable public static <T extends DomElement> DomCollectionChildDescription getChildDescription(final List<DomElement> contexts, Class<T> clazz) { if (contexts.size() == 0) { return null; } final DomElement context = contexts.get(0); final DomGenericInfo genericInfo = context.getGenericInfo(); final List<? extends DomCollectionChildDescription> descriptions = genericInfo.getCollectionChildrenDescriptions(); for (DomCollectionChildDescription description : descriptions) { final Type type = description.getType(); if (type.equals(clazz)) { return description; } } return null; }
public void testChildrenReflection() throws Throwable { final MyElement element = createElement("<a><child/><child-element/><child-element/></a>"); final DomGenericInfo info = element.getGenericInfo(); final DomFixedChildDescription foo = info.getFixedChildDescription("foo"); assertFixedChildDescription(foo, element.getFoo(), "foo"); final DomFixedChildDescription child = info.getFixedChildDescription("child"); assertFixedChildDescription(child, element.getChild(), "child"); final DomFixedChildDescription genericChild = info.getFixedChildDescription("generic-value"); assertGenericChildDescription(genericChild, element.getGenericValue(), "generic-value"); final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element"); assertEquals(element.getChildElements(), collectionChild.getValues(element)); assertEquals("child-element", collectionChild.getXmlElementName()); assertEquals(MyElement.class, collectionChild.getType()); assertEquals(MyElement.class.getMethod("getChildElements"), collectionChild.getGetterMethod().getMethod()); assertEquals(new HashSet(Arrays.asList(foo, child, collectionChild, genericChild, info.getAttributeChildrenDescriptions().get(0))), new HashSet(info.getChildrenDescriptions()) ); }
public void testAddChildrenByReflection() throws Throwable { final MyElement element = createElement("<a><child-element/></a>"); final DomGenericInfo info = element.getGenericInfo(); final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element"); final List<? extends DomElement> values = collectionChild.getValues(element); MyElement newChild = (MyElement) collectionChild.addValue(element); List<DomElement> newChildren = Arrays.asList(values.get(0), newChild); assertEquals(newChildren, element.getChildElements()); assertEquals(newChildren, collectionChild.getValues(element)); MyElement lastChild = (MyElement) collectionChild.addValue(element, 0); newChildren = Arrays.asList(lastChild, values.get(0), newChild); assertEquals(newChildren, element.getChildElements()); assertEquals(newChildren, collectionChild.getValues(element)); }
public void testChildrenReflection() throws Throwable { final MyElement element = createElement("<a><child/><child-element/><child-element/></a>"); final DomGenericInfo info = element.getGenericInfo(); final DomFixedChildDescription foo = info.getFixedChildDescription("foo"); assertFixedChildDescription(foo, element.getFoo(), "foo"); final DomFixedChildDescription child = info.getFixedChildDescription("child"); assertFixedChildDescription(child, element.getChild(), "child"); final DomFixedChildDescription genericChild = info.getFixedChildDescription("generic-value"); assertGenericChildDescription(genericChild, element.getGenericValue(), "generic-value"); final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element"); assertEquals(element.getChildElements(), collectionChild.getValues(element)); assertEquals("child-element", collectionChild.getXmlElementName()); assertEquals(MyElement.class, collectionChild.getType()); assertEquals(MyElement.class.getMethod("getChildElements"), collectionChild.getGetterMethod().getMethod()); assertEquals(new HashSet(Arrays.asList(foo, child, collectionChild, genericChild, info.getAttributeChildrenDescriptions().get(0))), new HashSet(info.getChildrenDescriptions())); }
private static Map<String, Pair<Type, Class>> getStaticallyRegisteredAttributes(final DomGenericInfo genericInfo) { final Map<String, Pair<Type, Class>> map = new HashMap<String, Pair<Type, Class>>(); for (DomAttributeChildDescription description : genericInfo.getAttributeChildrenDescriptions()) { final Type type = description.getType(); if (type instanceof ParameterizedType) { final Type[] typeArguments = ((ParameterizedType)type).getActualTypeArguments(); if (typeArguments.length == 1) { String name = description.getXmlElementName(); final Type attribType = typeArguments[0]; Class<? extends Converter> converterType = null; final Convert converterAnnotation = description.getAnnotation(Convert.class); if (converterAnnotation != null) { converterType = converterAnnotation.value(); } map.put(name.toLowerCase(Locale.US), new Pair<Type, Class>(attribType, converterType)); } } } return map; }
public void testFindChildDescriptionWithoutNamespace() throws Throwable { final DomGenericInfo info = getDomManager().getGenericInfo(MyListOrSet.class); assertNotNull(info.getAttributeChildDescription("attr")); assertNotNull(info.getAttributeChildDescription("attr").getType()); assertNotNull(info.getCollectionChildDescription("child")); assertNotNull(info.getCollectionChildDescription("child").getType()); assertNotNull(info.getFixedChildDescription("ref")); assertNotNull(info.getFixedChildDescription("ref").getType()); }
@Nullable private static DomExtension registerChild(DomExtensionsRegistrar registrar, DomGenericInfo elementInfo, String childName) { if (elementInfo.getCollectionChildDescription(childName) == null) { // register if not yet defined statically Class<? extends AntDomElement> modelClass = getModelClass(childName); if (modelClass == null) { modelClass = AntDomElement.class; } return registrar.registerCollectionChildrenExtension(new XmlName(childName), modelClass); } return null; }
@Override @NotNull public List<DomElementProblemDescriptor> checkRequired(final DomElement element, final DomElementAnnotationHolder holder) { final Required required = element.getAnnotation(Required.class); if (required != null) { final XmlElement xmlElement = element.getXmlElement(); if (xmlElement == null) { if (required.value()) { final String xmlElementName = element.getXmlElementName(); String namespace = element.getXmlElementNamespace(); if (element instanceof GenericAttributeValue) { return Collections.singletonList(holder.createProblem(element, IdeBundle.message("attribute.0.should.be.defined", xmlElementName), new DefineAttributeQuickFix(xmlElementName, namespace))); } return Collections.singletonList( holder.createProblem( element, HighlightSeverity.ERROR, IdeBundle.message("child.tag.0.should.be.defined", xmlElementName), new AddRequiredSubtagFix(xmlElementName, namespace) ) ); } } else if (element instanceof GenericDomValue) { return ContainerUtil.createMaybeSingletonList(checkRequiredGenericValue((GenericDomValue)element, required, holder)); } } if (DomUtil.hasXml(element)) { final SmartList<DomElementProblemDescriptor> list = new SmartList<DomElementProblemDescriptor>(); final DomGenericInfo info = element.getGenericInfo(); for (final AbstractDomChildrenDescription description : info.getChildrenDescriptions()) { if (description instanceof DomCollectionChildDescription && description.getValues(element).isEmpty()) { final DomCollectionChildDescription childDescription = (DomCollectionChildDescription)description; final Required annotation = description.getAnnotation(Required.class); if (annotation != null && annotation.value()) { list.add(holder.createProblem(element, childDescription, IdeBundle.message("child.tag.0.should.be.defined", ((DomCollectionChildDescription)description).getXmlElementName()))); } } } return list; } return Collections.emptyList(); }
@Override public final DomGenericInfo getGenericInfo(final Type type) { return myApplicationComponent.getStaticGenericInfo(type); }
@NotNull DomGenericInfo getGenericInfo();
@Override @NotNull public DomGenericInfo getGenericInfo() { throw new UnsupportedOperationException("Method getGenericInfo is not yet implemented in " + getClass().getName()); }
@NotNull public List<DomElementProblemDescriptor> checkRequired(final DomElement element, final DomElementAnnotationHolder holder) { final Required required = element.getAnnotation(Required.class); if (required != null) { final XmlElement xmlElement = element.getXmlElement(); if (xmlElement == null) { if (required.value()) { final String xmlElementName = element.getXmlElementName(); if (element instanceof GenericAttributeValue) { return Arrays.asList(holder.createProblem(element, IdeBundle.message("attribute.0.should.be.defined", xmlElementName))); } return Arrays.asList( holder.createProblem( element, HighlightSeverity.ERROR, IdeBundle.message("child.tag.0.should.be.defined", xmlElementName), new AddRequiredSubtagFix(xmlElementName, element.getXmlElementNamespace(), element.getParent().getXmlTag()) ) ); } } else if (element instanceof GenericDomValue) { return ContainerUtil.createMaybeSingletonList(checkRequiredGenericValue((GenericDomValue)element, required, holder)); } } if (DomUtil.hasXml(element)) { final SmartList<DomElementProblemDescriptor> list = new SmartList<DomElementProblemDescriptor>(); final DomGenericInfo info = element.getGenericInfo(); for (final AbstractDomChildrenDescription description : info.getChildrenDescriptions()) { if (description instanceof DomCollectionChildDescription && description.getValues(element).isEmpty()) { final DomCollectionChildDescription childDescription = (DomCollectionChildDescription)description; final Required annotation = description.getAnnotation(Required.class); if (annotation != null && annotation.value()) { list.add(holder.createProblem(element, childDescription, IdeBundle.message("child.tag.0.should.be.defined", ((DomCollectionChildDescription)description).getXmlElementName()))); } } } return list; } return Collections.emptyList(); }
public final DomGenericInfo getGenericInfo(final Type type) { return myApplicationComponent.getStaticGenericInfo(type); }
private static void defineAttributes(XmlTag xmlTag, DomExtensionsRegistrar registrar, DomGenericInfo genericInfo, AbstractIntrospector parentIntrospector) { final Map<String, Pair<Type, Class>> registeredAttribs = getStaticallyRegisteredAttributes(genericInfo); // define attributes discovered by introspector and not yet defined statically final Iterator<String> introspectedAttributes = parentIntrospector.getAttributesIterator(); while (introspectedAttributes.hasNext()) { final String attribName = introspectedAttributes.next(); if (genericInfo.getAttributeChildDescription(attribName) == null) { // if not defined yet final String _attribName = attribName.toLowerCase(Locale.US); final Pair<Type, Class> types = registeredAttribs.get(_attribName); Type type = types != null? types.getFirst() : null; Class converterClass = types != null ? types.getSecond() : null; if (type == null) { type = String.class; // use String by default final Class attributeType = parentIntrospector.getAttributeType(attribName); if (attributeType != null) { // handle well-known types if (File.class.isAssignableFrom(attributeType)) { type = PsiFileSystemItem.class; converterClass = AntPathConverter.class; } else if (Boolean.class.isAssignableFrom(attributeType)){ type = Boolean.class; converterClass = AntBooleanConverter.class; } else if (isAssignableFrom(ApacheAntClasses.Reference, attributeType)) { converterClass = AntDomRefIdConverter.class; } } } LOG.assertTrue(type != null); registerAttribute(registrar, attribName, type, converterClass); if (types == null) { // augment the map if this was a newly added attribute registeredAttribs.put(_attribName, new Pair<Type, Class>(type, converterClass)); } } } // handle attribute case problems: // additionaly register all attributes that exist in XML but differ from the registered ones only in case for (XmlAttribute xmlAttribute : xmlTag.getAttributes()) { final String existingAttribName = xmlAttribute.getName(); if (genericInfo.getAttributeChildDescription(existingAttribName) == null) { final Pair<Type, Class> pair = registeredAttribs.get(existingAttribName.toLowerCase(Locale.US)); if (pair != null) { // if such attribute should actually be here registerAttribute(registrar, existingAttribName, pair.getFirst(), pair.getSecond()); } } } }
public FixedChildColumnInfo(String name, DomGenericInfo info, @NonNls String tag, Icon icon) { super(name, info.getFixedChildDescription(tag), new IconTableCellRenderer(icon), new DefaultCellEditor(new JTextField())); }
/** * @param type Type. Only {@link Class} and {@link java.lang.reflect.ParameterizedType} are allowed * @return {@link com.intellij.util.xml.reflect.DomGenericInfo} instance for the desired type */ public abstract DomGenericInfo getGenericInfo(Type type);