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