From 6ac6c922ba0db2c398652655dd857c6d556fe3bd Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 04 Apr 2016 14:34:30 +0000
Subject: [PATCH] Restore accidentally deleted ConfigGuideGeneration

---
 opendj-server-legacy/src/main/java/org/opends/server/admin/doc/package-info.java          |   28 +
 opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java | 1606 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1,634 insertions(+), 0 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java
new file mode 100644
index 0000000..284e89b
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java
@@ -0,0 +1,1606 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2007-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011-2016 ForgeRock AS.
+ */
+package org.opends.server.admin.doc;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.ACIPropertyDefinition;
+import org.forgerock.opendj.config.AbsoluteInheritedDefaultBehaviorProvider;
+import org.forgerock.opendj.config.AbstractManagedObjectDefinition;
+import org.forgerock.opendj.config.AdministratorAction.Type;
+import org.forgerock.opendj.config.AggregationPropertyDefinition;
+import org.forgerock.opendj.config.AliasDefaultBehaviorProvider;
+import org.forgerock.opendj.config.AttributeTypePropertyDefinition;
+import org.forgerock.opendj.config.BooleanPropertyDefinition;
+import org.forgerock.opendj.config.ClassPropertyDefinition;
+import org.forgerock.opendj.config.ConfigurationFramework;
+import org.forgerock.opendj.config.DNPropertyDefinition;
+import org.forgerock.opendj.config.DefaultBehaviorProvider;
+import org.forgerock.opendj.config.DefinedDefaultBehaviorProvider;
+import org.forgerock.opendj.config.DurationPropertyDefinition;
+import org.forgerock.opendj.config.EnumPropertyDefinition;
+import org.forgerock.opendj.config.IPAddressMaskPropertyDefinition;
+import org.forgerock.opendj.config.IPAddressPropertyDefinition;
+import org.forgerock.opendj.config.IntegerPropertyDefinition;
+import org.forgerock.opendj.config.LDAPProfile;
+import org.forgerock.opendj.config.ManagedObjectOption;
+import org.forgerock.opendj.config.PropertyDefinition;
+import org.forgerock.opendj.config.PropertyDefinitionVisitor;
+import org.forgerock.opendj.config.PropertyOption;
+import org.forgerock.opendj.config.RelationDefinition;
+import org.forgerock.opendj.config.RelationOption;
+import org.forgerock.opendj.config.RelativeInheritedDefaultBehaviorProvider;
+import org.forgerock.opendj.config.SizePropertyDefinition;
+import org.forgerock.opendj.config.StringPropertyDefinition;
+import org.forgerock.opendj.config.Tag;
+import org.forgerock.opendj.config.TopCfgDefn;
+import org.forgerock.opendj.config.UndefinedDefaultBehaviorProvider;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.server.config.meta.RootCfgDefn;
+import org.opends.server.util.EmbeddedUtils;
+import org.opends.server.util.DynamicConstants;
+
+/**
+ * This class allow Configuration Guide documentation generation (html format).
+ * It is based on the Admin Framework Introspection API
+ */
+public class ConfigGuideGeneration {
+
+  // Note : still to be done :
+  // I18n support. Today all the strings are hardcoded in this file
+
+  private static final String ACI_SYNTAX_REL_URL =
+    "/doc/admin-guide/#about-acis";
+  private static final String DURATION_SYNTAX_REL_URL =
+    "duration-syntax.html";
+  private final String CSS_FILE = "opendj-config.css";
+
+  private final String MAIN_FILE = "index.html";
+  private final String INHERITANCE_TREE_FILE =
+    "ManagedObjectInheritanceTree.html";
+  private final String RELATION_TREE_FILE = "ManagedObjectRelationTree.html";
+  private final String MO_LIST_FILE = "ManagedObjectList.html";
+  private final String PROPERTIES_INDEX_FILE = "PropertiesIndex.html";
+  private final String WELCOME_FILE = "welcome.html";
+  private final String MAINTOP_FILE = "maintop.html";
+  private final String INDEX_FILE = "index.html";
+  private final String FAVICON = "http://forgerock.org/favicon.ico";
+
+  private static final String CONFIG_GUIDE_DIR = "opendj_config_guide";
+  private final String MAIN_FRAME = "mainFrame";
+
+  /**
+   * Entry point for documentation generation.
+   *
+   * Properties:
+   * GenerationDir - The directory where the doc is generated
+   *              (default is /var/tmp/[CONFIG_GUIDE_DIR>])
+   * LdapMapping - Presence means that the LDAP mapping section is to be
+   *               generated (default is no)
+   * OpenDJWiki - The URL of the OpenDJ Wiki
+   *              (default is
+   *              "http://wikis.forgerock.org/confluence/display/OPENDJ")
+   * OpenDJHome - The URL of the OpenDJ project Home page
+   *              (default is "http://opendj.forgerock.org")
+   *
+   * @param args none.
+   */
+  public static void main(String[] args) {
+    Properties properties = System.getProperties();
+    generationDir = properties.getProperty("GenerationDir");
+    if (generationDir == null) {
+      // Default dir is prefixed by the system-dependent default temporary dir
+      generationDir = System.getProperty("java.io.tmpdir") + File.separator +
+        CONFIG_GUIDE_DIR;
+    }
+    // Create new dir if necessary
+    try {
+      new File(generationDir).mkdir();
+    } catch (Exception e) {
+      e.printStackTrace();
+      System.exit(1);
+    }
+    System.out.println("Generation directory is : " + generationDir);
+
+    if (properties.getProperty("LdapMapping") != null) {
+      ldapMapping = true;
+    }
+
+    OpenDJWiki = properties.getProperty("OpenDJWiki");
+    if (OpenDJWiki == null) {
+      // Default is current wiki
+      OpenDJWiki = "http://wikis.forgerock.org/confluence/display/OPENDJ";
+    }
+
+    OpenDJHome = properties.getProperty("OpenDJHome");
+    if (OpenDJHome == null) {
+      // Default is current OpenDJ project home
+      OpenDJHome = "http://opendj.forgerock.org";
+    }
+
+    aciSyntaxPage = OpenDJHome + ACI_SYNTAX_REL_URL;
+    durationSyntaxPage = DURATION_SYNTAX_REL_URL;
+
+    ConfigGuideGeneration myGen = new ConfigGuideGeneration();
+    myGen.generate();
+  }
+
+  private void generate() {
+    init();
+
+    genManagedObjectRelationTree(catTopRelList);
+    genManagedObjectInheritanceTree(catTopMoList);
+    genAllManagedObject(topMoList);
+    genManagedObjectList(moList);
+    genPropertiesIndex();
+    genIndexPage();
+    genMainTopPage();
+    genWelcomePage();
+   }
+
+  private void init() {
+
+    // Build a list of top relations
+    RootCfgDefn rootCfg = RootCfgDefn.getInstance();
+    for (RelationDefinition rel : rootCfg.getAllRelationDefinitions()) {
+      topRelList.put(rel.getChildDefinition().getName(), rel);
+    }
+
+    // Enable the client-side class loader to explicitly load classes
+    // which are not directly reachable from the root configuration
+    EmbeddedUtils.initializeForClientUse();
+    // Bootstrap definition classes.
+    try {
+      ConfigurationFramework.getInstance().initialize();
+    } catch (ConfigException e) {
+      System.err.println("ERROR : Cannot enable the client-side class loader.");
+      e.printStackTrace();
+      System.exit(1);
+    }
+    // Switch off class name validation in client.
+//    ClassPropertyDefinition.setAllowClassValidation(false);
+    // Switch off attribute type name validation in client.
+//    AttributeTypePropertyDefinition.setCheckSchema(false);
+
+    // Build a sorted list of top managed objects
+    TopCfgDefn topCfg = TopCfgDefn.getInstance();
+    Collection<AbstractManagedObjectDefinition<?, ?>> topObjects =
+      topCfg.getChildren();
+    for (AbstractManagedObjectDefinition topObject : topObjects) {
+      if (topObject.getName().equals("")) {
+        // root
+        continue;
+      }
+      if (topObject.hasOption(ManagedObjectOption.HIDDEN))
+      {
+        continue;
+      }
+      topMoList.put(topObject.getName(), topObject);
+    }
+
+
+    // Build a list of top relations by category (core, database, ...)
+    for (RelationDefinition rel : topRelList.values()) {
+      AbstractManagedObjectDefinition<?, ?> mo = rel.getChildDefinition();
+      Collection<Tag> tags = mo.getAllTags();
+      for (Tag tag : tags) {
+        TreeMap<String, RelationDefinition> catMap =
+          catTopRelList.get(tag.getName());
+        if (catMap == null) {
+          catMap = new TreeMap<>();
+          catTopRelList.put(tag.getName(), catMap);
+        }
+        catMap.put(mo.getName(), rel);
+      }
+    }
+
+    // Build a list of top managed objects by category (core, database, ...)
+    for (AbstractManagedObjectDefinition<?, ?> topObject : topMoList.values()) {
+      Collection<Tag> tags = topObject.getAllTags();
+      for (Tag tag : tags) {
+        TreeMap<String, AbstractManagedObjectDefinition> catMap =
+          catTopMoList.get(tag.getName());
+        if (catMap == null) {
+          catMap = new TreeMap<>();
+          catTopMoList.put(tag.getName(), catMap);
+        }
+        catMap.put(topObject.getName(), topObject);
+      }
+    }
+
+  }
+
+  /**
+   * Generate the inheritance tree of all the managed objects.
+   */
+  @SuppressWarnings("unchecked")
+  private void genManagedObjectInheritanceTree(
+    TreeMap<String, TreeMap<String, AbstractManagedObjectDefinition>> list) {
+
+    htmlHeader(DynamicConstants.PRODUCT_NAME + " " +
+            "Configuration Reference - Inheritance View");
+    tabMenu(INHERITANCE_TREE_FILE);
+    viewHelp("This view represents the inheritance relationships between " +
+      "configuration components.");
+    jumpSection();
+
+    for (String catName : list.keySet()) {
+      heading3(getFriendlyName(catName));
+      // Get the list of the category
+      TreeMap<String, AbstractManagedObjectDefinition> catList = list.get(catName);
+      for (AbstractManagedObjectDefinition mo : catList.values()) {
+        RelationDefinition relDefn = relList.get(mo.getName());
+        if (relDefn != null && relDefn.hasOption(RelationOption.HIDDEN)) {
+          continue;
+        }
+        paragraph(
+          getLink(mo.getUserFriendlyName().toString(),
+          mo.getName() + ".html", MAIN_FRAME));
+        if (mo.hasChildren()) {
+          genMoInheritanceTree(makeMOTreeMap(mo.getChildren()));
+        }
+      }
+    }
+
+    htmlFooter();
+    generateFile(INHERITANCE_TREE_FILE);
+  }
+
+  @SuppressWarnings("unchecked")
+  private void genMoInheritanceTree(
+    TreeMap<String, AbstractManagedObjectDefinition> catList) {
+
+    beginList();
+    for (AbstractManagedObjectDefinition mo : catList.values()) {
+      link(mo.getUserFriendlyName().toString(), mo.getName() + ".html",
+        MAIN_FRAME);
+      if (mo.hasChildren()) {
+        genMoInheritanceTree(makeMOTreeMap(mo.getChildren()));
+      }
+    }
+    endList();
+  }
+
+   private void jumpSection() {
+     htmlBuff.append("<p class=\"category-index\"><strong>Jump To:</strong><br>\n");
+
+     String[] catNames = catTopMoList.keySet().toArray(new String[0]);
+    for (int ii=0; ii < catNames.length; ii++) {
+      if (ii != 0) {
+        htmlBuff.append(", ");
+      }
+      String catFriendlyName = getFriendlyName(catNames[ii]);
+      htmlBuff.append(getLink(catFriendlyName, "#" + catFriendlyName));
+    }
+    htmlBuff.append("</p>\n");
+   }
+
+
+  /**
+   * Generate the relation tree of all the managed objects.
+   */
+  private void genManagedObjectRelationTree(
+    TreeMap <String, TreeMap<String, RelationDefinition>> list) {
+
+    htmlHeader(DynamicConstants.PRODUCT_NAME +
+            " Configuration Reference - Structure View");
+    tabMenu(RELATION_TREE_FILE);
+    viewHelp("This view represents the structural relationships between " +
+      "components and indicates how certain components can exist only within " +
+      "container components.");
+    jumpSection();
+
+    for (String catName : list.keySet()) {
+      heading3(getFriendlyName(catName));
+      // Get the list of the category
+      TreeMap<String, RelationDefinition> catList = list.get(catName);
+      genMORelationTree(catList);
+    }
+
+    htmlFooter();
+    generateFile(RELATION_TREE_FILE);
+  }
+
+
+  @SuppressWarnings("unchecked")
+  private void genMORelationTree(TreeMap<String, RelationDefinition> list) {
+    for (RelationDefinition rel : list.values()) {
+      AbstractManagedObjectDefinition childMo = rel.getChildDefinition();
+      AbstractManagedObjectDefinition parentMo = rel.getParentDefinition();
+      // Does not generate several entry for the same relation
+      if (relList.put(childMo.getName(), rel) != null) {
+       continue;
+      }
+      if (rel.hasOption(RelationOption.HIDDEN)) {
+        continue;
+      }
+      String linkStr = getLink(childMo.getUserFriendlyName().toString(),
+        childMo.getName() + ".html", MAIN_FRAME);
+      String fromStr = "";
+      if (!parentMo.getName().equals("")) {
+        fromStr = " (from " +
+          getLink(parentMo.getUserFriendlyName().toString(),
+          parentMo.getName() + ".html", MAIN_FRAME) + ")";
+      }
+      if (!inList) {
+        paragraph(linkStr + fromStr);
+      } else {
+        bullet(linkStr + fromStr);
+      }
+      genMORelationSubTree(makeRelTreeMap(childMo.getAllRelationDefinitions()));
+      if (childMo.hasChildren()) {
+        for (Iterator<AbstractManagedObjectDefinition> it =
+          childMo.getChildren().iterator(); it.hasNext();) {
+
+          AbstractManagedObjectDefinition mo = it.next();
+          if (mo.hasOption(ManagedObjectOption.HIDDEN))
+          {
+            continue;
+          }
+          genMORelationSubTree(makeRelTreeMap(mo.getAllRelationDefinitions()));
+        }
+      }
+    }
+  }
+
+
+  private void genMORelationSubTree(TreeMap<String, RelationDefinition> list) {
+    if (!list.values().isEmpty()) {
+      beginList();
+      genMORelationTree(list);
+      endList();
+    }
+  }
+
+
+  /**
+   * Generate all the managed objects HTML pages and their children.
+   */
+  @SuppressWarnings("unchecked")
+  private void genAllManagedObject(
+    TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+    for (AbstractManagedObjectDefinition mo : list.values()) {
+      RelationDefinition relDefn = relList.get(mo.getName());
+      if (relDefn != null && relDefn.hasOption(RelationOption.HIDDEN)) {
+        continue;
+      }
+      moList.put(mo.getName(), mo);
+      genManagedObject(mo);
+      if (mo.hasChildren()) {
+        genAllManagedObject(makeMOTreeMap(mo.getChildren()));
+      }
+    }
+  }
+
+  private void genManagedObject(AbstractManagedObjectDefinition mo) {
+    //------------------------------------------------------------------------
+    // Header
+    //------------------------------------------------------------------------
+
+    homeLink();
+    String title = mo.getUserFriendlyName().toString();
+    htmlHeader(DynamicConstants.PRODUCT_NAME + " - " + title);
+
+    // title
+    heading2(title);
+
+    // Abstract notice
+    if (mo.hasChildren()) {
+      paragraph(
+        "Note: this is an abstract component, that cannot be instantiated.",
+        TextStyle.ITALIC);
+    }
+
+    // description
+    paragraph(mo.getSynopsis());
+    paragraph(mo.getDescription());
+
+    // sub-components
+    if (mo.hasChildren()) {
+      heading3("Direct Subcomponents");
+      paragraph("The following " + mo.getUserFriendlyPluralName() +
+        " are available in the server :");
+      beginList();
+      @SuppressWarnings("unchecked")
+      TreeMap<String, AbstractManagedObjectDefinition> children =
+        makeMOTreeMap(mo.getChildren());
+      for ( AbstractManagedObjectDefinition child : children.values()) {
+        link(child.getUserFriendlyName().toString(), child.getName() + ".html");
+      }
+      endList();
+
+      paragraph("These " + mo.getUserFriendlyPluralName() +
+        " inherit from the properties described below.");
+    }
+
+    // Parent
+    if (!mo.getParent().isTop()) {
+      heading3("Parent Component");
+      paragraph("The " + mo.getUserFriendlyName() +
+        " component inherits from the " +
+        getLink(mo.getParent().getUserFriendlyName().toString(),
+        mo.getParent().getName() + ".html"));
+    }
+
+    // Relations
+    generateRelationsSection(mo);
+
+    // Page links in case of LDAP mapping
+    if (ldapMapping) {
+      newline();
+      horizontalLine();
+      newline();
+      paragraph("This page describes the " + mo.getUserFriendlyName() + ":");
+      beginList();
+      link("Properties", "#Properties");
+      link("LDAP Mapping", "#LDAP Mapping");
+      endList();
+      newline();
+    }
+
+
+    //------------------------------------------------------------------------
+    // Properties
+    //------------------------------------------------------------------------
+
+    heading3("Properties");
+
+    paragraph("A description of each property follows.");
+    newline();
+
+    TreeMap<String, PropertyDefinition> basicProps = new TreeMap<>();
+    TreeMap<String, PropertyDefinition> advancedProps = new TreeMap<>();
+    // Properties actually defined in this managed object
+    @SuppressWarnings("unchecked")
+    Collection<PropertyDefinition> props = mo.getAllPropertyDefinitions();
+    for ( PropertyDefinition prop : props) {
+      if (prop.hasOption(PropertyOption.ADVANCED)) {
+        advancedProps.put(prop.getName(), prop);
+      } else {
+        basicProps.put(prop.getName(), prop);
+      }
+    }
+
+    propertiesLinkTable(basicProps, advancedProps);
+
+    // basic properties
+    if (!basicProps.isEmpty()) {
+      heading4("Basic Properties");
+      for ( PropertyDefinition prop : basicProps.values()) {
+        generateProperty(mo, prop);
+        newline();
+      }
+      newline();
+    }
+
+    // advanced properties
+    if (!advancedProps.isEmpty()) {
+      heading4("Advanced Properties");
+      for ( PropertyDefinition prop : advancedProps.values()) {
+        generateProperty(mo, prop);
+        newline();
+      }
+      newline();
+    }
+
+    if (ldapMapping) {
+      genLdapMapping(mo);
+    }
+
+    htmlFooter();
+
+    generateFile(mo.getName() + ".html");
+  }
+
+
+  private TreeMap<String, PropertyDefinition>
+    getPropertyList(AbstractManagedObjectDefinition mo) {
+
+    @SuppressWarnings("unchecked")
+    Collection<PropertyDefinition> props = mo.getAllPropertyDefinitions();
+    return makePropTreeMap(props);
+  }
+
+  private void homeLink() {
+    htmlBuff.append("<div style=\"font-size:11px;margin-top:-10px;")
+      .append("margin-bottom:-10px; text-align:right\"><a href=\"")
+      .append(MAIN_FILE)
+      .append("\" target=\"_top\">Configuration Reference Home</a></div>");
+  }
+
+
+  private void generateRelationsSection(AbstractManagedObjectDefinition mo) {
+    // Composition relations
+    @SuppressWarnings("unchecked")
+    Collection<RelationDefinition> compRels = mo.getRelationDefinitions();
+    @SuppressWarnings("unchecked")
+    Collection<RelationDefinition> reverseCompRels =
+      mo.getReverseRelationDefinitions();
+    // Aggregation properties
+    @SuppressWarnings("unchecked")
+    Collection<AggregationPropertyDefinition> aggregProps =
+      mo.getAggregationPropertyDefinitions();
+    @SuppressWarnings("unchecked")
+    Collection<AggregationPropertyDefinition> reverseAggregProps =
+      mo.getReverseAggregationPropertyDefinitions();
+
+
+    // Check if something to print in composition relations
+    // (even if the list not empty, it may contain only hidden relations)
+    boolean isCompRelsEmpty = true;
+    if (!compRels.isEmpty()) {
+      for (RelationDefinition rel : compRels) {
+        if (rel.hasOption(RelationOption.HIDDEN)) {
+          continue;
+        }
+        isCompRelsEmpty = false;
+      }
+    }
+    boolean isReverseCompRelsEmpty = true;
+    if (!reverseCompRels.isEmpty()) {
+      for (RelationDefinition rel : reverseCompRels) {
+        if (rel.hasOption(RelationOption.HIDDEN)) {
+          continue;
+        }
+        // check if it is not root
+        if (rel.getParentDefinition().getName().equals("")) {
+          continue;
+        }
+        isReverseCompRelsEmpty = false;
+      }
+    }
+
+    // Check if something to print in reverse aggregation relations
+    // (even if the list not empty, it may contain only relations from
+    // hidden component)
+    boolean isReverseAggregPropsEmpty = true;
+    if (!reverseAggregProps.isEmpty()) {
+      for (AggregationPropertyDefinition agg : reverseAggregProps) {
+        AbstractManagedObjectDefinition fromMo =
+          agg.getManagedObjectDefinition();
+        @SuppressWarnings("unchecked")
+        Collection<RelationDefinition> rels =
+          fromMo.getAllReverseRelationDefinitions();
+        for (RelationDefinition rel : rels) {
+          if (rel.hasOption(RelationOption.HIDDEN)) {
+            continue;
+          }
+          isReverseAggregPropsEmpty = false;
+        }
+      }
+    }
+
+
+    //
+    // Relations FROM this component
+    //
+
+    if (!isCompRelsEmpty || !aggregProps.isEmpty()) {
+        heading3("Relations From this Component");
+    }
+
+    if (!isCompRelsEmpty) {
+      paragraph(
+        "The following components have a direct COMPOSITION relation FROM " +
+        mo.getUserFriendlyPluralName() + " :");
+      for ( RelationDefinition rel : compRels) {
+        if (rel.hasOption(RelationOption.HIDDEN)) {
+          continue;
+        }
+        beginList();
+        AbstractManagedObjectDefinition childRel = rel.getChildDefinition();
+        link(childRel.getUserFriendlyName().toString(), childRel.getName() +
+          ".html");
+        endList();
+      }
+    }
+    if (!aggregProps.isEmpty()) {
+      paragraph(
+        "The following components have a direct AGGREGATION relation FROM " +
+        mo.getUserFriendlyPluralName() + " :");
+      TreeMap<String, AbstractManagedObjectDefinition> componentList = new TreeMap<>();
+      for ( AggregationPropertyDefinition agg : aggregProps) {
+        RelationDefinition rel = agg.getRelationDefinition();
+        AbstractManagedObjectDefinition childRel = rel.getChildDefinition();
+        componentList.put(childRel.getName(), childRel);
+      }
+      for (AbstractManagedObjectDefinition component : componentList.values()) {
+        beginList();
+        link(component.getUserFriendlyName().toString(), component.getName() + ".html");
+        endList();
+      }
+    }
+
+
+    //
+    // Relations TO this component
+    //
+
+    if (!isReverseCompRelsEmpty || !isReverseAggregPropsEmpty) {
+        heading3("Relations To this Component");
+    }
+
+    if (!mo.getReverseRelationDefinitions().isEmpty()
+        && !isReverseCompRelsEmpty)
+    {
+      paragraph(
+        "The following components have a direct COMPOSITION relation TO " +
+        mo.getUserFriendlyPluralName() + " :");
+      for ( RelationDefinition rel : reverseCompRels) {
+        beginList();
+        AbstractManagedObjectDefinition childRel = rel.getParentDefinition();
+        link(childRel.getUserFriendlyName().toString(), childRel.getName() + ".html");
+        endList();
+      }
+    }
+    if (!isReverseAggregPropsEmpty) {
+      paragraph(
+        "The following components have a direct AGGREGATION relation TO " +
+        mo.getUserFriendlyPluralName() + " :");
+      TreeMap<String, AbstractManagedObjectDefinition> componentList = new TreeMap<>();
+      for ( AggregationPropertyDefinition agg : reverseAggregProps) {
+        AbstractManagedObjectDefinition fromMo =
+          agg.getManagedObjectDefinition();
+        componentList.put(fromMo.getName(), fromMo);
+      }
+      for (AbstractManagedObjectDefinition component : componentList.values()) {
+        beginList();
+        link(component.getUserFriendlyName().toString(), component.getName() +
+          ".html");
+        endList();
+
+      }
+    }
+
+  }
+
+  private void generateProperty(
+    AbstractManagedObjectDefinition mo, PropertyDefinition prop) {
+
+    // Property name
+    paragraph(getAnchor(prop.getName()) + prop.getName(), TextStyle.STANDARD,
+      "propertyname");
+
+    // Property table
+    startTable();
+    tableRow("Description",
+      ((prop.getSynopsis() != null) ? prop.getSynopsis()+ " " : "") +
+      ((prop.getDescription() != null) ?
+        prop.getDescription().toString() : ""));
+
+    // Default value
+    String defValueStr = getDefaultBehaviorString(prop);
+    tableRow("Default Value", defValueStr);
+
+    tableRow("Allowed Values", getSyntaxStr(prop));
+
+    tableRow("Multi-valued",
+      prop.hasOption(PropertyOption.MULTI_VALUED) ? "Yes" : "No");
+
+    if (prop.hasOption(PropertyOption.MANDATORY)) {
+      tableRow("Required", "Yes");
+    } else {
+      tableRow("Required", "No");
+    }
+
+    String action = "None";
+    if (prop.getAdministratorAction() != null) {
+      LocalizableMessage synopsis = prop.getAdministratorAction().getSynopsis();
+      Type actionType = prop.getAdministratorAction().getType();
+      String actionStr = "";
+      if (actionType == Type.COMPONENT_RESTART) {
+        actionStr = "The " + mo.getUserFriendlyName() +
+          " must be disabled and re-enabled for changes to this setting " +
+          "to take effect";
+      } else if (actionType == Type.SERVER_RESTART) {
+        actionStr = "Restart the server";
+      } else if (actionType == Type.NONE) {
+        actionStr = "None";
+      }
+      String dot = actionStr.equals("") ? "" : ". ";
+      action = actionStr +
+        ((synopsis != null) ? dot + synopsis : "");
+    }
+    tableRow("Admin Action Required", action);
+
+    if (prop.hasOption(PropertyOption.ADVANCED)) {
+      tableRow("Advanced Property", "Yes");
+    } else {
+      tableRow("Advanced Property", "No");
+    }
+
+    if (prop.hasOption(PropertyOption.READ_ONLY)) {
+      tableRow("Read-only", "Yes");
+    } else {
+      tableRow("Read-only", "No");
+    }
+
+    endTable();
+
+  }
+
+
+  private void propertiesLinkTable(TreeMap<String,
+    PropertyDefinition> basicProps,
+    TreeMap<String, PropertyDefinition> advancedProps) {
+    htmlBuff.append("<table border=\"0\" cellspacing=\"0\" class=\"jump-table\">\n")
+        .append("  <tr>\n")
+        .append("    <th>Basic Properties:</th>\n")
+        .append("    <th>Advanced Properties:</th>\n")
+        .append("  </tr>\n");
+
+    PropertyDefinition[] basicPropsArray =
+      basicProps.values().toArray(new PropertyDefinition[0]);
+    PropertyDefinition[] advancedPropsArray =
+      advancedProps.values().toArray(new PropertyDefinition[0]);
+
+    for (int ii=0;
+        ii < basicPropsArray.length || ii < advancedPropsArray.length;
+        ii++) {
+      String basicPropName =
+        ii < basicPropsArray.length ? basicPropsArray[ii].getName() : null;
+      String advancedPropName =
+        ii < advancedPropsArray.length ?
+          advancedPropsArray[ii].getName() : null;
+
+      String basicHtmlCell = "";
+      if (basicPropName != null) {
+        basicHtmlCell = "  <td>&darr;&nbsp;<a href=\"#" + basicPropName + "\">"
+          + basicPropName + "</a></td>\n";
+      } else if (basicPropsArray.length == 0 && ii == 0) {
+        basicHtmlCell = "  <td>&nbsp;None</td>\n";
+      } else if (ii >= basicPropsArray.length) {
+        // Case of nb of basic props < nb of advanced props
+        basicHtmlCell = "  <td></td>\n";
+      }
+
+      String advancedHtmlCell = "";
+      if (advancedPropName != null) {
+        advancedHtmlCell = "  <td>&darr;&nbsp;<a href=\"#" + advancedPropName +
+          "\">" + advancedPropName + "</a></td>\n";
+      } else if (advancedPropsArray.length == 0 && ii == 0) {
+        advancedHtmlCell = "  <td>&nbsp;None</td>\n";
+      }
+
+      htmlBuff.append("<tr>\n");
+      htmlBuff.append(basicHtmlCell).append(advancedHtmlCell);
+      htmlBuff.append("</tr>\n");
+    }
+    htmlBuff.append("</table>\n");
+  }
+
+
+  private void genLdapMapping(AbstractManagedObjectDefinition mo) {
+    //------------------------------------------------------------------------
+    // LDAP mapping
+    //------------------------------------------------------------------------
+
+    heading3("LDAP Mapping");
+    paragraph(
+      "Each configuration property can be mapped to a specific " +
+      "LDAP attribute under the \"cn=config\" entry. " +
+      "The mappings that follow are provided for information only. " +
+      "In general, you should avoid changing the server configuration " +
+      "by manipulating the LDAP attributes directly.");
+
+    // Managed object table
+    startTable();
+
+    LDAPProfile ldapProfile = LDAPProfile.getInstance();
+    tableRow("Base DN", getBaseDN(mo, ldapProfile));
+
+    tableRow("objectclass name", ldapProfile.getObjectClass(mo));
+    if (mo.getParent().getName() != null) {
+      String superior = "";
+      if (mo.getParent().getName().equals("top")) {
+        superior = "top";
+      } else {
+        if (moList.get(mo.getParent().getName()) != null) {
+          superior =
+            ldapProfile.getObjectClass(moList.get(mo.getParent().getName()));
+        } else {
+          System.err.println(
+            "Error: managed object " + mo.getName() + " not found.");
+        }
+      }
+      tableRow("objectclass superior", superior);
+    } else {
+      System.err.println(
+        "Error: objectclass superior not found for " + mo.getName());
+    }
+    endTable();
+
+    newline();
+    // Properties table
+    startTable();
+    tableRow("Property", "LDAP attribute");
+    for ( PropertyDefinition prop : getPropertyList(mo).values()) {
+      tableRow(prop.getName(), ldapProfile.getAttributeName(mo, prop));
+    }
+
+    endTable();
+
+  }
+
+  /** Generate a list of managed objects. */
+  private void genManagedObjectList(
+    TreeMap<String, AbstractManagedObjectDefinition> list) {
+
+    htmlHeader(DynamicConstants.PRODUCT_NAME
+            + " Configuration Reference - Components View");
+    tabMenu(MO_LIST_FILE);
+    viewHelp("This view provides a list of all configuration components, " +
+      "in alphabetical order.");
+
+    newline();
+    StringBuffer moPointers = new StringBuffer();
+    String lettersPointers = "";
+    String firstChar = ".";
+    for (AbstractManagedObjectDefinition mo : list.values()) {
+      if (!mo.getName().startsWith(firstChar)) {
+        firstChar = mo.getName().substring(0, 1);
+        String letter = firstChar.toUpperCase();
+        moPointers.append(getAnchor(letter)).append(getHeading2(letter));
+        lettersPointers += getLink(letter, "#" + letter) + " ";
+      }
+      moPointers.append("<p> ")
+        .append(getLink(mo.getUserFriendlyName().toString(), mo.getName() + ".html", MAIN_FRAME))
+        .append("</p>\n");
+    }
+    paragraph(lettersPointers);
+    htmlBuff.append(moPointers);
+    htmlFooter();
+    generateFile(MO_LIST_FILE);
+  }
+
+  /** Generate an index of properties. */
+  private void genPropertiesIndex() {
+
+    // Build a sorted list of (property name + its managed object name)
+    TreeSet<String> propMoList = new TreeSet<>();
+    for (AbstractManagedObjectDefinition<?, ?> mo : moList.values()) {
+      for (PropertyDefinition<?> prop : mo.getPropertyDefinitions()) {
+        propMoList.add(
+          prop.getName() + "," + prop.getManagedObjectDefinition().getName());
+      }
+    }
+
+    String lettersPointers = "";
+    String firstChar = ".";
+    for (String propMoStr : propMoList) {
+      String[] propMoArray = propMoStr.split(",");
+      String propName = propMoArray[0];
+      AbstractManagedObjectDefinition mo = moList.get(propMoArray[1]);
+      if (!propName.startsWith(firstChar)) {
+        firstChar = propName.substring(0, 1);
+        String letter = firstChar.toUpperCase();
+        htmlBuff.append(getAnchor(letter)).append(getHeading2(letter));
+        lettersPointers += getLink(letter, "#" + letter) + " ";
+      }
+      String propLink = getLink(propName,
+        mo.getName() + ".html" + "#" + propName, MAIN_FRAME);
+      String moLink =
+        getLink(mo.getUserFriendlyName().toString(), mo.getName() + ".html",
+        MAIN_FRAME, "#666");
+      paragraph(propLink + "  [ " + moLink + " ]");
+    }
+
+    String indexBody = htmlBuff.toString();
+    htmlBuff = new StringBuffer();
+    htmlHeader(DynamicConstants.PRODUCT_NAME +
+            " Configuration Reference - Properties View");
+    tabMenu(PROPERTIES_INDEX_FILE);
+    viewHelp("This view provides a list of all configuration properties, " +
+      "in alphabetical order, and indicates the configuration component to " +
+      "which each property applies.");
+
+    newline();
+    paragraph(lettersPointers);
+    htmlBuff.append(indexBody);
+    htmlFooter();
+    generateFile(PROPERTIES_INDEX_FILE);
+  }
+
+    private void genWelcomePage() {
+    htmlHeader(DynamicConstants.PRODUCT_NAME +
+            " Configuration Reference - Welcome");
+    heading2("About This Reference");
+    paragraph("This reference " +
+      "describes the " + DynamicConstants.PRODUCT_NAME +
+      " configuration properties that can be manipulated " +
+      "with the dsconfig command.");
+    paragraph("Configuration components are grouped according to the area of " +
+      "the server in which they are used, as follows:");
+
+    beginList();
+    for (String catName : catTopMoList.keySet()) {
+      bullet(getFriendlyName(catName));
+    }
+    endList();
+
+    paragraph(
+      "For ease of reference, the configuration is described on multiple " +
+      "tabs. These tabs provide alternative views of the configuration " +
+      "components:");
+    beginList();
+    bullet("The <strong>Inheritance</strong> view represents the inheritance " +
+      "relationships between configuration components. A sub-component " +
+      "inherits all of the properties of its parent component.");
+    bullet("The <strong>Structure</strong> view represents the structural " +
+      "relationships between components and indicates how certain components " +
+      "can exist only within container components. When a container " +
+      "component is deleted, all of the components within it are also " +
+      "deleted.");
+    bullet(
+      "The <strong>Components</strong> view provides an alphabetical list " +
+      "of all configuration components.");
+    bullet(
+      "The <strong>Properties</strong> view provides an alphabetical list " +
+      "of all configuration properties, and indicates the configuration " +
+      "component to which each property applies.");
+    endList();
+
+    newline();
+    paragraph("When you set up " +
+            DynamicConstants.PRODUCT_NAME +
+            ", certain components are created in the " +
+      "configuration by default. These components are configured with " +
+      "specific values, which are not necessarily the same as the " +
+      "\"default values\" of new components that you create using dsconfig. " +
+      "The \"default values\" listed in this document refer to the values " +
+      "of the new components that you create using dsconfig.");
+
+    htmlFooter();
+    generateFile(WELCOME_FILE);
+
+  }
+
+  private void genMainTopPage() {
+    htmlHeader(DynamicConstants.PRODUCT_NAME +
+            " Configuration Reference - Main Top");
+    // "Home" might be depend on where this is published.
+    /*
+    htmlBuff.append("<div class=\"breadcrumb\"><span class=\"pageactions\">" +
+      "<a href=\"" + OpenDJHome + "\" target=\"_parent\">" +
+      "<span style=\"font-size: 12px;\">&laquo;&nbsp;&nbsp;</span>" +
+      "Back to " +
+      DynamicConstants.PRODUCT_NAME + " Home</a></span>&nbsp;&nbsp;</div>\n");
+    */
+    htmlBuff.append("<div class=\"breadcrumb\"><span class=\"pageactions\">" +
+            "&nbsp;&nbsp;</span>&nbsp;&nbsp;</div>\n");
+    htmlBuff.append("<table class=\"titletable\" cellspacing=\"0\" " +
+      "width=\"100%\">\n");
+    htmlBuff.append("<tbody><tr>\n");
+    htmlBuff.append("  <td><h2>"+
+            DynamicConstants.PRODUCT_NAME +
+            " Configuration Reference</h2></td>\n");
+    /*
+    htmlBuff.append("  <td valign=\"bottom\" width=\"10%\">" +
+      "<a href=\"" + OpenDJHome + "\" target=\"_parent\">" +
+      "<img src=\"opendj_logo_sm.png\" alt=\"OpenDJ Logo\" align=\"bottom\" " +
+      "border=\"0\" height=\"33\" width=\"114\"></a></td>\n");
+    */
+    htmlBuff.append("  <td valign=\"bottom\" width=\"10%\">" +
+            "<img src=\"opendj_logo_sm.png\" alt=\"OpenDJ Logo\" align=\"bottom\" " +
+            "border=\"0\" height=\"33\" width=\"114\"></td>\n");
+    htmlBuff.append("</tr>\n");
+    htmlBuff.append("</tbody></table>\n");
+
+    htmlFooter();
+    generateFile(MAINTOP_FILE);
+
+  }
+
+  private void genIndexPage() {
+    htmlBuff.append(getHtmlHeader(
+            DynamicConstants.PRODUCT_NAME + " Configuration Reference"));
+
+    htmlBuff.append("<frameset rows=\"80,*\" framespacing=\"1\" " +
+      "frameborder=\"yes\" border=\"1\" bordercolor=\"#333333\">\n");
+    htmlBuff.append("  <frame src=\"" + MAINTOP_FILE + "\" name=\"topFrame\" " +
+      "id=\"topFrame\" border=\"1\" title=\"topFrame\" scrolling=\"no\">\n");
+    htmlBuff.append("  <frameset cols=\"375,*\" frameborder=\"yes\" " +
+      "border=\"1\" " +
+      "framespacing=\"1\">\n");
+    htmlBuff.append("     <frame src=\"" + INHERITANCE_TREE_FILE + "\" " +
+      "name=\"leftFrame\" id=\"leftFrame\" title=\"leftFrame\" " +
+      "scrolling=\"auto\">\n");
+    htmlBuff.append("     <frame src=\"" + WELCOME_FILE +
+      "\" name=\"mainFrame\" " +
+      "id=\"mainFrame\" title=\"mainFrame\" scrolling=\"auto\">\n");
+    htmlBuff.append("   </frameset>\n");
+    htmlBuff.append("</frameset>\n");
+    htmlBuff.append("<noframes><body>\n");
+    htmlBuff.append("</body>\n");
+    htmlBuff.append("</noframes>\n");
+    htmlBuff.append("</html>\n");
+
+    generateFile(INDEX_FILE);
+  }
+
+  private String getBaseDN(
+    AbstractManagedObjectDefinition mo, LDAPProfile ldapProfile) {
+
+    RelationDefinition rel = relList.get(mo.getName());
+    if (rel != null) {
+      String baseDn = ldapProfile.getRelationRDNSequence(rel);
+      if (!baseDn.equals("")) {
+        return baseDn;
+      } else {
+        // Check the parent relation
+        return getBaseDN(rel.getParentDefinition(), ldapProfile);
+      }
+    } else if (moList.get(mo.getParent().getName()) != null) {
+      // check its superior
+      return getBaseDN(moList.get(mo.getParent().getName()), ldapProfile);
+    } else {
+      System.err.println("Error: Base DN not found for " + mo.getName());
+    }
+    return null;
+  }
+
+  @SuppressWarnings("unchecked")
+  private String getSyntaxStr(PropertyDefinition prop) {
+    // Create a visitor for performing syntax specific processing.
+    PropertyDefinitionVisitor<String, Void> visitor =
+      new PropertyDefinitionVisitor<String, Void>() {
+
+      @Override
+      public String visitACI(ACIPropertyDefinition prop, Void p) {
+        // Rather than return a link that is coupled to a site location,
+        // assume that readers can find ACI syntax in the documentation.
+        // ACI syntax being difficult to understand and to explain,
+        // it is better not to have to maintain a separate page, either.
+        return "An ACI syntax"; // getLink("An ACI Syntax", aciSyntaxPage);
+      }
+
+      @Override
+      public String visitAggregation(
+        AggregationPropertyDefinition prop, Void p) {
+
+        RelationDefinition rel = prop.getRelationDefinition();
+        String linkStr = getLink(rel.getUserFriendlyName().toString(),
+          rel.getName() + ".html");
+      return "The DN of any " +  linkStr + ". " +
+        ((prop.getSourceConstraintSynopsis() != null) ?
+          prop.getSourceConstraintSynopsis().toString() : "");
+      }
+
+      @Override
+      public String visitAttributeType(
+        AttributeTypePropertyDefinition prop, Void p) {
+        return "The name of an attribute type defined in the server schema.";
+      }
+
+      @Override
+      public String visitBoolean(BooleanPropertyDefinition prop, Void p) {
+        return "true" + getNewLine() + "false";
+      }
+
+      @Override
+      public String visitClass(ClassPropertyDefinition prop, Void p) {
+        String classStr =
+          "A java class that implements or extends the class(es) :";
+        for (String clazz : prop.getInstanceOfInterface()) {
+          classStr += getNewLine() + clazz;
+        }
+        return classStr;
+      }
+
+      @Override
+      public String visitDN(DNPropertyDefinition prop, Void p) {
+        String retStr = "A valid DN.";
+        if (prop.getBaseDN() != null) {
+          retStr += prop.getBaseDN().toString();
+        }
+        return retStr;
+      }
+
+      @Override
+      public String visitDuration(DurationPropertyDefinition prop, Void p) {
+        String durationStr = "";
+
+        durationStr += getLink("A duration Syntax", durationSyntaxPage) +
+          ". ";
+        if (prop.isAllowUnlimited()) {
+          durationStr += "A value of \"-1\" or \"unlimited\" for no limit. ";
+        }
+        if (prop.getMaximumUnit() != null) {
+          durationStr += "Maximum unit is \"" +
+            prop.getMaximumUnit().getLongName() + "\". ";
+        }
+        long lowerLimitStr = Double.valueOf(prop.getBaseUnit().
+          fromMilliSeconds(prop.getLowerLimit())).longValue();
+        durationStr += "Lower limit is " + lowerLimitStr +
+          " " + prop.getBaseUnit().getLongName() + ". ";
+        if (prop.getUpperLimit() != null) {
+          long upperLimitStr = Double.valueOf(prop.getBaseUnit().
+            fromMilliSeconds(prop.getUpperLimit())).longValue();
+          durationStr += "Upper limit is " + upperLimitStr +
+            " " + prop.getBaseUnit().getLongName() + ". ";
+        }
+
+        return durationStr;
+      }
+
+      @Override
+      public String visitEnum(EnumPropertyDefinition prop, Void p) {
+        String enumStr = "";
+        Class en = prop.getEnumClass();
+        for (Object cst : en.getEnumConstants()) {
+          enumStr += cst.toString();
+          if (prop.getValueSynopsis((Enum) cst) != null) {
+            enumStr += " - " + prop.getValueSynopsis((Enum) cst);
+          }
+          enumStr += getNewLine() + getNewLine();
+        }
+        return enumStr;
+      }
+
+      @Override
+      public String visitInteger(IntegerPropertyDefinition prop, Void p) {
+        String intStr = "An integer value.";
+        intStr += " Lower value is " + prop.getLowerLimit() + ".";
+        if (prop.getUpperLimit() != null) {
+          intStr += " Upper value is " + prop.getUpperLimit() + " .";
+        }
+        if (prop.isAllowUnlimited()) {
+          intStr += " A value of \"-1\" or \"unlimited\" for no limit.";
+        }
+        if (prop.getUnitSynopsis() != null) {
+          intStr += " Unit is " + prop.getUnitSynopsis() + ".";
+        }
+        return intStr;
+      }
+
+      @Override
+      public String visitIPAddress(IPAddressPropertyDefinition prop, Void p) {
+        return "An IP address";
+      }
+
+      @Override
+      public String visitIPAddressMask(
+        IPAddressMaskPropertyDefinition prop, Void p) {
+
+        return "An IP address mask";
+      }
+
+      @Override
+      public String visitSize(SizePropertyDefinition prop, Void p) {
+        String sizeStr = "A positive integer representing a size.";
+        if (prop.getLowerLimit() != 0) {
+          sizeStr += " Lower value is " + prop.getLowerLimit() + ".";
+        }
+        if (prop.getUpperLimit() != null) {
+          sizeStr += " Upper value is " + prop.getUpperLimit() + " .";
+        }
+        if (prop.isAllowUnlimited()) {
+          sizeStr += " A value of \"-1\" or \"unlimited\" for no limit.";
+        }
+        return sizeStr;
+      }
+
+      @Override
+      public String visitString(StringPropertyDefinition prop, Void p) {
+        String retStr = "A String";
+        if (prop.getPatternSynopsis() != null) {
+          retStr = prop.getPatternSynopsis().toString();
+        }
+        return retStr;
+      }
+
+      @Override
+      public String visitUnknown(PropertyDefinition prop, Void p) {
+        return "Unknown";
+      }
+    };
+
+    // Invoke the visitor against the property definition.
+    return (String) prop.accept(visitor, null);
+
+  }
+
+  @SuppressWarnings("unchecked")
+  private String getDefaultBehaviorString(PropertyDefinition prop) {
+    DefaultBehaviorProvider defaultBehav = prop.getDefaultBehaviorProvider();
+    String defValueStr = "";
+    if (defaultBehav instanceof UndefinedDefaultBehaviorProvider) {
+      defValueStr = "None";
+    } else if (defaultBehav instanceof DefinedDefaultBehaviorProvider) {
+      DefinedDefaultBehaviorProvider defBehav =
+        (DefinedDefaultBehaviorProvider) defaultBehav;
+      for (Iterator<String> it = defBehav.getDefaultValues().iterator();
+      it.hasNext();) {
+
+        String str = it.next();
+        defValueStr += str + (it.hasNext() ? "\n" : "");
+      }
+    } else if (defaultBehav instanceof AliasDefaultBehaviorProvider) {
+      AliasDefaultBehaviorProvider aliasBehav = (
+        AliasDefaultBehaviorProvider) defaultBehav;
+      defValueStr = aliasBehav.getSynopsis().toString();
+    } else if
+      (defaultBehav instanceof RelativeInheritedDefaultBehaviorProvider) {
+      RelativeInheritedDefaultBehaviorProvider relativBehav =
+        (RelativeInheritedDefaultBehaviorProvider) defaultBehav;
+      defValueStr = getDefaultBehaviorString(
+        relativBehav.getManagedObjectDefinition().
+        getPropertyDefinition(relativBehav.getPropertyName()));
+    } else if
+      (defaultBehav instanceof AbsoluteInheritedDefaultBehaviorProvider) {
+      AbsoluteInheritedDefaultBehaviorProvider absoluteBehav =
+        (AbsoluteInheritedDefaultBehaviorProvider) defaultBehav;
+      defValueStr = getDefaultBehaviorString(
+        absoluteBehav.getManagedObjectDefinition().
+        getPropertyDefinition(absoluteBehav.getPropertyName()));
+    }
+    return defValueStr;
+  }
+
+  private TreeMap<String, AbstractManagedObjectDefinition> makeMOTreeMap(
+    Collection<AbstractManagedObjectDefinition> coll) {
+
+    if (coll == null) {
+      return null;
+    }
+    TreeMap<String, AbstractManagedObjectDefinition> map = new TreeMap<>();
+    for (AbstractManagedObjectDefinition mo : coll) {
+      if (mo.hasOption(ManagedObjectOption.HIDDEN))
+      {
+        continue;
+      }
+      map.put(mo.getName(), mo);
+    }
+    return map;
+  }
+
+  private TreeMap<String, RelationDefinition> makeRelTreeMap(
+    Collection<RelationDefinition> coll) {
+
+    if (coll == null) {
+      return null;
+    }
+    TreeMap<String, RelationDefinition> map = new TreeMap<>();
+    for (RelationDefinition rel : coll) {
+      map.put(rel.getChildDefinition().getName(), rel);
+    }
+    return map;
+  }
+
+  private TreeMap<String, PropertyDefinition> makePropTreeMap(
+    Collection<PropertyDefinition> coll) {
+
+    if (coll == null) {
+      return null;
+    }
+    TreeMap<String, PropertyDefinition> map = new TreeMap<>();
+    for (PropertyDefinition prop : coll) {
+      map.put(prop.getName(), prop);
+    }
+    return map;
+  }
+
+  private void horizontalLine() {
+    htmlBuff.append("<hr style=\"width: 100%; height: 2px;\">");
+  }
+
+  private void endTable() {
+    htmlBuff.append("</tbody>\n");
+    htmlBuff.append("</table>\n");
+  }
+
+  private void bullet(String str) {
+    htmlBuff.append("<li>").append(str).append("</li>\n");
+  }
+
+  private void heading2(String string) {
+    heading(string, 2);
+  }
+
+  private void heading3(String string) {
+    heading(string, 3);
+  }
+
+  private void heading4(String string) {
+    heading(string, 4);
+  }
+
+  private void heading(String str, int level) {
+    htmlBuff.append(getHeading(str, level));
+  }
+
+  private String getHeading(String str, int level) {
+    String strLevel = Integer.valueOf(level).toString();
+    return "<h" + strLevel + ">" +
+      "<a name=\"" + str + "\"></a>" +
+      str +
+      "</h" + strLevel + ">\n";
+  }
+
+  private String getHeading2(String str) {
+    return getHeading(str, 2);
+  }
+
+  private String getAnchor(String str) {
+    return "<a name=\"" + str + "\"></a>";
+  }
+
+  private void htmlHeader(String pageTitle) {
+    htmlBuff.append(getHtmlHeader(pageTitle)).append("<body>\n");
+
+  }
+
+  private final String Now = new Date().toString();
+  private String getHtmlHeader(String pageTitle) {
+    return "<html>\n" +
+      "<head>\n" +
+      "<meta http-equiv=\"content-type\"\n" +
+      "content=\"text/html; charset=ISO-8859-1\">\n" +
+      "<title>" + pageTitle + "</title>\n" +
+      "<link rel=\"stylesheet\" type=\"text/css\"\n" +
+      "href=\"" + CSS_FILE + "\">\n" +
+      "<link rel=\"shortcut icon\" href=\"" + FAVICON + "\">\n" +
+      "<meta name=\"date generated\" content=\"" + Now + "\">\n" +
+      "</head>\n";
+  }
+
+  /** Add a Tab Menu, the active tab is the one given as parameter. */
+  private void tabMenu(String activeTab) {
+    htmlBuff.append(
+      "<div class=\"tabmenu\"> " +
+
+      "<span><a " +
+      (activeTab.equals(INHERITANCE_TREE_FILE) ? "class=\"activetab\" " : "") +
+      "href=\"" + INHERITANCE_TREE_FILE + "\"" +
+      " title=\"Inheritance View of Components\">Inheritance</a></span> " +
+
+      "<span><a " +
+      (activeTab.equals(RELATION_TREE_FILE) ? "class=\"activetab\" " : "") +
+      "href=\"" + RELATION_TREE_FILE + "\"" +
+      " title=\"Relational View of Components\">Structure</a></span> " +
+
+      "<span><a " +
+      (activeTab.equals(MO_LIST_FILE) ? "class=\"activetab\" " : "") +
+      "href=\"" + MO_LIST_FILE + "\"" +
+      " title=\"Alphabetical Index of Components\">Components</a></span> " +
+
+      "<span><a " +
+      (activeTab.equals(PROPERTIES_INDEX_FILE) ? "class=\"activetab\" " : "") +
+      "href=\"" + PROPERTIES_INDEX_FILE + "\"" +
+      " title=\"Alphabetical Index of Properties\" >Properties</a></span>" +
+
+      "</div>" +
+      "\n"
+      );
+  }
+
+  private String getLink(String str, String link) {
+    return getLink(str, link, null, null);
+  }
+
+  private String getLink(String str, String link, String target) {
+    return getLink(str, link, target, null);
+  }
+
+  private String getLink(String str, String link, String target, String color) {
+    return "<a " +
+      (color != null ? "style=\"color:" + color + "\" " : "") +
+      "href=\"" + link + "\"" +
+      (target == null ? "" : " target=\"" + target + "\"") +
+      ">"
+      + str + "</a>";
+  }
+
+  private void link(String str, String link) {
+    link(str, link, null, null);
+  }
+
+  private void link(String str, String link, String target) {
+    link(str, link, target, null);
+  }
+
+  private void link(String str, String link, String target, String color) {
+    String htmlStr = "";
+    if (!inList && getIndentPixels() > 0) {
+      htmlStr += "<div style=\"margin-left: " + getIndentPixels() + "px;\">";
+    } else if (inList) {
+      htmlStr += "<li>";
+    }
+    htmlStr += getLink(str, link, target, color);
+    if (!inList && getIndentPixels() > 0) {
+      htmlStr += "</div>";
+    } else if (inList) {
+      htmlStr += "</li>";
+    }
+    if (!inList) {
+      htmlStr += "<br>";
+    }
+    htmlBuff.append(htmlStr).append("\n");
+  }
+
+  private void newline() {
+    htmlBuff.append(
+      getNewLine());
+  }
+
+  private String getNewLine() {
+    return "<br>\n";
+  }
+
+  private void paragraph(LocalizableMessage description) {
+    if (description != null) {
+      paragraph(description.toString());
+    }
+  }
+
+  private void paragraph(String description) {
+    paragraph(description, TextStyle.STANDARD, null);
+  }
+
+  private void paragraph(String description, TextStyle style) {
+    paragraph(description, style, null);
+  }
+
+  private void paragraph(String description, TextStyle style, String pClass) {
+    String indentStr = "";
+    String styleStr = "";
+    String classStr = "";
+    if (getIndentPixels() > 0) {
+      indentStr = "style=\"margin-left: " + getIndentPixels() + "px;\"";
+    }
+    if (style == TextStyle.BOLD) {
+      styleStr = "style=\"font-weight: bold;\"";
+    } else if (style == TextStyle.ITALIC) {
+      styleStr = "style=\"font-style: italic;\"";
+    }
+    if (pClass != null) {
+      classStr = "class=" + pClass;
+    }
+
+    htmlBuff.append("<p ").append(indentStr).append(" ").append(styleStr).append(" ").append(classStr).append(">")
+        .append(description)
+        .append("</p>\n");
+  }
+
+  private int getIndentPixels() {
+    return ind * 40;
+  }
+
+  private void startTable() {
+    htmlBuff.append("<table ")
+            .append("style=\"width: 100%; text-align: left;\"")
+            .append("border=\"1\"")
+            .append("cellpadding=\"1\"")
+            .append("cellspacing=\"0\"")
+            .append(">\n");
+
+    htmlBuff.append("<tbody>\n");
+  }
+
+  /**
+   * Generate a "friendly" name from a string :
+   * '-' and '_' replaced by space
+   * first letter of a word in uppercase
+   */
+  private String getFriendlyName(String str) {
+    String retStr = "";
+    String[] words = str.split("\\p{Punct}");
+    for (int ii = 0; ii < words.length; ii++) {
+      if (ii>0) {
+        retStr += " ";
+      }
+      String word = words[ii];
+       String firstChar = word.substring(0, 1).toUpperCase();
+       retStr += firstChar + word.substring(1, word.length());
+    }
+    return retStr;
+  }
+
+  private void tableRow(String... strings) {
+    htmlBuff.append(
+      "<tr>\n");
+    for (int ii = 0; ii < strings.length; ii++) {
+      String string = strings[ii];
+      htmlBuff.append("<td style=\"")
+              .append("vertical-align: top; ")
+              .append(ii == 0 ? "width: 20%;" : "")
+              .append("\">")
+              .append(string)
+              .append("<br></td>");
+    }
+    htmlBuff.append(
+      "</tr>\n");
+  }
+
+  /**
+   * Text style.
+   */
+  private enum TextStyle {
+
+    STANDARD, BOLD, ITALIC, UNDERLINE, FIXED_WIDTH
+  }
+
+  private void beginList() {
+    inList = true;
+    listLevel++;
+    htmlBuff.append(
+      "<ul>\n");
+  }
+
+  private void endList() {
+    listLevel--;
+    if (listLevel == 0) {
+      inList = false;
+    }
+    htmlBuff.append(
+      "</ul>\n");
+  }
+
+  private void htmlFooter() {
+    htmlBuff.append("</body>\n").append("</html>\n");
+  }
+
+  private void viewHelp(String helpStr) {
+    htmlBuff.append("<p class=\"view-help\" >")
+            .append(helpStr)
+            .append("</p>")
+            .append("\n");
+  }
+
+  private void generateFile(String fileName) {
+    // Write the html buffer in a file
+    try {
+      PrintWriter file = new java.io.PrintWriter(
+        new java.io.FileWriter(generationDir + File.separator + fileName));
+      file.write(htmlBuff.toString());
+      file.close();
+    } catch (Exception e) {
+      e.printStackTrace();
+      System.exit(1);
+    }
+    // re-init html buffer
+    htmlBuff = new StringBuffer();
+  }
+
+  /** Relation List from RootConfiguration. */
+  private final TreeMap<String, RelationDefinition> topRelList = new TreeMap<>();
+  private final TreeMap<String, RelationDefinition> relList = new TreeMap<>();
+  private final TreeMap<String, TreeMap<String, RelationDefinition>> catTopRelList = new TreeMap<>();
+  /** Managed object list. */
+  private final TreeMap<String, AbstractManagedObjectDefinition> moList = new TreeMap<>();
+  private final TreeMap<String, AbstractManagedObjectDefinition> topMoList = new TreeMap<>();
+  private final TreeMap<String, TreeMap<String, AbstractManagedObjectDefinition>>
+    catTopMoList = new TreeMap<>();
+  private final int ind = 0;
+  private StringBuffer htmlBuff = new StringBuffer();
+  private static String generationDir;
+  private static boolean ldapMapping;
+  private static String OpenDJWiki;
+  private static String OpenDJHome;
+  private static String aciSyntaxPage;
+  private static String durationSyntaxPage;
+  private boolean inList;
+  private int listLevel;
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/package-info.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/package-info.java
new file mode 100644
index 0000000..7ebb434
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/doc/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2007-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2016 ForgeRock AS.
+ */
+
+
+
+/**
+ * Administration documentation classes.
+ * <p>
+ * This package contains classes used to generate administration documentation.
+ */
+@org.opends.server.types.PublicAPI(
+     stability=org.opends.server.types.StabilityLevel.PRIVATE)
+package org.opends.server.admin.doc;
+

--
Gitblit v1.10.0