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