/* * 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; } }