001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools.makeldif; 018 019import static org.opends.messages.ToolMessages.*; 020import static org.opends.server.util.StaticUtils.*; 021 022import java.io.IOException; 023import java.util.Collections; 024import java.util.HashSet; 025import java.util.Map; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.opendj.ldap.DN; 029import org.forgerock.opendj.ldap.schema.AttributeType; 030 031/** 032 * This class defines a template, which is a pattern that may be used to 033 * generate entries. A template may be used either below a branch or below 034 * another template. 035 */ 036public class Template 037{ 038 /** 039 * The attribute types that are used in the RDN for entries generated using 040 * this template. 041 */ 042 private final AttributeType[] rdnAttributes; 043 /** The number of entries to create for each subordinate template. */ 044 private final int[] numEntriesPerTemplate; 045 /** The name for this template. */ 046 private final String name; 047 048 /** The names of the subordinate templates below this template. */ 049 private String[] subordinateTemplateNames; 050 /** The subordinate templates below this template. */ 051 private Template[] subordinateTemplates; 052 /** The template file that contains this template. */ 053 private final TemplateFile templateFile; 054 /** The set of template lines for this template. */ 055 private TemplateLine[] templateLines; 056 057 058 059 060 /** 061 * Creates a new template with the provided information. 062 * 063 * @param templateFile The template file that contains this 064 * template. 065 * @param name The name for this template. 066 * @param rdnAttributes The set of attribute types that are used 067 * in the RDN for entries generated using 068 * this template. 069 * @param subordinateTemplateNames The names of the subordinate templates 070 * below this template. 071 * @param numEntriesPerTemplate The number of entries to create below 072 * each subordinate template. 073 * @param templateLines The set of template lines for this 074 * template. 075 */ 076 public Template(TemplateFile templateFile, String name, 077 AttributeType[] rdnAttributes, 078 String[] subordinateTemplateNames, 079 int[] numEntriesPerTemplate, TemplateLine[] templateLines) 080 { 081 this.templateFile = templateFile; 082 this.name = name; 083 this.rdnAttributes = rdnAttributes; 084 this.subordinateTemplateNames = subordinateTemplateNames; 085 this.numEntriesPerTemplate = numEntriesPerTemplate; 086 this.templateLines = templateLines; 087 088 subordinateTemplates = null; 089 } 090 091 092 093 /** 094 * Performs any necessary processing to ensure that the template 095 * initialization is completed. In particular, it should make sure that all 096 * referenced subordinate templates actually exist in the template file, and 097 * that all of the RDN attributes are contained in the template lines. 098 * 099 * @param templates The set of templates defined in the template file. 100 * 101 * @throws MakeLDIFException If any of the subordinate templates are not 102 * defined in the template file. 103 */ 104 public void completeTemplateInitialization(Map<String,Template> templates) 105 throws MakeLDIFException 106 { 107 // Make sure that all of the specified subordinate templates exist. 108 if (subordinateTemplateNames == null) 109 { 110 subordinateTemplateNames = new String[0]; 111 subordinateTemplates = new Template[0]; 112 } 113 else 114 { 115 subordinateTemplates = new Template[subordinateTemplateNames.length]; 116 for (int i=0; i < subordinateTemplates.length; i++) 117 { 118 subordinateTemplates[i] = 119 templates.get(toLowerCase(subordinateTemplateNames[i])); 120 if (subordinateTemplates[i] == null) 121 { 122 LocalizableMessage message = ERR_MAKELDIF_UNDEFINED_TEMPLATE_SUBORDINATE.get( 123 subordinateTemplateNames[i], name); 124 throw new MakeLDIFException(message); 125 } 126 } 127 } 128 129 130 // Make sure that all of the RDN attributes are defined. 131 HashSet<AttributeType> rdnAttrs = new HashSet<>(rdnAttributes.length); 132 Collections.addAll(rdnAttrs, rdnAttributes); 133 134 for (TemplateLine l : templateLines) 135 { 136 if (rdnAttrs.remove(l.getAttributeType()) 137 && rdnAttrs.isEmpty()) 138 { 139 break; 140 } 141 } 142 143 if (! rdnAttrs.isEmpty()) 144 { 145 AttributeType t = rdnAttrs.iterator().next(); 146 LocalizableMessage message = 147 ERR_MAKELDIF_TEMPLATE_MISSING_RDN_ATTR.get(name, t.getNameOrOID()); 148 throw new MakeLDIFException(message); 149 } 150 } 151 152 153 154 /** 155 * Retrieves the name for this template. 156 * 157 * @return The name for this template. 158 */ 159 public String getName() 160 { 161 return name; 162 } 163 164 165 166 /** 167 * Retrieves the set of attribute types that are used in the RDN for entries 168 * generated using this template. 169 * 170 * @return The set of attribute types that are used in the RDN for entries 171 * generated using this template. 172 */ 173 public AttributeType[] getRDNAttributes() 174 { 175 return rdnAttributes; 176 } 177 178 179 180 /** 181 * Retrieves the names of the subordinate templates used to generate entries 182 * below entries created by this template. 183 * 184 * @return The names of the subordinate templates used to generate entries 185 * below entries created by this template. 186 */ 187 public String[] getSubordinateTemplateNames() 188 { 189 return subordinateTemplateNames; 190 } 191 192 193 194 /** 195 * Retrieves the subordinate templates used to generate entries below entries 196 * created by this template. 197 * 198 * @return The subordinate templates used to generate entries below entries 199 * created by this template. 200 */ 201 public Template[] getSubordinateTemplates() 202 { 203 return subordinateTemplates; 204 } 205 206 207 208 /** 209 * Retrieves the number of entries that should be created for each subordinate 210 * template. 211 * 212 * @return The number of entries that should be created for each subordinate 213 * template. 214 */ 215 public int[] getNumEntriesPerTemplate() 216 { 217 return numEntriesPerTemplate; 218 } 219 220 221 222 /** 223 * Retrieves the set of template lines for this template. 224 * 225 * @return The set of template lines for this template. 226 */ 227 public TemplateLine[] getTemplateLines() 228 { 229 return templateLines; 230 } 231 232 233 234 /** 235 * Adds the provided template line to this template. 236 * 237 * @param line The template line to add to this template. 238 */ 239 public void addTemplateLine(TemplateLine line) 240 { 241 TemplateLine[] newTemplateLines = new TemplateLine[templateLines.length+1]; 242 System.arraycopy(templateLines, 0, newTemplateLines, 0, 243 templateLines.length); 244 newTemplateLines[templateLines.length] = line; 245 templateLines = newTemplateLines; 246 } 247 248 249 250 /** 251 * Indicates whether this template contains any template lines that reference 252 * the provided attribute type. 253 * 254 * @param attributeType The attribute type for which to make the 255 * determination. 256 * 257 * @return <CODE>true</CODE> if this template contains one or more template 258 * lines that reference the provided attribute type, or 259 * <CODE>false</CODE> if not. 260 */ 261 public boolean hasAttribute(AttributeType attributeType) 262 { 263 for (TemplateLine l : templateLines) 264 { 265 if (l.getAttributeType().equals(attributeType)) 266 { 267 return true; 268 } 269 } 270 271 return false; 272 } 273 274 275 276 /** 277 * Writes the entry for this template, as well as all appropriate subordinate 278 * entries. 279 * 280 * @param entryWriter The entry writer that will be used to write the 281 * entries. 282 * @param parentDN The DN of the entry below which the subordinate 283 * entries should be generated. 284 * @param count The number of entries to generate based on this 285 * template. 286 * 287 * @return The result that indicates whether processing should continue. 288 * 289 * @throws IOException If a problem occurs while attempting to write to the 290 * LDIF writer. 291 * 292 * @throws MakeLDIFException If some other problem occurs. 293 */ 294 public TagResult writeEntries(EntryWriter entryWriter, DN parentDN, int count) 295 throws IOException, MakeLDIFException 296 { 297 for (int i=0; i < count; i++) 298 { 299 templateFile.nextFirstAndLastNames(); 300 TemplateEntry templateEntry = new TemplateEntry(this, parentDN); 301 302 for (TemplateLine l : templateLines) 303 { 304 TagResult r = l.generateLine(templateEntry); 305 if (!r.keepProcessingEntry() 306 || !r.keepProcessingParent() 307 || !r.keepProcessingTemplateFile()) 308 { 309 return r; 310 } 311 } 312 313 if (! entryWriter.writeEntry(templateEntry)) 314 { 315 return TagResult.STOP_PROCESSING; 316 } 317 318 for (int j=0; j < subordinateTemplates.length; j++) 319 { 320 TagResult r = 321 subordinateTemplates[j].writeEntries(entryWriter, 322 templateEntry.getDN(), numEntriesPerTemplate[j]); 323 if (!r.keepProcessingParent() 324 || !r.keepProcessingTemplateFile()) 325 { 326 if (r.keepProcessingTemplateFile()) 327 { 328 // We don't want to propagate a "stop processing parent" all the 329 // way up the chain. 330 return TagResult.SUCCESS_RESULT; 331 } 332 333 return r; 334 } 335 } 336 } 337 338 return TagResult.SUCCESS_RESULT; 339 } 340} 341