/* * Copyright 2012 the original author or authors. * * 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 org.gradle.build.docs.dsl.docbook; import org.gradle.build.docs.dsl.docbook.model.ClassDoc; import org.gradle.build.docs.dsl.docbook.model.ExtraAttributeDoc; import org.gradle.build.docs.dsl.docbook.model.PropertyDoc; import org.gradle.build.docs.dsl.source.model.PropertyMetaData; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; import java.util.*; public class ClassDocPropertiesBuilder extends ModelBuilderSupport { private final JavadocConverter javadocConverter; private final GenerationListener listener; private static final Logger LOG = Logging.getLogger(ClassDocPropertiesBuilder.class); public ClassDocPropertiesBuilder(JavadocConverter javadocConverter, GenerationListener listener) { this.javadocConverter = javadocConverter; this.listener = listener; } /** * Builds the properties of the given class */ void build(ClassDoc classDoc) { Element thead = getChild(classDoc.getPropertiesTable(), "thead"); Element tr = getChild(thead, "tr"); List<Element> header = children(tr, "td"); if (header.size() < 1) { throw new RuntimeException(String.format("Expected at least 1 <td> in <thead>/<tr>, found: %s", header)); } Map<String, Element> inheritedValueTitleMapping = new HashMap<String, Element>(); List<Element> valueTitles = new ArrayList<Element>(); for (int i = 1; i < header.size(); i++) { Element element = header.get(i); Element override = findChild(element, "overrides"); if (override != null) { element.removeChild(override); inheritedValueTitleMapping.put(override.getTextContent(), element); } Node firstChild = element.getFirstChild(); if (firstChild instanceof Text) { firstChild.setTextContent(firstChild.getTextContent().replaceFirst("^\\s+", "")); } Node lastChild = element.getLastChild(); if (lastChild instanceof Text) { lastChild.setTextContent(lastChild.getTextContent().replaceFirst("\\s+$", "")); } valueTitles.add(element); } //adding the properties from the super class onto the inheriting class Map<String, PropertyDoc> props = new TreeMap<String, PropertyDoc>(); List<ClassDoc> superTypes = classDoc.getSuperTypes(); for (ClassDoc superType : superTypes) { LOG.info("Getting properties for {}", superType.getName()); for (PropertyDoc propertyDoc : superType.getClassProperties()) { Map<String, ExtraAttributeDoc> additionalValues = new LinkedHashMap<String, ExtraAttributeDoc>(); for (ExtraAttributeDoc attributeDoc : propertyDoc.getAdditionalValues()) { String key = attributeDoc.getKey(); if (inheritedValueTitleMapping.get(key) != null) { ExtraAttributeDoc newAttribute = new ExtraAttributeDoc(inheritedValueTitleMapping.get(key), attributeDoc.getValueCell()); additionalValues.put(newAttribute.getKey(), newAttribute); } else { additionalValues.put(key, attributeDoc); } } props.put(propertyDoc.getName(), propertyDoc.forClass(classDoc, additionalValues.values())); } } for (Element row : children(classDoc.getPropertiesTable(), "tr")) { List<Element> cells = children(row, "td"); if (cells.size() != header.size()) { throw new RuntimeException(String.format("Expected %s <td> elements in <tr>, found: %s", header.size(), tr)); } String propName = cells.get(0).getTextContent().trim(); PropertyMetaData property = classDoc.getClassMetaData().findProperty(propName); if (property == null) { throw new RuntimeException(String.format("No metadata for property '%s.%s'. Available properties: %s", classDoc.getName(), propName, classDoc.getClassMetaData().getPropertyNames())); } Map<String, ExtraAttributeDoc> additionalValues = new LinkedHashMap<String, ExtraAttributeDoc>(); if (!superTypes.isEmpty()) { PropertyDoc overriddenProp = props.get(propName); if (overriddenProp != null) { for (ExtraAttributeDoc attributeDoc : overriddenProp.getAdditionalValues()) { additionalValues.put(attributeDoc.getKey(), attributeDoc); } } } for (int i = 1; i < header.size(); i++) { if (cells.get(i).getFirstChild() == null) { continue; } ExtraAttributeDoc attributeDoc = new ExtraAttributeDoc(valueTitles.get(i - 1), cells.get(i)); additionalValues.put(attributeDoc.getKey(), attributeDoc); } PropertyDoc propertyDoc = new PropertyDoc(property, javadocConverter.parse(property, listener).getDocbook(), new ArrayList<ExtraAttributeDoc>(additionalValues.values())); if (propertyDoc.getDescription() == null) { throw new RuntimeException(String.format("Docbook content for '%s.%s' does not contain a description paragraph.", classDoc.getName(), propName)); } props.put(propName, propertyDoc); } for (PropertyDoc propertyDoc : props.values()) { classDoc.addClassProperty(propertyDoc); } } }