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