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.ArrayList;
034 import java.util.List;
035 import java.util.Map;
036
037 import org.opends.server.core.DirectoryServer;
038 import org.opends.server.types.Attribute;
039 import org.opends.server.types.AttributeType;
040 import org.opends.server.types.AttributeValue;
041 import org.opends.server.types.DN;
042 import org.opends.server.types.Entry;
043
044 import static org.opends.messages.ToolMessages.*;
045 import static org.opends.server.util.StaticUtils.*;
046
047
048
049 /**
050 * This class defines a branch that should be included in the resulting LDIF. A
051 * branch may or may not have subordinate entries.
052 */
053 public class Branch
054 {
055 // The DN for this branch entry.
056 private DN branchDN;
057
058 // The number of entries that should be created below this branch for each
059 // subordinate template.
060 private int[] numEntriesPerTemplate;
061
062 // The names of the subordinate templates for this branch.
063 private String[] subordinateTemplateNames;
064
065 // The set of subordinate templates for this branch.
066 private Template[] subordinateTemplates;
067
068 // The template file in which this branch appears.
069 private TemplateFile templateFile;
070
071 // The set of template lines that correspond to the RDN components.
072 private TemplateLine[] rdnLines;
073
074 // The set of extra lines that should be included in this branch entry.
075 private TemplateLine[] extraLines;
076
077
078
079 /**
080 * Creates a new branch with the provided information.
081 *
082 * @param templateFile The template file in which this branch appears.
083 * @param branchDN The DN for this branch entry.
084 */
085 public Branch(TemplateFile templateFile, DN branchDN)
086 {
087 this(templateFile, branchDN, new String[0], new int[0],
088 new TemplateLine[0]);
089 }
090
091
092
093 /**
094 * Creates a new branch with the provided information.
095 *
096 * @param templateFile The template file in which this branch
097 * appears.
098 * @param branchDN The DN for this branch entry.
099 * @param subordinateTemplateNames The names of the subordinate templates
100 * used to generate entries below this
101 * branch.
102 * @param numEntriesPerTemplate The number of entries that should be
103 * created below this branch for each
104 * subordinate template.
105 * @param extraLines The set of extra lines that should be
106 * included in this branch entry.
107 */
108 public Branch(TemplateFile templateFile, DN branchDN,
109 String[] subordinateTemplateNames, int[] numEntriesPerTemplate,
110 TemplateLine[] extraLines)
111 {
112 this.templateFile = templateFile;
113 this.branchDN = branchDN;
114 this.subordinateTemplateNames = subordinateTemplateNames;
115 this.numEntriesPerTemplate = numEntriesPerTemplate;
116 this.extraLines = extraLines;
117
118 subordinateTemplates = null;
119
120
121 // Get the RDN template lines based just on the entry DN.
122 Entry entry = createEntry(branchDN);
123
124 ArrayList<Message> warnings = new ArrayList<Message>();
125 ArrayList<TemplateLine> lineList = new ArrayList<TemplateLine>();
126
127 for (String ocName : entry.getObjectClasses().values())
128 {
129 try
130 {
131 String[] valueStrings = new String[] { ocName };
132 Tag[] tags = new Tag[1];
133 tags[0] = new StaticTextTag();
134 tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
135 warnings);
136
137 TemplateLine l =
138 new TemplateLine(DirectoryServer.getObjectClassAttributeType(), 0,
139 tags);
140 lineList.add(l);
141 }
142 catch (Exception e)
143 {
144 // This should never happen.
145 e.printStackTrace();
146 }
147 }
148
149 for (List<Attribute> attrList : entry.getUserAttributes().values())
150 {
151 for (Attribute a : attrList)
152 {
153 for (AttributeValue v : a.getValues())
154 {
155 try
156 {
157 String[] valueStrings = new String[] { v.getStringValue() };
158 Tag[] tags = new Tag[1];
159 tags[0] = new StaticTextTag();
160 tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
161 warnings);
162 lineList.add(new TemplateLine(a.getAttributeType(), 0, tags));
163 }
164 catch (Exception e)
165 {
166 // This should never happen.
167 e.printStackTrace();
168 }
169 }
170 }
171 }
172
173 for (List<Attribute> attrList : entry.getOperationalAttributes().values())
174 {
175 for (Attribute a : attrList)
176 {
177 for (AttributeValue v : a.getValues())
178 {
179 try
180 {
181 String[] valueStrings = new String[] { v.getStringValue() };
182 Tag[] tags = new Tag[1];
183 tags[0] = new StaticTextTag();
184 tags[0].initializeForBranch(templateFile, this, valueStrings, 0,
185 warnings);
186 lineList.add(new TemplateLine(a.getAttributeType(), 0, tags));
187 }
188 catch (Exception e)
189 {
190 // This should never happen.
191 e.printStackTrace();
192 }
193 }
194 }
195 }
196
197 rdnLines = new TemplateLine[lineList.size()];
198 lineList.toArray(rdnLines);
199 }
200
201
202
203 /**
204 * Performs any necessary processing to ensure that the branch initialization
205 * is completed. In particular, it should make sure that all referenced
206 * subordinate templates actually exist in the template file.
207 *
208 * @param templates The set of templates defined in the template file.
209 *
210 * @throws MakeLDIFException If any of the subordinate templates are not
211 * defined in the template file.
212 */
213 public void completeBranchInitialization(Map<String,Template> templates)
214 throws MakeLDIFException
215 {
216 if (subordinateTemplateNames == null)
217 {
218 subordinateTemplateNames = new String[0];
219 subordinateTemplates = new Template[0];
220 }
221 else
222 {
223 subordinateTemplates = new Template[subordinateTemplateNames.length];
224 for (int i=0; i < subordinateTemplates.length; i++)
225 {
226 subordinateTemplates[i] =
227 templates.get(toLowerCase(subordinateTemplateNames[i]));
228 if (subordinateTemplates[i] == null)
229 {
230 Message message = ERR_MAKELDIF_UNDEFINED_BRANCH_SUBORDINATE.get(
231 subordinateTemplateNames[i], branchDN.toString());
232 throw new MakeLDIFException(message);
233 }
234 }
235 }
236 }
237
238
239
240 /**
241 * Retrieves the DN for this branch entry.
242 *
243 * @return The DN for this branch entry.
244 */
245 public DN getBranchDN()
246 {
247 return branchDN;
248 }
249
250
251
252 /**
253 * Retrieves the names of the subordinate templates for this branch.
254 *
255 * @return The names of the subordinate templates for this branch.
256 */
257 public String[] getSubordinateTemplateNames()
258 {
259 return subordinateTemplateNames;
260 }
261
262
263
264 /**
265 * Retrieves the set of subordinate templates used to generate entries below
266 * this branch. Note that the subordinate templates will not be available
267 * until the <CODE>completeBranchInitialization</CODE> method has been called.
268 *
269 * @return The set of subordinate templates used to generate entries below
270 * this branch.
271 */
272 public Template[] getSubordinateTemplates()
273 {
274 return subordinateTemplates;
275 }
276
277
278
279 /**
280 * Retrieves the number of entries that should be created below this branch
281 * for each subordinate template.
282 *
283 * @return The number of entries that should be created below this branch for
284 * each subordinate template.
285 */
286 public int[] getNumEntriesPerTemplate()
287 {
288 return numEntriesPerTemplate;
289 }
290
291
292
293 /**
294 * Adds a new subordinate template to this branch. Note that this should not
295 * be used after <CODE>completeBranchInitialization</CODE> has been called.
296 *
297 * @param name The name of the template to use to generate the
298 * entries.
299 * @param numEntries The number of entries to create based on the template.
300 */
301 public void addSubordinateTemplate(String name, int numEntries)
302 {
303 String[] newNames = new String[subordinateTemplateNames.length+1];
304 int[] newCounts = new int[numEntriesPerTemplate.length+1];
305
306 System.arraycopy(subordinateTemplateNames, 0, newNames, 0,
307 subordinateTemplateNames.length);
308 System.arraycopy(numEntriesPerTemplate, 0, newCounts, 0,
309 numEntriesPerTemplate.length);
310
311 newNames[subordinateTemplateNames.length] = name;
312 newCounts[numEntriesPerTemplate.length] = numEntries;
313
314 subordinateTemplateNames = newNames;
315 numEntriesPerTemplate = newCounts;
316 }
317
318
319
320 /**
321 * Retrieves the set of extra lines that should be included in this branch
322 * entry.
323 *
324 * @return The set of extra lines that should be included in this branch
325 * entry.
326 */
327 public TemplateLine[] getExtraLines()
328 {
329 return extraLines;
330 }
331
332
333
334 /**
335 * Adds the provided template line to the set of extra lines for this branch.
336 *
337 * @param line The line to add to the set of extra lines for this branch.
338 */
339 public void addExtraLine(TemplateLine line)
340 {
341 TemplateLine[] newExtraLines = new TemplateLine[extraLines.length+1];
342 System.arraycopy(extraLines, 0, newExtraLines, 0, extraLines.length);
343 newExtraLines[extraLines.length] = line;
344
345 extraLines = newExtraLines;
346 }
347
348
349
350 /**
351 * Indicates whether this branch contains a reference to the specified
352 * attribute type, either in the RDN components of the DN or in the extra
353 * lines.
354 *
355 * @param attributeType The attribute type for which to make the
356 * determination.
357 *
358 * @return <CODE>true</CODE> if the branch does contain the specified
359 * attribute type, or <CODE>false</CODE> if it does not.
360 */
361 public boolean hasAttribute(AttributeType attributeType)
362 {
363 if (branchDN.getRDN().hasAttributeType(attributeType))
364 {
365 return true;
366 }
367
368 for (TemplateLine l : extraLines)
369 {
370 if (l.getAttributeType().equals(attributeType))
371 {
372 return true;
373 }
374 }
375
376 return false;
377 }
378
379
380
381 /**
382 * Writes the entry for this branch, as well as all appropriate subordinate
383 * entries.
384 *
385 * @param entryWriter The entry writer to which the entries should be
386 * written.
387 *
388 * @return The result that indicates whether processing should continue.
389 *
390 * @throws IOException If a problem occurs while attempting to write to the
391 * LDIF writer.
392 *
393 * @throws MakeLDIFException If some other problem occurs.
394 */
395 public TagResult writeEntries(EntryWriter entryWriter)
396 throws IOException, MakeLDIFException
397 {
398 // Create a new template entry and populate it based on the RDN attributes
399 // and extra lines.
400 TemplateEntry entry = new TemplateEntry(this);
401
402 for (TemplateLine l : rdnLines)
403 {
404 TagResult r = l.generateLine(entry);
405 if (! (r.keepProcessingEntry() && r.keepProcessingParent() &&
406 r.keepProcessingTemplateFile()))
407 {
408 return r;
409 }
410 }
411
412 for (TemplateLine l : extraLines)
413 {
414 TagResult r = l.generateLine(entry);
415 if (! (r.keepProcessingEntry() && r.keepProcessingParent() &&
416 r.keepProcessingTemplateFile()))
417 {
418 return r;
419 }
420 }
421
422 if (! entryWriter.writeEntry(entry.toEntry()))
423 {
424 return TagResult.STOP_PROCESSING;
425 }
426
427
428 for (int i=0; i < subordinateTemplates.length; i++)
429 {
430 TagResult r =
431 subordinateTemplates[i].writeEntries(entryWriter, branchDN,
432 numEntriesPerTemplate[i]);
433 if (! (r.keepProcessingParent() && r.keepProcessingTemplateFile()))
434 {
435 if (r.keepProcessingTemplateFile())
436 {
437 // We don't want to propagate a "stop processing parent" all the way
438 // up the chain.
439 return TagResult.SUCCESS_RESULT;
440 }
441
442 return r;
443 }
444 }
445
446 return TagResult.SUCCESS_RESULT;
447 }
448 }
449