/*
* 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 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.opends.server.tools.makeldif;
import org.forgerock.i18n.LocalizableMessage;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import static org.opends.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
/**
* This class defines a template, which is a pattern that may be used to
* generate entries. A template may be used either below a branch or below
* another template.
*/
public class Template
{
/**
* The attribute types that are used in the RDN for entries generated using
* this template.
*/
private AttributeType[] rdnAttributes;
/** The number of entries to create for each subordinate template. */
private int[] numEntriesPerTemplate;
/** The name for this template. */
private String name;
/** The names of the subordinate templates below this template. */
private String[] subordinateTemplateNames;
/** The subordinate templates below this template. */
private Template[] subordinateTemplates;
/** The template file that contains this template. */
private TemplateFile templateFile;
/** The set of template lines for this template. */
private TemplateLine[] templateLines;
/**
* Creates a new template with the provided information.
*
* @param templateFile The template file that contains this
* template.
* @param name The name for this template.
* @param rdnAttributes The set of attribute types that are used
* in the RDN for entries generated using
* this template.
* @param subordinateTemplateNames The names of the subordinate templates
* below this template.
* @param numEntriesPerTemplate The number of entries to create below
* each subordinate template.
*/
public Template(TemplateFile templateFile, String name,
AttributeType[] rdnAttributes,
String[] subordinateTemplateNames,
int[] numEntriesPerTemplate)
{
this.templateFile = templateFile;
this.name = name;
this.rdnAttributes = rdnAttributes;
this.subordinateTemplateNames = subordinateTemplateNames;
this.numEntriesPerTemplate = numEntriesPerTemplate;
templateLines = new TemplateLine[0];
subordinateTemplates = null;
}
/**
* Creates a new template with the provided information.
*
* @param templateFile The template file that contains this
* template.
* @param name The name for this template.
* @param rdnAttributes The set of attribute types that are used
* in the RDN for entries generated using
* this template.
* @param subordinateTemplateNames The names of the subordinate templates
* below this template.
* @param numEntriesPerTemplate The number of entries to create below
* each subordinate template.
* @param templateLines The set of template lines for this
* template.
*/
public Template(TemplateFile templateFile, String name,
AttributeType[] rdnAttributes,
String[] subordinateTemplateNames,
int[] numEntriesPerTemplate, TemplateLine[] templateLines)
{
this.templateFile = templateFile;
this.name = name;
this.rdnAttributes = rdnAttributes;
this.subordinateTemplateNames = subordinateTemplateNames;
this.numEntriesPerTemplate = numEntriesPerTemplate;
this.templateLines = templateLines;
subordinateTemplates = null;
}
/**
* Performs any necessary processing to ensure that the template
* initialization is completed. In particular, it should make sure that all
* referenced subordinate templates actually exist in the template file, and
* that all of the RDN attributes are contained in the template lines.
*
* @param templates The set of templates defined in the template file.
*
* @throws MakeLDIFException If any of the subordinate templates are not
* defined in the template file.
*/
public void completeTemplateInitialization(Map<String,Template> templates)
throws MakeLDIFException
{
// Make sure that all of the specified subordinate templates exist.
if (subordinateTemplateNames == null)
{
subordinateTemplateNames = new String[0];
subordinateTemplates = new Template[0];
}
else
{
subordinateTemplates = new Template[subordinateTemplateNames.length];
for (int i=0; i < subordinateTemplates.length; i++)
{
subordinateTemplates[i] =
templates.get(toLowerCase(subordinateTemplateNames[i]));
if (subordinateTemplates[i] == null)
{
LocalizableMessage message = ERR_MAKELDIF_UNDEFINED_TEMPLATE_SUBORDINATE.get(
subordinateTemplateNames[i], name);
throw new MakeLDIFException(message);
}
}
}
// Make sure that all of the RDN attributes are defined.
HashSet<AttributeType> rdnAttrs = new HashSet<>(rdnAttributes.length);
Collections.addAll(rdnAttrs, rdnAttributes);
for (TemplateLine l : templateLines)
{
if (rdnAttrs.remove(l.getAttributeType())
&& rdnAttrs.isEmpty())
{
break;
}
}
if (! rdnAttrs.isEmpty())
{
AttributeType t = rdnAttrs.iterator().next();
LocalizableMessage message =
ERR_MAKELDIF_TEMPLATE_MISSING_RDN_ATTR.get(name, t.getNameOrOID());
throw new MakeLDIFException(message);
}
}
/**
* Retrieves the name for this template.
*
* @return The name for this template.
*/
public String getName()
{
return name;
}
/**
* Retrieves the set of attribute types that are used in the RDN for entries
* generated using this template.
*
* @return The set of attribute types that are used in the RDN for entries
* generated using this template.
*/
public AttributeType[] getRDNAttributes()
{
return rdnAttributes;
}
/**
* Retrieves the names of the subordinate templates used to generate entries
* below entries created by this template.
*
* @return The names of the subordinate templates used to generate entries
* below entries created by this template.
*/
public String[] getSubordinateTemplateNames()
{
return subordinateTemplateNames;
}
/**
* Retrieves the subordinate templates used to generate entries below entries
* created by this template.
*
* @return The subordinate templates used to generate entries below entries
* created by this template.
*/
public Template[] getSubordinateTemplates()
{
return subordinateTemplates;
}
/**
* Retrieves the number of entries that should be created for each subordinate
* template.
*
* @return The number of entries that should be created for each subordinate
* template.
*/
public int[] getNumEntriesPerTemplate()
{
return numEntriesPerTemplate;
}
/**
* Retrieves the set of template lines for this template.
*
* @return The set of template lines for this template.
*/
public TemplateLine[] getTemplateLines()
{
return templateLines;
}
/**
* Adds the provided template line to this template.
*
* @param line The template line to add to this template.
*/
public void addTemplateLine(TemplateLine line)
{
TemplateLine[] newTemplateLines = new TemplateLine[templateLines.length+1];
System.arraycopy(templateLines, 0, newTemplateLines, 0,
templateLines.length);
newTemplateLines[templateLines.length] = line;
templateLines = newTemplateLines;
}
/**
* Indicates whether this template contains any template lines that reference
* the provided attribute type.
*
* @param attributeType The attribute type for which to make the
* determination.
*
* @return <CODE>true</CODE> if this template contains one or more template
* lines that reference the provided attribute type, or
* <CODE>false</CODE> if not.
*/
public boolean hasAttribute(AttributeType attributeType)
{
for (TemplateLine l : templateLines)
{
if (l.getAttributeType().equals(attributeType))
{
return true;
}
}
return false;
}
/**
* Writes the entry for this template, as well as all appropriate subordinate
* entries.
*
* @param entryWriter The entry writer that will be used to write the
* entries.
* @param parentDN The DN of the entry below which the subordinate
* entries should be generated.
* @param count The number of entries to generate based on this
* template.
*
* @return The result that indicates whether processing should continue.
*
* @throws IOException If a problem occurs while attempting to write to the
* LDIF writer.
*
* @throws MakeLDIFException If some other problem occurs.
*/
public TagResult writeEntries(EntryWriter entryWriter, DN parentDN, int count)
throws IOException, MakeLDIFException
{
for (int i=0; i < count; i++)
{
templateFile.nextFirstAndLastNames();
TemplateEntry templateEntry = new TemplateEntry(this, parentDN);
for (TemplateLine l : templateLines)
{
TagResult r = l.generateLine(templateEntry);
if (!r.keepProcessingEntry()
|| !r.keepProcessingParent()
|| !r.keepProcessingTemplateFile())
{
return r;
}
}
if (! entryWriter.writeEntry(templateEntry))
{
return TagResult.STOP_PROCESSING;
}
for (int j=0; j < subordinateTemplates.length; j++)
{
TagResult r =
subordinateTemplates[j].writeEntries(entryWriter,
templateEntry.getDN(), numEntriesPerTemplate[j]);
if (!r.keepProcessingParent()
|| !r.keepProcessingTemplateFile())
{
if (r.keepProcessingTemplateFile())
{
// We don't want to propagate a "stop processing parent" all the
// way up the chain.
return TagResult.SUCCESS_RESULT;
}
return r;
}
}
}
return TagResult.SUCCESS_RESULT;
}
}