Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 63229 invoked from network); 4 Aug 2008 13:37:58 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 4 Aug 2008 13:37:58 -0000 Received: (qmail 4357 invoked by uid 500); 4 Aug 2008 13:37:57 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 4249 invoked by uid 500); 4 Aug 2008 13:37:57 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 4201 invoked by uid 99); 4 Aug 2008 13:37:56 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 06:37:56 -0700 X-ASF-Spam-Status: No, hits=-1996.5 required=10.0 tests=ALL_TRUSTED,URIBL_BLACK,WEIRD_PORT X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 13:27:06 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id C2BC12388988; Mon, 4 Aug 2008 06:27:03 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r682379 - in /cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin: ./ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/cocoon/ src/main/java/org/apache/cocoon/maven/ src/main/java/org/apache/cocoon/maven/do... Date: Mon, 04 Aug 2008 13:27:03 -0000 To: cvs@cocoon.apache.org From: felixk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080804132703.C2BC12388988@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: felixk Date: Mon Aug 4 06:27:02 2008 New Revision: 682379 URL: http://svn.apache.org/viewvc?rev=682379&view=rev Log: The mojo and some docs Added: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java (with props) cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/index.apt cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/usage.apt cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml (with props) Modified: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/ (props changed) cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/pom.xml Propchange: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Mon Aug 4 06:27:02 2008 @@ -2,3 +2,5 @@ .settings .classpath .project +.externalToolBuilders +maven-eclipse.xml Modified: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/pom.xml URL: http://svn.apache.org/viewvc/cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/pom.xml?rev=682379&r1=682378&r2=682379&view=diff ============================================================================== --- cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/pom.xml (original) +++ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/pom.xml Mon Aug 4 06:27:02 2008 @@ -7,9 +7,9 @@ to you 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 - + + 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 @@ -18,7 +18,10 @@ under the License. --> - + 4.0.0 @@ -156,12 +159,6 @@ runtime - xerces - xmlParserAPIs - 2.6.2 - runtime - - avalon-framework avalon-framework-api 4.2.0 @@ -174,23 +171,15 @@ org.apache.maven - maven-artifact - - - org.apache.maven maven-model org.apache.maven - maven-artifact - - - org.apache.maven maven-project - org.apache.maven.plugins - maven-war-plugin + org.apache.maven + maven-settings @@ -237,9 +226,9 @@ ??? cdocs-maven-plugin - false - - + false + + Added: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java URL: http://svn.apache.org/viewvc/cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java?rev=682379&view=auto ============================================================================== --- cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java (added) +++ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java Mon Aug 4 06:27:02 2008 @@ -0,0 +1,709 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.cocoon.maven.documentation.daisy; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.outerj.daisy.htmlcleaner.HtmlCleanerFactory; +import org.outerj.daisy.htmlcleaner.HtmlCleanerTemplate; +import org.outerj.daisy.repository.CollectionManager; +import org.outerj.daisy.repository.CollectionNotFoundException; +import org.outerj.daisy.repository.Credentials; +import org.outerj.daisy.repository.Document; +import org.outerj.daisy.repository.DocumentCollection; +import org.outerj.daisy.repository.Repository; +import org.outerj.daisy.repository.RepositoryException; +import org.outerj.daisy.repository.RepositoryManager; +import org.outerj.daisy.repository.clientimpl.RemoteRepositoryManager; +import org.outerj.daisy.repository.query.QueryHelper; +import org.outerx.daisy.x10.SearchResultDocument; +import org.xml.sax.InputSource; + +import com.thoughtworks.qdox.JavaDocBuilder; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.JavaClass; + +/** + * A plugin to sync the information about sitemap components from the Java + * sources to the Daisy documentation, supports custom annotations using + * cocoon.sitemap.* tags. + * + * Since you normally never use sitemap components by their Java API, but rather + * just from the sitemap, it makes more sense to document these components in + * Daisy. This makes it easier to manage longer and better formatted + * documentation, and doesn't scare non-Java-developers away from Cocoon. + * + * The sync tool takes a few special javadoc-style annotations into account: + * + *
+ * @cocoon.sitemap.component.name
+ *    default name with which this component is declared in the sitemap
+ * <p/>
+ * @cocoon.sitemap.component.documentation.disabled
+ *    excludes the component from the documentation
+ * <p/>
+ * @cocoon.sitemap.component.documentation
+ *    A short (one-paragraph) description of the component.
+ *    Can contain HTML markup (preferably only inline tags).
+ * <p/>
+ * @cocoon.sitemap.component.documentation.caching
+ *    A comment about the caching of this component. The cacheability of the
+ *    component is figured out automatially by its implemented interfaces, but
+ *    this tag allows to provide a short comment on the chaching conditions.
+ *    This is mapped to a field in Daisy, thus should not contain HTML markup.
+ * 
+ * + * The tool will not update documents unnecessarily, to avoid generating new + * document versions in Daisy each time it is run.

Reuses some ideas from + * the Ant SitemapTask in Cocoon 2.1. + * + * @goal sitemaptags2daisy + */ +public class SitemapTagsToDaisyMojo extends AbstractMojo { + /** + * POM + * + * @parameter expression="${project}" + * @readonly + * @required + */ + protected MavenProject project; + + /** + * The id of the the daisy server. It is used to look up the server + * configuration from settings.xml. + * + * @parameter expression="${daisyServerId}" default-value="cocoon-daisy" + * @required + */ + protected String daisyServerId; + + /** + * Run in simulate mode (won't update documents). Values are 'true|false'. + * + * @parameter expression="${simulateInput}" default-value=false + * @required + */ + protected Boolean simulateInput; + + /** + * The current user system settings for use in Maven. + * + * @parameter expression="${settings}" + * @required + * @readonly + */ + protected Settings settings; + + /** + * The URL of the Daisy repository server. + * + * @parameter expression="${repoUrl}" + * default-value="http://cocoon.zones.apache.org:9263" + * @required + */ + protected String repoUrl; + + private static final String GENERATOR = "org.apache.cocoon.generation.Generator"; + private static final String TRANSFORMER = "org.apache.cocoon.transformation.Transformer"; + private static final String SERIALIZER = "org.apache.cocoon.serialization.Serializer"; + private static final String READER = "org.apache.cocoon.reading.Reader"; + private static final String MATCHER = "org.apache.cocoon.matching.Matcher"; + private static final String SELECTOR = "org.apache.cocoon.selection.Selector"; + private static final String ACTION = "org.apache.cocoon.acting.Action"; + private static final String PIPELINE = "org.apache.cocoon.components.pipeline.ProcessingPipeline"; + + private static final String CACHEABLE = "org.apache.cocoon.caching.CacheableProcessingComponent"; + private static final String DEPRECATED_CACHEABLE = "org.apache.cocoon.caching.Cacheable"; + + /** The name of the component in the sitemap (required) */ + public static final String NAME_TAG = "cocoon.sitemap.component.name"; + /** If this tag is specified no documentation is generated (optional) */ + public static final String NO_DOC_TAG = "cocoon.sitemap.component.documentation.disabled"; + /** The documentation (optional) */ + public static final String DOC_TAG = "cocoon.sitemap.component.documentation"; + /** Caching info (optional) */ + public static final String CACHING_INFO_TAG = "cocoon.sitemap.component.documentation.caching"; + + private static final String DAISY_BLOCK_FIELD = "CocoonBlock"; + private static final String DAISY_CLASSNAME_FIELD = "JavaClassName"; + private static final String DAISY_COMPONENT_TYPE_FIELD = "CocoonComponentReference"; + private static final String DAISY_CACHEABLE_FIELD = "SitemapComponentCacheabilityInfo"; + private static final String DAISY_DEPRECATED_FIELD = "SitemapComponentDeprecationInfo"; + private static final String DAISY_COMPONENT_NAME_FIELD = "SitemapComponentName"; + private static final String DAISY_SHORTDESCR_PART = "SitemapComponentShortDescription"; + private static final String DAISY_DOCTYPE = "SitemapComponent"; + + private static final String COLLECTION_PREFIX = "cdocs-"; + + private HtmlCleanerTemplate htmlCleanerTemplate; + private Repository daisyRepository; + private boolean simulate; + + /** + * @throws MojoExecutionException + */ + public void execute() throws MojoExecutionException { + getLog() + .info( + "This is the source annotations to Daisy documents sync tool for sitemap components."); + + if (!this.settings.isOffline()) { + try { + File rootDir = project.getBasedir(); + getLog() + .info("Path to the Cocoon source directory: " + rootDir); + File cocoonCoreDir = new File(new File(rootDir, "core"), + "cocoon-core"); + if (!cocoonCoreDir.exists()) { + throw new MojoExecutionException( + "This is not a valid Cocoon source directory, did not find the following path: " + + cocoonCoreDir.getPath()); + } + + // Normalize path + String rootPath = rootDir.getPath(); + + setupHtmlCleanerTemplate(); + + Server server = this.settings.getServer(this.daisyServerId); + if (server == null) { + throw new MojoExecutionException( + "You have to configure the Daisy CMS server with the id '" + + this.daisyServerId + + "' in your settings.xml file."); + } + + setupDaisyRepositoryClient(repoUrl, server.getUsername(), + server.getPassword()); + + JavaDocBuilder javaDocBuilder = getJavaDocBuilder(rootPath); + + JavaClass[] allClasses = javaDocBuilder.getClasses(); + int newDocs = 0; + int updatedDocs = 0; + int unmodifiedDocs = 0; + + try { + for (int i = 0; i < allClasses.length; i++) { + JavaClass currentClass = allClasses[i]; + if (!currentClass.isAbstract() + && !currentClass.isPrivate() + && !currentClass.isProtected() + && !currentClass.isInterface() + && !currentClass.isInner()) { + String componentType = getComponentTypeName(currentClass); + if (componentType != null) { + if (currentClass.getTagByName(NO_DOC_TAG) != null) + continue; + + String blockName = determineBlock(rootPath, + currentClass); + if (blockName == null) + continue; + + ComponentDocs docs = getComponentDocs( + currentClass, componentType, blockName); + + Document daisyDoc = getDaisyDoc(docs); + if (daisyDoc == null) { + getLog() + .info( + "Creating the document for " + + currentClass + .getFullyQualifiedName()); + createDocument(docs, currentClass.getName()); + newDocs++; + } else { + ComponentDocs oldDocs = getComponentDocs(daisyDoc); + boolean collectionsNeedUpdating = updateCollections( + daisyDoc, blockName); + if (collectionsNeedUpdating + || !docs.equals(oldDocs)) { + getLog() + .info( + "Will update the document for " + + currentClass + .getFullyQualifiedName()); + updateDocument(daisyDoc, docs); + updatedDocs++; + } else { + getLog() + .info( + "No update required for " + + currentClass + .getFullyQualifiedName()); + unmodifiedDocs++; + } + } + } + } + } + } finally { + getLog().info("New documents: " + newDocs); + getLog().info("Updated documents: " + updatedDocs); + getLog().info("Unmodified documents: " + unmodifiedDocs); + } + } catch (Exception e) { + throw new MojoExecutionException("SitemapTagsToDaisy failed.", + e); + } + } else { + getLog() + .info( + "Daisy documentation can't be synced when maven is run in offline mode. Nothing will be done."); + } + } + + private JavaDocBuilder getJavaDocBuilder(String rootPath) { + File rootFile = new File(rootPath); + + getLog().info("Searching java directories in " + rootPath + " ..."); + List javaDirs = new ArrayList(100); + collectJavaDirs(javaDirs, rootFile); + getLog().info("Found " + javaDirs.size() + " java directories."); + + JavaDocBuilder javaDocBuilder = new JavaDocBuilder(); + Iterator javaDirsIt = javaDirs.iterator(); + getLog().info("Parsing sources ..."); + while (javaDirsIt.hasNext()) { + File currentDir = (File) javaDirsIt.next(); + getLog().info("Parsing sources in " + currentDir.getPath()); + javaDocBuilder.addSourceTree(currentDir); + } + getLog().info("Done parsing sources."); + + return javaDocBuilder; + } + + private void collectJavaDirs(List javaDirs, File currentDir) { + File[] files = currentDir.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + if (files[i].getName().equals("java")) { + javaDirs.add(files[i]); + } else { + collectJavaDirs(javaDirs, files[i]); + } + } + } + } + + private String getComponentTypeName(JavaClass javaClass) { + if (javaClass.isA(GENERATOR)) { + return "Generator"; + } else if (javaClass.isA(TRANSFORMER)) { + return "Transformer"; + } else if (javaClass.isA(READER)) { + return "Reader"; + } else if (javaClass.isA(SERIALIZER)) { + return "Serializer"; + } else if (javaClass.isA(ACTION)) { + return "Action"; + } else if (javaClass.isA(MATCHER)) { + return "Matcher"; + } else if (javaClass.isA(SELECTOR)) { + return "Selector"; + } else if (javaClass.isA(PIPELINE)) { + return "Pipe"; + } else { + return null; + } + } + + /** + * Extracts the block name from the directory name. + */ + private String determineBlock(String rootPath, JavaClass javaClass) { + String path = javaClass.getSource().getURL().getPath(); + if (!path.startsWith(rootPath)) + return null; + + String subPath = path.substring(rootPath.length()); + if (subPath.startsWith("/")) + subPath = subPath.substring(1); + + if (subPath.startsWith("blocks/")) + subPath = subPath.substring("blocks/".length()); + else if (subPath.startsWith("blocks-tobeconverted/")) + subPath = subPath.substring("blocks-tobeconverted/".length()); + else if (subPath.startsWith("core/")) + return "core"; // all subprojects below core are considered to be + // block "core" + else + return null; + + if (!subPath.startsWith("cocoon-")) + return null; + + int slashPos = subPath.indexOf("/"); + if (slashPos == -1) // very unlikely + return null; + + String blockName = subPath.substring("cocoon-".length(), slashPos); + return blockName; + } + + /** + * This class contains the information that is synced from the source file + * to a Daisy document. + */ + static class ComponentDocs { + /** The name of the block in which this component occurs. */ + String blockName; + /** Fully-qualified Java class name of the component. */ + String className; + /** Component type: generator, transformer, etc. */ + String componentType; + /** Short component name as used in the sitemamp. */ + String componentName; + /** The short description of this component, as HTML. */ + String documentation; + /** Information about the caceability of this component. */ + String cacheInfo; + /** Deprecated info about this component. */ + String deprecated; + + public boolean equals(Object obj) { + ComponentDocs other = (ComponentDocs) obj; + if (!safeComp(blockName, other.blockName)) + return false; + if (!safeComp(className, other.className)) + return false; + if (!safeComp(componentType, other.componentType)) + return false; + if (!safeComp(componentName, other.componentName)) + return false; + if (!safeComp(documentation, other.documentation)) + return false; + if (!safeComp(cacheInfo, other.cacheInfo)) + return false; + if (!safeComp(deprecated, other.deprecated)) + return false; + return true; + } + + private boolean safeComp(String value1, String value2) { + if (value1 == null && value2 == null) + return true; + if (value1 == null || value2 == null) + return false; + else + return value1.equals(value2); + } + } + + /** + * Gets a {@link ComponentDocs} instance by extracting info from a Java + * source file. + */ + private ComponentDocs getComponentDocs(JavaClass javaClass, + String componentType, String blockName) throws Exception { + ComponentDocs componentDocs = new ComponentDocs(); + componentDocs.componentType = componentType; + componentDocs.className = javaClass.getFullyQualifiedName(); + componentDocs.blockName = blockName; + + DocletTag documentationTag = javaClass.getTagByName(DOC_TAG); + if (documentationTag != null) { + String documentation = documentationTag.getValue(); + if (documentation != null) { + componentDocs.documentation = cleanupDocumentation(documentation); + } + } + + // Sitemap component name + DocletTag nameTag = javaClass.getTagByName(NAME_TAG); + if (nameTag != null) + componentDocs.componentName = nameTag.getValue(); + + // Deprecated + DocletTag deprecatedTag = javaClass.getTagByName("deprecated"); + if (deprecatedTag != null) { + if (deprecatedTag.getValue() != null) { + componentDocs.deprecated = limitLength("Yes: " + + deprecatedTag.getValue()); + } else { + componentDocs.deprecated = "Yes."; + } + } + + // Caching + if (javaClass.isA(GENERATOR) || javaClass.isA(TRANSFORMER) + || javaClass.isA(SERIALIZER) || javaClass.isA(READER)) { + String cacheInfo; + if (javaClass.isA(CACHEABLE)) { + cacheInfo = getTagValue(javaClass, CACHING_INFO_TAG, null); + if (cacheInfo != null) { + cacheInfo = limitLength("Yes - " + cacheInfo); + } else { + cacheInfo = "Yes"; + } + } else if (javaClass.isA(DEPRECATED_CACHEABLE)) { + cacheInfo = getTagValue(javaClass, CACHING_INFO_TAG, null); + if (cacheInfo != null) { + cacheInfo = limitLength("Yes (2.0 Caching) - " + cacheInfo); + } else { + cacheInfo = "Yes (2.0 Caching)"; + } + } else { + cacheInfo = "No"; + } + componentDocs.cacheInfo = cacheInfo; + } + + return componentDocs; + } + + private String getTagValue(JavaClass javaClass, String tagName, + String defaultValue) { + final DocletTag tag = javaClass.getTagByName(tagName); + if (tag != null) { + return tag.getValue(); + } + return defaultValue; + } + + private String limitLength(String value) { + if (value.length() > 254) + return value.substring(0, 254); + else + return value; + } + + private String cleanupDocumentation(String documentation) throws Exception { + // tag is often used but not handled by Daisy, translate it to + // + documentation = documentation.replaceAll("", ""); + documentation = documentation.replaceAll("", ""); + + // make it into a complete HTML doc + documentation = "" + documentation + ""; + + // pull it through a HTMLCleaner + return htmlCleanerTemplate.newHtmlCleaner() + .cleanToString(documentation); + } + + private void setupHtmlCleanerTemplate() throws Exception { + InputStream is = null; + try { + is = getClass().getClassLoader().getResourceAsStream( + "org/apache/cocoon/documentation/daisy/htmlcleaner.xml"); + htmlCleanerTemplate = new HtmlCleanerFactory() + .buildTemplate(new InputSource(is)); + } finally { + if (is != null) + is.close(); + } + } + + private void setupDaisyRepositoryClient(String url, String username, + String password) throws Exception { + RepositoryManager repositoryManager = new RemoteRepositoryManager(url, + new Credentials(username, password)); + this.daisyRepository = repositoryManager.getRepository(new Credentials( + username, password)); + } + + /** + * Gets the Daisy document for a certain component, based on a field + * containing the fully qualified class name. Returns null if there is no + * such document, throws an exception if there are multiple such documents. + */ + private Document getDaisyDoc(ComponentDocs docs) throws Exception { + String query = "select id where documentType = " + + QueryHelper.formatString(DAISY_DOCTYPE) + + " and $JavaClassName = " + + QueryHelper.formatString(docs.className); + SearchResultDocument.SearchResult.Rows.Row[] rows = daisyRepository + .getQueryManager().performQuery(query, Locale.US) + .getSearchResult().getRows().getRowArray(); + if (rows.length == 0) { + return null; + } else if (rows.length > 1) { + throw new Exception( + "There are multiple documents in Daisy for the class " + + docs.className + ". Please correct this first."); + } else { + return daisyRepository.getDocument(rows[0].getDocumentId(), rows[0] + .getBranchId(), rows[0].getLanguageId(), true); + } + } + + /** + * Gets a {@link ComponentDocs} instance from a Daisy document. + */ + private ComponentDocs getComponentDocs(Document daisyDoc) throws Exception { + ComponentDocs docs = new ComponentDocs(); + + if (daisyDoc.hasField(DAISY_BLOCK_FIELD)) + docs.blockName = (String) daisyDoc.getField(DAISY_BLOCK_FIELD) + .getValue(); + + if (daisyDoc.hasField(DAISY_CACHEABLE_FIELD)) + docs.cacheInfo = (String) daisyDoc.getField(DAISY_CACHEABLE_FIELD) + .getValue(); + + if (daisyDoc.hasField(DAISY_CLASSNAME_FIELD)) + docs.className = (String) daisyDoc.getField(DAISY_CLASSNAME_FIELD) + .getValue(); + + if (daisyDoc.hasField(DAISY_COMPONENT_NAME_FIELD)) + docs.componentName = (String) daisyDoc.getField( + DAISY_COMPONENT_NAME_FIELD).getValue(); + + if (daisyDoc.hasField(DAISY_COMPONENT_TYPE_FIELD)) + docs.componentType = (String) daisyDoc.getField( + DAISY_COMPONENT_TYPE_FIELD).getValue(); + + if (daisyDoc.hasField(DAISY_DEPRECATED_FIELD)) + docs.deprecated = (String) daisyDoc + .getField(DAISY_DEPRECATED_FIELD).getValue(); + + if (daisyDoc.hasPart(DAISY_SHORTDESCR_PART)) + docs.documentation = new String(daisyDoc.getPart( + DAISY_SHORTDESCR_PART).getData(), "UTF-8"); + + return docs; + } + + /** + * Updates the Daisy collections the document belongs too, if needed, and + * returns true if updated. + */ + private boolean updateCollections(Document daisyDoc, String blockName) + throws Exception { + if (blockName != null) { + boolean belongsToRequiredCollection = false; + boolean updated = false; + String expectedCollection = COLLECTION_PREFIX + blockName; + + DocumentCollection[] collections = daisyDoc.getCollections() + .getArray(); + for (int i = 0; i < collections.length; i++) { + String collectionName = collections[i].getName(); + if (collectionName.equals(expectedCollection)) { + belongsToRequiredCollection = true; + } else if (collectionName.startsWith(COLLECTION_PREFIX)) { + // belongs to cdocs- collection it shouldn't belong too + updated = true; + daisyDoc.removeFromCollection(collections[i]); + } + } + + if (!belongsToRequiredCollection) { + DocumentCollection collection = null; + CollectionManager collectionManager = daisyRepository + .getCollectionManager(); + try { + try { + collection = collectionManager.getCollectionByName( + expectedCollection, false); + } catch (CollectionNotFoundException e) { + // ok, collection will be null + } + + if (collection == null) { + getLog().info( + "Will create collection " + expectedCollection); + if (!simulate) { + collection = collectionManager + .createCollection(expectedCollection); + collection.save(); + } + } + } catch (RepositoryException e) { + throw new Exception( + "Error trying to get or create the collection " + + expectedCollection, e); + } + + if (!simulate) // when in simulate mode, collection might not + // have been created + daisyDoc.addToCollection(collection); + + updated = true; + } + + return updated; + } else { + return false; + } + } + + private void updateDocument(Document daisyDoc, ComponentDocs docs) + throws Exception { + updateField(daisyDoc, DAISY_BLOCK_FIELD, docs.blockName); + updateField(daisyDoc, DAISY_CACHEABLE_FIELD, docs.cacheInfo); + updateField(daisyDoc, DAISY_CLASSNAME_FIELD, docs.className); + updateField(daisyDoc, DAISY_COMPONENT_NAME_FIELD, docs.componentName); + updateField(daisyDoc, DAISY_COMPONENT_TYPE_FIELD, docs.componentType); + updateField(daisyDoc, DAISY_DEPRECATED_FIELD, docs.deprecated); + + if (docs.documentation != null) { + boolean setPart = false; + if (daisyDoc.hasPart(DAISY_SHORTDESCR_PART)) { + String oldDescr = new String(daisyDoc.getPart( + DAISY_SHORTDESCR_PART).getData(), "UTF-8"); + // Note: for parts we need to check ourselves if the content has + // not changed + // (in contrasts to fields, for which Daisy does the comparison + // itself) + if (!oldDescr.equals(docs.documentation)) { + setPart = true; + } + } else { + setPart = true; + } + if (setPart) + daisyDoc.setPart(DAISY_SHORTDESCR_PART, "text/xml", + docs.documentation.getBytes("UTF-8")); + } else if (daisyDoc.hasPart(DAISY_SHORTDESCR_PART)) { + daisyDoc.deletePart(DAISY_SHORTDESCR_PART); + } + + if (!simulate) + daisyDoc.save(); + } + + private void createDocument(ComponentDocs docs, String name) + throws Exception { + Document daisyDoc = daisyRepository.createDocument(name, DAISY_DOCTYPE); + updateCollections(daisyDoc, docs.blockName); + updateDocument(daisyDoc, docs); + } + + private void updateField(Document daisyDoc, String fieldName, String value) + throws Exception { + if (value != null) + daisyDoc.setField(fieldName, value); + else if (daisyDoc.hasField(fieldName)) + daisyDoc.deleteField(fieldName); + } + +} Propchange: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/main/java/org/apache/cocoon/maven/documentation/daisy/SitemapTagsToDaisyMojo.java ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/index.apt URL: http://svn.apache.org/viewvc/cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/index.apt?rev=682379&view=auto ============================================================================== --- cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/index.apt (added) +++ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/index.apt Mon Aug 4 06:27:02 2008 @@ -0,0 +1,49 @@ + ------ + Cocoon SitemapTagsToDaisy Plugin + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you 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. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/guides/mini/guide-apt-format.html + +Overview + + The plugin is a tool to sync information about sitemap components to + Daisy documents. + + Since you normally never use sitemap components by their Java API, but rather + just from the sitemap, it makes more sense to document these components in + Daisy. This makes it easier to manage longer and better formatted documentation, + and doesn't scare non-Java-developers away from Cocoon. + +* Goals Overview + + The SitemapTagsToDaisy Plugin only has one goal. + + * {{{sitemaptags2daisy-mojo.html}cocoon-sitemaptags2daisy:sitemaptags2daisy}} attempts to + sync cocoon.sitemap annotations with documents in Daisy. + The plugin will not update documents unnecessarily, to avoid generating + new document versions in Daisy each time it is run. + +* Usage + + Instructions on the basic usage of the SitemapTagsToDaisy Plugin can be found + {{{usage.html}here}}. + + [] Added: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/usage.apt URL: http://svn.apache.org/viewvc/cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/usage.apt?rev=682379&view=auto ============================================================================== --- cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/usage.apt (added) +++ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/apt/usage.apt Mon Aug 4 06:27:02 2008 @@ -0,0 +1,25 @@ + ------ + Cocoon SitemapTagsToDaisy Plugin + ------ + +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you 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. + +~~ NOTE: For help with the syntax of this file, see: +~~ http://maven.apache.org/guides/mini/guide-apt-format.html + +TODO Added: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml URL: http://svn.apache.org/viewvc/cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml?rev=682379&view=auto ============================================================================== --- cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml (added) +++ cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml Mon Aug 4 06:27:02 2008 @@ -0,0 +1,29 @@ + + + + + +

+ + + + + + + + \ No newline at end of file Propchange: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/whiteboard/cocoon-sitemaptags2daisy-plugin/src/site/site.xml ------------------------------------------------------------------------------ svn:keywords = Id