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