ConfigGuideGeneration.java revision a41662c1136b2bb4a4198df89e0e87d2be3ef099
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2007-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 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.opends.server.admin.ACIPropertyDefinition;
import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.AdministratorAction.Type;
import org.opends.server.admin.RelationDefinition;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.admin.*;
import org.opends.server.types.InitializationException;
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();
// Generate the relation tree of all the managed objects
genManagedObjectRelationTree(catTopRelList);
// Generate the inheritance tree of all the managed objects
genManagedObjectInheritanceTree(catTopMoList);
// Generate all the managed objects and their children
genAllManagedObject(topMoList);
// Generate a list of managed objects
genManagedObjectList(moList);
// Generate an index of properties
genPropertiesIndex();
// Generate the Index page
genIndexPage();
// Generate the Main Top page
genMainTopPage();
// Generate the Welcome page
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 {
ClassLoaderProvider.getInstance().enable();
} catch (InitializationException 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.
*/
@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();
}
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);
}
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;
}