From 869998098af41978080fadabbfab637030ec7aa3 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 19 Nov 2013 13:31:55 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1075 Port server make-ldif tool to the SDK CR-2586
---
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java | 450 +--
opendj3/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties | 41
opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/TemplateTagTestcase.java | 293 ++
opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template | 4
opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/people_and_groups.template | 62
opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java | 78
opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java | 346 ++
opendj3/opendj-core/src/main/java/com/forgerock/opendj/util/Pair.java | 152 +
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java | 2405 +++++++++-------------
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java | 2345 ++++-----------------
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java | 27
11 files changed, 2,512 insertions(+), 3,691 deletions(-)
diff --git a/opendj3/opendj-core/src/main/java/com/forgerock/opendj/util/Pair.java b/opendj3/opendj-core/src/main/java/com/forgerock/opendj/util/Pair.java
new file mode 100644
index 0000000..7953a69
--- /dev/null
+++ b/opendj3/opendj-core/src/main/java/com/forgerock/opendj/util/Pair.java
@@ -0,0 +1,152 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2013 ForgeRock AS
+ */
+package com.forgerock.opendj.util;
+
+/**
+ * Ordered pair of arbitrary objects.
+ *
+ * @param <F>
+ * type of the first pair element
+ * @param <S>
+ * type of the second pair element
+ */
+public final class Pair<F, S> {
+
+ /** An empty Pair. */
+ public static final Pair<?, ?> EMPTY = Pair.of(null, null);
+
+ /** The first pair element. */
+ private final F first;
+
+ /** The second pair element. */
+ private final S second;
+
+ /**
+ * Creates a pair.
+ *
+ * @param first
+ * the first element of the constructed pair
+ * @param second
+ * the second element of the constructed pair
+ */
+ private Pair(F first, S second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ /**
+ * Factory method to build a new Pair.
+ *
+ * @param first
+ * the first element of the constructed pair
+ * @param second
+ * the second element of the constructed pair
+ * @param <F>
+ * type of the first pair element
+ * @param <S>
+ * type of the second pair element
+ * @return A new Pair built with the provided elements
+ */
+ public static <F, S> Pair<F, S> of(F first, S second) {
+ return new Pair<F, S>(first, second);
+ }
+
+ /**
+ * Returns an empty Pair matching the required types.
+ *
+ * @param <F>
+ * type of the first pair element
+ * @param <S>
+ * type of the second pair element
+ * @return An empty Pair matching the required types
+ */
+ @SuppressWarnings("unchecked")
+ public static <F, S> Pair<F, S> empty() {
+ return (Pair<F, S>) EMPTY;
+ }
+
+ /**
+ * Returns the first element of this pair.
+ *
+ * @return the first element of this pair
+ */
+ public F getFirst() {
+ return first;
+ }
+
+ /**
+ * Returns the second element of this pair.
+ *
+ * @return the second element of this pair
+ */
+ public S getSecond() {
+ return second;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((first == null) ? 0 : first.hashCode());
+ result = prime * result + ((second == null) ? 0 : second.hashCode());
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Pair)) {
+ return false;
+ }
+ Pair<?, ?> other = (Pair<?, ?>) obj;
+ if (first == null) {
+ if (other.first != null) {
+ return false;
+ }
+ } else if (!first.equals(other.first)) {
+ return false;
+ }
+ if (second == null) {
+ if (other.second != null) {
+ return false;
+ }
+ } else if (!second.equals(other.second)) {
+ return false;
+ }
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "Pair [" + first + ", " + second + "]";
+ }
+
+}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
index 9372bad..efa55e7 100644
--- a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
@@ -31,6 +31,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -42,6 +43,7 @@
import com.forgerock.opendj.util.Iterators;
import com.forgerock.opendj.util.SubstringReader;
+import com.forgerock.opendj.util.Validator;
/**
* A relative distinguished name (RDN) as defined in RFC 4512 section 2.3 is the
@@ -216,7 +218,32 @@
this.avas = new AVA[] { new AVA(attributeType, attributeValue) };
}
+ /**
+ * Creates a new RDN using the provided AVAs.
+ *
+ * @param avas
+ * The attribute-value assertions used to build this RDN.
+ * @throws NullPointerException
+ * If {@code avas} is {@code null} or contains a null ava.
+ */
+ public RDN(final AVA... avas) {
+ this(avas, null);
+ }
+
+ /**
+ * Creates a new RDN using the provided AVAs.
+ *
+ * @param avas
+ * The attribute-value assertions used to build this RDN.
+ * @throws NullPointerException
+ * If {@code ava} is {@code null} or contains null ava.
+ */
+ public RDN(Collection<AVA> avas) {
+ this(avas.toArray(new AVA[avas.size()]), null);
+ }
+
private RDN(final AVA[] avas, final String stringValue) {
+ Validator.ensureNotNull((Object[]) avas);
this.avas = avas;
this.stringValue = stringValue;
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java
index ebbbbf1..6d56afd 100644
--- a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java
@@ -31,20 +31,17 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Random;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.schema.Schema;
-import org.forgerock.opendj.ldif.TemplateFile.EntryWriter;
-import org.forgerock.opendj.ldif.TemplateFile.TemplateEntry;
import com.forgerock.opendj.util.Validator;
@@ -52,247 +49,187 @@
* Generator of entries based on a {@code TemplateFile template file}, which can
* be provided as a file, a list of lines, an array of lines, or an input
* stream.
+ * <p>
+ * To build a generator with all default values, including default template
+ * file, use the empty constructor:
+ *
+ * <pre>
+ * generator = new EntryGenerator();
+ * </pre>
+ * <p>
+ * To build a generator with some custom values, use the non-empty constructor
+ * and the <code>set</code> methods:
+ *
+ * <pre>
+ * generator = new EntryGenerator(templatePath)
+ * .setResourcePath(path)
+ * .setSchema(schema)
+ * </pre>
*/
public final class EntryGenerator implements EntryReader {
- private static final TemplateEntry POISON_ENTRY = TemplateFile.TemplateEntry.NULL_TEMPLATE_ENTRY;
+ private static final int DEFAULT_RANDOM_SEED = 1;
/** Template file that contains directives for generation of entries. */
- private final TemplateFile templateFile;
+ private TemplateFile templateFile;
- /** Queue used to hold generated entries until they can be read. */
- private final BlockingQueue<TemplateEntry> entryQueue;
+ /** Warnings issued by the parsing of the template file. */
+ private final List<LocalizableMessage> warnings = new LinkedList<LocalizableMessage>();
- /** The next available entry. */
- private TemplateEntry nextEntry;
+ /** Indicates if the generator is closed. */
+ private boolean isClosed = false;
- private final List<LocalizableMessage> warnings;
+ /** Indicates if the generator is initialized, which means template file has been parsed. */
+ private boolean isInitialized = false;
- private volatile IOException ioException;
-
- private volatile boolean generationIsFinished = false;
-
- private volatile boolean isClosed = false;
-
- /** Thread that provides generation of entries. */
- private Thread generationThread;
+ /** Random seed is used to generate random data. */
+ private int randomSeed = DEFAULT_RANDOM_SEED;
/**
- * Creates a reader.
- *
- * @param templateFile
- * contains definition of entries to generate. It must have
- * already been parsed
- * @param warnings
- * list of warnings that were issued when parsing the template
- * file
- * @param entryQueue
- * used to hold generated entries and block generation until
- * entries are read
+ * Path to the directory that may contain additional resource files needed
+ * during the generation process. It may be {@code null}.
*/
- private EntryGenerator(TemplateFile templateFile, LinkedList<LocalizableMessage> warnings,
- BlockingQueue<TemplateEntry> entryQueue) {
- this.templateFile = templateFile;
- this.warnings = warnings;
- this.entryQueue = entryQueue;
+ private String resourcePath;
+
+ /**
+ * Schema is used to create attributes. If not provided, the default schema
+ * is used.
+ */
+ private Schema schema;
+
+ /**
+ * Path of template file, can be {@code null} if template file has been
+ * provided through another way.
+ */
+ private String templatePath;
+
+ /**
+ * Lines of template file, can be {@code null} if template file has been
+ * provided through another way.
+ */
+ private String[] templateLines;
+
+ /**
+ * Input stream containing template file, can be {@code null} if template
+ * file has been provided through another way.
+ */
+ private InputStream templateStream;
+
+ /** Dictionary of constants to use in the template file. */
+ private Map<String, String> constants = new HashMap<String, String>();
+
+ /**
+ * Creates a generator using default values.
+ * <p>
+ * The default template file will be used to generate entries.
+ */
+ public EntryGenerator() {
+ // nothing to do
}
/**
- * Returns a builder to create a reader based on a template file given by
- * the provided path.
+ * Creates a generator from the provided template path.
*
* @param templatePath
- * path of the template file
- * @return a builder allowing to create the reader
+ * Path of the template file.
*/
- public static Builder newReader(final String templatePath) {
- return new Builder(templatePath);
+ public EntryGenerator(final String templatePath) {
+ Validator.ensureNotNull(templatePath);
+ this.templatePath = templatePath;
}
/**
- * Returns a builder to create a reader based on a template file given by
- * the provided lines.
+ * Creates a generator from the provided template lines.
*
* @param templateLines
- * lines defining the template file
- * @return a builder allowing to create the reader
+ * Lines defining the template file.
*/
- public static Builder newReader(final String... templateLines) {
- return new Builder(templateLines);
+ public EntryGenerator(final String... templateLines) {
+ Validator.ensureNotNull((Object[]) templateLines);
+ this.templateLines = templateLines;
}
/**
- * Returns a builder to create a reader based on a template file given by
- * the provided lines.
+ * Creates a generator from the provided template lines.
*
* @param templateLines
- * lines defining the template file
- * @return a builder allowing to create the reader
+ * Lines defining the template file.
*/
- public static Builder newReader(final List<String> templateLines) {
- return new Builder(templateLines.toArray(new String[templateLines.size()]));
+ public EntryGenerator(final List<String> templateLines) {
+ Validator.ensureNotNull(templateLines);
+ this.templateLines = templateLines.toArray(new String[templateLines.size()]);
}
/**
- * Returns a builder to create a reader based on a template file given by
- * the provided stream.
+ * Creates a generator from the provided input stream.
*
* @param templateStream
- * input stream to read the template file
- * @return a builder allowing to create the reader
+ * Input stream to read the template file.
*/
- public static Builder newReader(final InputStream templateStream) {
- return new Builder(templateStream);
+ public EntryGenerator(final InputStream templateStream) {
+ Validator.ensureNotNull(templateStream);
+ this.templateStream = templateStream;
}
/**
- * Builder of {@code EntryGenerator readers}.
- * <p>
+ * Sets the random seed to use when generating entries.
*
- * To build a reader with all default values:
- * <pre>
- * {@code reader = EntryGenerator.newReader(...).build() }
- * </pre>
- * <p>
- *
- * To build a reader with some custom values, using the
- * <code>set</code> methods:
- * <pre>
- * {@code reader = EntryGenerator.newReader(...).
- * setResourcePath(path).
- * setSchema(schema).
- * build() }
- * </pre>
+ * @param seed
+ * Seed to use.
+ * @return A reference to this {@code EntryGenerator}.
*/
- public static final class Builder {
-
- private static final int DEFAULT_QUEUE_SIZE = 100;
- private static final int DEFAULT_RANDOM_SEED = 1;
- private static final String DEFAULT_RESOURCE_PATH = ".";
-
- private String templatePath;
- private String[] templateLines;
- private InputStream templateStream;
-
- private TemplateFile templateFile;
- private int maxNumberOfEntriesInQueue = DEFAULT_QUEUE_SIZE;
- private int randomSeed = DEFAULT_RANDOM_SEED;
- private String resourcePath = DEFAULT_RESOURCE_PATH;
- private Schema schema;
-
- private Builder(String templatePath) {
- this.templatePath = templatePath;
- }
-
- private Builder(String[] templateLines) {
- this.templateLines = templateLines;
- }
-
- private Builder(InputStream templateStream) {
- this.templateStream = templateStream;
- }
-
- /**
- * Sets the capacity of the queue holding generated entries.
- *
- * @param max
- * capacity of the queue that holds generated entries
- * @return A reference to this {@code EntryGenerator.Builder}.
- */
- public Builder setMaxNumberOfEntriesInQueue(final int max) {
- Validator.ensureTrue(max > 0, "queue capacity must be strictly superior to zero");
- maxNumberOfEntriesInQueue = max;
- return this;
- }
-
- /**
- * Sets the random seed to use when generating entries.
- *
- * @param seed
- * seed to use
- * @return A reference to this {@code EntryGenerator.Builder}.
- */
- public Builder setRandomSeed(final int seed) {
- randomSeed = seed;
- return this;
- }
-
- /**
- * Sets the resource path, used to looks for resources files like first
- * names, last names, or other custom resources.
- *
- * @param path
- * resource path
- * @return A reference to this {@code EntryGenerator.Builder}.
- */
- public Builder setResourcePath(final String path) {
- Validator.ensureNotNull(path);
- resourcePath = path;
- return this;
- }
-
- /**
- * Sets the schema which should be when generating entries. The default
- * schema is used if no other is specified.
- *
- * @param schema
- * The schema which should be used for generating entries.
- * @return A reference to this {@code EntryGenerator.Builder}.
- */
- public Builder setSchema(final Schema schema) {
- this.schema = schema;
- return this;
- }
-
- /**
- * Return an instance of reader.
- *
- * @return a new instance of reader
- * @throws IOException
- * If an error occurs while reading template file.
- * @throws DecodeException
- * If some other problem occurs during initialization
- */
- public EntryGenerator build() throws IOException, DecodeException {
- if (schema == null) {
- schema = Schema.getDefaultSchema();
- }
- templateFile = new TemplateFile(schema, resourcePath, new Random(randomSeed));
- LinkedList<LocalizableMessage> warnings = new LinkedList<LocalizableMessage>();
- try {
- if (templatePath != null) {
- templateFile.parse(templatePath, warnings);
- } else if (templateLines != null) {
- templateFile.parse(templateLines, warnings);
- } else if (templateStream != null) {
- templateFile.parse(templateStream, warnings);
- } else {
- // this should never happen
- throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_MISSING_TEMPLATE_FILE.get());
- }
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_EXCEPTION_DURING_PARSE.get(e.getMessage()), e);
- }
- EntryGenerator reader = new EntryGenerator(templateFile,
- warnings, new LinkedBlockingQueue<TemplateEntry>(maxNumberOfEntriesInQueue));
- reader.startEntriesGeneration();
- return reader;
- }
+ public EntryGenerator setRandomSeed(final int seed) {
+ randomSeed = seed;
+ return this;
}
/**
- * Start generation of entries by launching a separate thread.
+ * Sets the resource path, used to looks for resources files like first
+ * names, last names, or other custom resources.
+ *
+ * @param path
+ * Resource path.
+ * @return A reference to this {@code EntryGenerator}.
*/
- private void startEntriesGeneration() {
- generationThread =
- new Thread(new EntriesGenerator(new MakeEntryWriter(), templateFile), "MakeLDIF Generator Thread");
- generationThread.start();
+ public EntryGenerator setResourcePath(final String path) {
+ Validator.ensureNotNull(path);
+ resourcePath = path;
+ return this;
+ }
+
+ /**
+ * Sets the schema which should be when generating entries. The default
+ * schema is used if no other is specified.
+ *
+ * @param schema
+ * The schema which should be used for generating entries.
+ * @return A reference to this {@code EntryGenerator}.
+ */
+ public EntryGenerator setSchema(final Schema schema) {
+ this.schema = schema;
+ return this;
+ }
+
+ /**
+ * Sets a constant to use in template file. It overrides the constant set in
+ * the template file.
+ *
+ * @param name
+ * Name of the constant.
+ * @param value
+ * Value of the constant.
+ * @return A reference to this {@code EntryGenerator}.
+ */
+ public EntryGenerator setConstant(String name, Object value) {
+ constants.put(name, value.toString());
+ return this;
}
/**
* Checks if there are some warning(s) after the parsing of template file.
+ * <p>
+ * Warnings are available only after the first call to {@code hasNext()} or
+ * {@code readEntry()} methods.
*
* @return true if there is at least one warning
*/
@@ -302,6 +239,9 @@
/**
* Returns the warnings generated by the parsing of template file.
+ * <p>
+ * Warnings are available only after the first call to {@code hasNext()}
+ * or {@code readEntry()} methods.
*
* @return the list of warnings, which is empty if there is no warning
*/
@@ -312,120 +252,60 @@
@Override
public void close() {
isClosed = true;
- ioException = null;
- try {
- generationThread.join(0);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
}
@Override
public boolean hasNext() throws IOException {
if (isClosed) {
return false;
- } else if (ioException != null) {
- throw ioException;
- } else if (nextEntry != null) {
- return true;
- } else if (generationIsFinished) {
- nextEntry = entryQueue.poll();
- } else {
- try {
- nextEntry = entryQueue.take();
- } catch (InterruptedException ie) {
- Thread.currentThread().interrupt();
- }
}
- if (nextEntry == POISON_ENTRY) {
- nextEntry = null;
- }
- return nextEntry != null;
+ ensureGeneratorIsInitialized();
+ return templateFile.hasNext();
}
@Override
public Entry readEntry() throws IOException {
if (!hasNext()) {
- // LDIF reader has completed successfully.
throw new NoSuchElementException();
} else {
- final Entry entry = nextEntry.toEntry();
- nextEntry = null;
- return entry;
+ return templateFile.nextEntry();
}
}
/**
- * Entry writer that store entries into the entry queue of this reader, and
- * record close and exception events.
+ * Check that generator is initialized, and initialize it
+ * if it has not been initialized.
*/
- private final class MakeEntryWriter implements EntryWriter {
-
- @Override
- public boolean writeEntry(final TemplateEntry entry) {
- while (!isClosed) {
- try {
- if (entryQueue.offer(entry, 500, TimeUnit.MILLISECONDS)) {
- return true;
- }
- } catch (InterruptedException ie) {
- // nothing to do
- }
- }
- return false;
- }
-
- @Override
- public void closeEntryWriter() {
- generationIsFinished = true;
- writeEntry(POISON_ENTRY);
- }
-
- public void setIOException(final IOException ioe) {
- ioException = ioe;
+ private void ensureGeneratorIsInitialized() throws IOException {
+ if (!isInitialized) {
+ isInitialized = true;
+ initialize();
}
}
-
/**
- * Generator of entries, that writes entries to a provided
- * {@code EntryWriter writer}.
+ * Initializes the generator, by retrieving template file and parsing it.
*/
- private static final class EntriesGenerator implements Runnable {
-
- private final MakeEntryWriter entryWriter;
-
- private final TemplateFile templateFile;
-
- /**
- * Creates a generator that writes to provided writer using the provided
- * template file.
- *
- * @param entryWriter
- * @param templateFile
- */
- EntriesGenerator(final MakeEntryWriter entryWriter, final TemplateFile templateFile) {
- this.entryWriter = entryWriter;
- this.templateFile = templateFile;
+ private void initialize() throws IOException {
+ if (schema == null) {
+ schema = Schema.getDefaultSchema();
}
-
- /**
- * Run the generation of entries.
- */
- public void run() {
- generate();
- }
-
- /**
- * Generates entries to the entry writer.
- */
- void generate() {
- try {
- templateFile.generateEntries(entryWriter);
- } catch (IOException e) {
- entryWriter.setIOException(e);
- entryWriter.closeEntryWriter();
+ templateFile = new TemplateFile(schema, constants, resourcePath, new Random(randomSeed));
+ try {
+ if (templatePath != null) {
+ templateFile.parse(templatePath, warnings);
+ } else if (templateLines != null) {
+ templateFile.parse(templateLines, warnings);
+ } else if (templateStream != null) {
+ templateFile.parse(templateStream, warnings);
+ } else {
+ // use default template file
+ templateFile.parse(warnings);
}
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_EXCEPTION_DURING_PARSE.get(e.getMessage()), e);
}
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java
index 4af2d24..4b5d35e 100644
--- a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java
@@ -36,29 +36,30 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Random;
+import java.util.Set;
import java.util.StringTokenizer;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.AVA;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.AttributeDescription;
-import org.forgerock.opendj.ldap.AttributeFactory;
+import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.DecodeException;
-import org.forgerock.opendj.ldap.Entries;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.LinkedAttribute;
import org.forgerock.opendj.ldap.LinkedHashMapEntry;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.ldap.schema.CoreSchema;
-import org.forgerock.opendj.ldap.schema.ObjectClass;
import org.forgerock.opendj.ldap.schema.Schema;
import org.forgerock.opendj.ldif.TemplateTag.AttributeValueTag;
import org.forgerock.opendj.ldif.TemplateTag.DNTag;
@@ -79,7 +80,9 @@
import org.forgerock.opendj.ldif.TemplateTag.UnderscoreDNTag;
import org.forgerock.opendj.ldif.TemplateTag.UnderscoreParentDNTag;
+import com.forgerock.opendj.util.Pair;
import com.forgerock.opendj.util.StaticUtils;
+import com.forgerock.opendj.util.Validator;
/**
* A template file allow to generate entries from a collection of constant
@@ -88,21 +91,24 @@
* @see EntryGenerator
*/
class TemplateFile {
- /**
- * The name of the file holding the list of first names.
- */
- public static final String FIRST_NAME_FILE = "first.names";
- /**
- * The name of the file holding the list of last names.
- */
- public static final String LAST_NAME_FILE = "last.names";
+ /** Default resource path used if no resource path is provided. */
+ private static final File DEFAULT_RESOURCES_PATH = new File("org/forgerock/opendj/ldif");
+
+ /** Default template path used if no template file is provided. */
+ private static final String DEFAULT_TEMPLATE_PATH = "example.template";
+
+ /** The name of the file holding the list of first names. */
+ private static final String FIRST_NAME_FILE = "first.names";
+
+ /** The name of the file holding the list of last names. */
+ private static final String LAST_NAME_FILE = "last.names";
/**
* A map of the contents of various text files used during the parsing
* process, mapped from absolute path to the array of lines in the file.
*/
- private Map<String, String[]> fileLines;
+ private final Map<String, String[]> fileLines = new HashMap<String, String[]>();
/** The index of the next first name value that should be used. */
private int firstNameIndex;
@@ -120,22 +126,22 @@
* A counter that will be used in case we have exhausted all possible first
* and last name combinations.
*/
- private int nameUniquenessCounter;
+ private int nameUniquenessCounter = 1;
/** The set of branch definitions for this template file. */
- private Map<DN, Branch> branches;
+ private final Map<DN, Branch> branches = new LinkedHashMap<DN, Branch>();
/** The set of constant definitions for this template file. */
- private Map<String, String> constants;
+ private final Map<String, String> constants;
/** The set of registered tags for this template file. */
- private Map<String, TemplateTag> registeredTags;
+ private final Map<String, TemplateTag> registeredTags = new LinkedHashMap<String, TemplateTag>();
/** The set of template definitions for this template file. */
- private Map<String, Template> templates;
+ private final Map<String, Template> templates = new LinkedHashMap<String, Template>();
/** The random number generator for this template file. */
- private Random random;
+ private final Random random;
/** The next first name that should be used. */
private String firstName;
@@ -149,14 +155,11 @@
*/
private String resourcePath;
- /** The path to the directory containing the template file, if available. */
- private String templatePath;
-
/** The set of first names to use when generating the LDIF. */
- private String[] firstNames;
+ private String[] firstNames = new String[0];
/** The set of last names to use when generating the LDIF. */
- private String[] lastNames;
+ private String[] lastNames = new String[0];
/** Schema used to create attributes. */
private final Schema schema;
@@ -165,110 +168,54 @@
* Creates a new, empty template file structure.
*
* @param schema
- * LDAP Schema to use
+ * LDAP Schema to use.
+ * @param constants
+ * Constants to use, override any constant defined in the
+ * template file. May be {@code null}.
* @param resourcePath
* The path to the directory that may contain additional resource
- * files needed during the generation process.
+ * files needed during the generation process. May be
+ * {@code null}.
+ * @throws IOException
+ * if a problem occurs when initializing
*/
- public TemplateFile(Schema schema, String resourcePath) {
- this(schema, resourcePath, new Random());
+ TemplateFile(Schema schema, Map<String, String> constants, String resourcePath) throws IOException {
+ this(schema, constants, resourcePath, new Random());
}
/**
* Creates a new, empty template file structure.
*
* @param schema
- * used to create attributes
+ * LDAP Schema to use.
+ * @param constants
+ * Constants to use, override any constant defined in the
+ * template file. May be {@code null}.
* @param resourcePath
* The path to the directory that may contain additional resource
- * files needed during the generation process.
+ * files needed during the generation process. May be
+ * {@code null}.
* @param random
* The random number generator for this template file.
+ * @throws IOException
+ * if a problem occurs when initializing
*/
- public TemplateFile(Schema schema, String resourcePath, Random random) {
+ TemplateFile(Schema schema, Map<String, String> constants, String resourcePath, Random random)
+ throws IOException {
+ Validator.ensureNotNull(schema, random);
this.schema = schema;
+ this.constants = constants != null ? constants : new HashMap<String, String>();
this.resourcePath = resourcePath;
this.random = random;
-
- fileLines = new HashMap<String, String[]>();
- branches = new LinkedHashMap<DN, Branch>();
- constants = new LinkedHashMap<String, String>();
- registeredTags = new LinkedHashMap<String, TemplateTag>();
- templates = new LinkedHashMap<String, Template>();
- templatePath = null;
- firstNames = new String[0];
- lastNames = new String[0];
- firstName = null;
- lastName = null;
- firstNameIndex = 0;
- lastNameIndex = 0;
- nameLoopCounter = 0;
- nameUniquenessCounter = 1;
-
registerDefaultTags();
-
- readNames();
+ retrieveFirstAndLastNames();
}
- /**
- * Retrieves the set of tags that have been registered. They will be in the
- * form of a mapping between the name of the tag (in all lowercase
- * characters) and the corresponding tag implementation.
- *
- * @return The set of tags that have been registered.
- */
- public Map<String, TemplateTag> getTags() {
- return registeredTags;
- }
-
- /**
- * Retrieves the tag with the specified name.
- *
- * @param lowerName
- * The name of the tag to retrieve, in all lowercase characters.
- * @return The requested tag, or <CODE>null</CODE> if no such tag has been
- * registered.
- */
- public TemplateTag getTag(String lowerName) {
+ TemplateTag getTag(String lowerName) {
return registeredTags.get(lowerName);
}
/**
- * Registers the specified class as a tag that may be used in templates.
- *
- * @param tagClass
- * The fully-qualified name of the class to register as a tag.
- * @throws DecodeException
- * If a problem occurs while attempting to register the
- * specified tag.
- */
- public void registerTag(String tagClass) throws DecodeException {
- Class<?> c;
- try {
- c = Class.forName(tagClass);
- } catch (Exception e) {
- final LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_LOAD_TAG_CLASS.get(tagClass);
- throw DecodeException.fatalError(message, e);
- }
-
- TemplateTag t;
- try {
- t = (TemplateTag) c.newInstance();
- } catch (Exception e) {
- final LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG.get(tagClass);
- throw DecodeException.fatalError(message, e);
- }
-
- String lowerName = t.getName().toLowerCase();
- if (registeredTags.containsKey(lowerName)) {
- final LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_TAG_NAME.get(tagClass, t.getName());
- throw DecodeException.fatalError(message);
- } else {
- registeredTags.put(lowerName, t);
- }
- }
-
- /**
* Registers the set of tags that will always be available for use in
* templates.
*/
@@ -278,182 +225,45 @@
ListTag.class, ParentDNTag.class, PresenceTag.class, RandomTag.class, RDNTag.class,
SequentialTag.class, StaticTextTag.class, UnderscoreDNTag.class, UnderscoreParentDNTag.class };
- for (Class<?> c : defaultTagClasses) {
+ for (final Class<?> c : defaultTagClasses) {
try {
- TemplateTag t = (TemplateTag) c.newInstance();
+ final TemplateTag t = (TemplateTag) c.newInstance();
registeredTags.put(t.getName().toLowerCase(), t);
} catch (Exception e) {
- // this should never happen
- StaticUtils.DEFAULT_LOG.error(ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG.get(c.getName()).toString());
+ // this is a programming error
+ throw new RuntimeException(ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG.get(c.getName()).toString(), e);
}
}
}
- /**
- * Retrieves the set of constants defined for this template file.
- *
- * @return The set of constants defined for this template file.
- */
- public Map<String, String> getConstants() {
- return constants;
- }
-
- /**
- * Retrieves the value of the constant with the specified name.
- *
- * @param lowerName
- * The name of the constant to retrieve, in all lowercase
- * characters.
- * @return The value of the constant with the specified name, or
- * <CODE>null</CODE> if there is no such constant.
- */
- public String getConstant(String lowerName) {
- return constants.get(lowerName);
- }
-
- /**
- * Registers the provided constant for use in the template.
- *
- * @param name
- * The name for the constant.
- * @param value
- * The value for the constant.
- */
- public void registerConstant(String name, String value) {
- constants.put(name.toLowerCase(), value);
- }
-
- /**
- * Retrieves the set of branches defined in this template file.
- *
- * @return The set of branches defined in this template file.
- */
- public Map<DN, Branch> getBranches() {
- return branches;
- }
-
- /**
- * Retrieves the branch registered with the specified DN.
- *
- * @param branchDN
- * The DN for which to retrieve the corresponding branch.
- * @return The requested branch, or <CODE>null</CODE> if no such branch has
- * been registered.
- */
- public Branch getBranch(DN branchDN) {
- return branches.get(branchDN);
- }
-
- /**
- * Registers the provided branch in this template file.
- *
- * @param branch
- * The branch to be registered.
- */
- public void registerBranch(Branch branch) {
- branches.put(branch.getBranchDN(), branch);
- }
-
- /**
- * Retrieves the set of templates defined in this template file.
- *
- * @return The set of templates defined in this template file.
- */
- public Map<String, Template> getTemplates() {
- return templates;
- }
-
- /**
- * Retrieves the template with the specified name.
- *
- * @param lowerName
- * The name of the template to retrieve, in all lowercase
- * characters.
- * @return The requested template, or <CODE>null</CODE> if there is no such
- * template.
- */
- public Template getTemplate(String lowerName) {
- return templates.get(lowerName);
- }
-
- /**
- * Registers the provided template for use in this template file.
- *
- * @param template
- * The template to be registered.
- */
- public void registerTemplate(Template template) {
- templates.put(template.getName().toLowerCase(), template);
- }
-
- /**
- * Retrieves the random number generator for this template file.
- *
- * @return The random number generator for this template file.
- */
- public Random getRandom() {
+ Random getRandom() {
return random;
}
- /**
- * Reads the first and last names in standard files or use default values if
- * files can't be read.
- */
- private void readNames() {
- firstNames = readNamesFromFile(FIRST_NAME_FILE);
- if (firstNames == null) {
- firstNames = new String[] { "Christophe", "Gael", "Gary", "Jean-Noel", "Laurent", "Ludovic", "Mark",
- "Matthew", "Nicolas", "Violette" };
- }
- lastNames = readNamesFromFile(LAST_NAME_FILE);
- if (lastNames == null) {
- lastNames = new String[] { "Maahs", "Maas", "Mabes", "Mabson", "Mabuchi", "Mac", "Mac Maid", "MacAdams",
- "MacArthur", "MacCarthy" };
- }
- }
-
- /**
- * Returns an array of names read in the provided file, or null if a problem
- * occurs.
- */
- private String[] readNamesFromFile(String fileName) {
- String[] names = null;
- File file = getFile(fileName);
- if (file != null) {
- try {
- List<String> nameList = readDataFile(file);
- names = new String[nameList.size()];
- nameList.toArray(names);
- } catch (IOException e) {
- // TODO : I18N
- StaticUtils.DEFAULT_LOG.error("Unable to read names file {}", fileName);
- }
- }
- return names;
- }
-
- /**
- * Read a file of data, and return a list containing one item per line.
- */
- private List<String> readDataFile(File file) throws FileNotFoundException, IOException {
- List<String> data = new ArrayList<String>();
- BufferedReader reader = null;
+ private void retrieveFirstAndLastNames() throws IOException {
+ BufferedReader first = null;
try {
- reader = new BufferedReader(new FileReader(file));
- while (true) {
- String line = reader.readLine();
- if (line == null) {
- break;
- } else {
- data.add(line);
- }
+ first = getReader(FIRST_NAME_FILE);
+ if (first == null) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_COULD_NOT_FIND_NAME_FILE.get(FIRST_NAME_FILE));
}
+ final List<String> names = readLines(first);
+ firstNames = names.toArray(new String[names.size()]);
} finally {
- if (reader != null) {
- reader.close();
- }
+ StaticUtils.closeSilently(first);
}
- return data;
+
+ BufferedReader last = null;
+ try {
+ last = getReader(LAST_NAME_FILE);
+ if (last == null) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_COULD_NOT_FIND_NAME_FILE.get(LAST_NAME_FILE));
+ }
+ final List<String> names = readLines(last);
+ lastNames = names.toArray(new String[names.size()]);
+ } finally {
+ StaticUtils.closeSilently(first);
+ }
}
/**
@@ -463,22 +273,21 @@
* names and the number of last names being relatively prime. This method
* should be called before beginning generation of each template entry.
*/
- public void nextFirstAndLastNames() {
+ void nextFirstAndLastNames() {
firstName = firstNames[firstNameIndex++];
lastName = lastNames[lastNameIndex++];
- // If we've already exhausted every possible combination, then append an
- // integer to the last name.
+ // If we've already exhausted every possible combination
+ // then append an integer to the last name.
if (nameUniquenessCounter > 1) {
lastName += nameUniquenessCounter;
}
if (firstNameIndex >= firstNames.length) {
- // We're at the end of the first name list, so start over. If the
- // first
- // name list is larger than the last name list, then we'll also need
- // to
- // set the last name index to the next loop counter position.
+ // We're at the end of the first name list, so start over.
+ // If the first name list is larger than the last name list,
+ // then we'll also need to set the last name index
+ // to the next loop counter position.
firstNameIndex = 0;
if (firstNames.length > lastNames.length) {
lastNameIndex = ++nameLoopCounter;
@@ -490,11 +299,10 @@
}
if (lastNameIndex >= lastNames.length) {
- // We're at the end of the last name list, so start over. If the
- // last
- // name list is larger than the first name list, then we'll also
- // need to
- // set the first name index to the next loop counter position.
+ // We're at the end of the last name list, so start over.
+ // If the last name list is larger than the first name list,
+ // then we'll also need to set the first name index
+ // to the next loop counter position.
lastNameIndex = 0;
if (lastNames.length > firstNames.length) {
firstNameIndex = ++nameLoopCounter;
@@ -506,29 +314,35 @@
}
}
- /**
- * Retrieves the first name value that should be used for the current entry.
- *
- * @return The first name value that should be used for the current entry.
- */
- public String getFirstName() {
+ String getFirstName() {
return firstName;
}
- /**
- * Retrieves the last name value that should be used for the current entry.
- *
- * @return The last name value that should be used for the current entry.
- */
- public String getLastName() {
+ String getLastName() {
return lastName;
}
/**
- * Parses the contents of the specified file as a MakeLDIF template file
- * definition.
+ * Parses the contents of the default template file definition, that will be
+ * used to generate entries.
*
- * @param filename
+ * @param warnings
+ * A list into which any warnings identified may be placed.
+ * @throws IOException
+ * If a problem occurs while attempting to read data from the
+ * default template file.
+ * @throws DecodeException
+ * If any other problem occurs while parsing the template file.
+ */
+ void parse(List<LocalizableMessage> warnings) throws IOException, DecodeException {
+ parse(DEFAULT_TEMPLATE_PATH, warnings);
+ }
+
+ /**
+ * Parses the contents of the provided file as an entry generator template
+ * file definition.
+ *
+ * @param templateFilename
* The name of the file containing the template data.
* @param warnings
* A list into which any warnings identified may be placed.
@@ -538,37 +352,31 @@
* @throws DecodeException
* If any other problem occurs while parsing the template file.
*/
- public void parse(String filename, List<LocalizableMessage> warnings) throws IOException, DecodeException {
- ArrayList<String> fileLines = new ArrayList<String>();
-
- templatePath = null;
- File f = getFile(filename);
- if ((f == null) || (!f.exists())) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_COULD_NOT_FIND_TEMPLATE_FILE.get(filename);
- throw new IOException(message.toString());
- } else {
- templatePath = f.getParentFile().getAbsolutePath();
- }
-
- BufferedReader reader = new BufferedReader(new FileReader(f));
- while (true) {
- String line = reader.readLine();
- if (line == null) {
- break;
- } else {
- fileLines.add(line);
+ void parse(String templateFilename, List<LocalizableMessage> warnings) throws IOException, DecodeException {
+ BufferedReader templateReader = null;
+ try {
+ templateReader = getReader(templateFilename);
+ if (templateReader == null) {
+ throw DecodeException.fatalError(
+ ERR_ENTRY_GENERATOR_COULD_NOT_FIND_TEMPLATE_FILE.get(templateFilename));
}
+ if (resourcePath == null) {
+ // Use the template file directory as resource path
+ final File file = getFile(templateFilename);
+ if (file != null) {
+ resourcePath = file.getParentFile().getAbsolutePath();
+ }
+ }
+ final List<String> fileLines = readLines(templateReader);
+ final String[] lines = fileLines.toArray(new String[fileLines.size()]);
+ parse(lines, warnings);
+ } finally {
+ StaticUtils.closeSilently(templateReader);
}
-
- reader.close();
-
- String[] lines = new String[fileLines.size()];
- fileLines.toArray(lines);
- parse(lines, warnings);
}
/**
- * Parses the data read from the provided input stream as a MakeLDIF
+ * Parses the contents of the provided input stream as an entry generator
* template file definition.
*
* @param inputStream
@@ -581,28 +389,48 @@
* @throws DecodeException
* If any other problem occurs while parsing the template.
*/
- public void parse(InputStream inputStream, List<LocalizableMessage> warnings) throws IOException, DecodeException {
- ArrayList<String> fileLines = new ArrayList<String>();
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
- while (true) {
- String line = reader.readLine();
- if (line == null) {
- break;
- } else {
- fileLines.add(line);
- }
+ void parse(InputStream inputStream, List<LocalizableMessage> warnings) throws IOException, DecodeException {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(inputStream));
+ final List<String> fileLines = readLines(reader);
+ final String[] lines = fileLines.toArray(new String[fileLines.size()]);
+ parse(lines, warnings);
+ } finally {
+ StaticUtils.closeSilently(reader);
}
+ }
- reader.close();
+ private static final String INCLUDE_LABEL = "include ";
+ private static final String DEFINE_LABEL = "define ";
+ private static final String BRANCH_LABEL = "branch: ";
+ private static final String TEMPLATE_LABEL = "template: ";
+ private static final String SUBORDINATE_TEMPLATE_LABEL = "subordinatetemplate: ";
+ private static final String RDNATTR_LABEL = "rdnattr: ";
+ private static final String EXTENDS_LABEL = "extends: ";
- String[] lines = new String[fileLines.size()];
- fileLines.toArray(lines);
- parse(lines, warnings);
+ /**
+ * Structure to hold template data during parsing of the template.
+ */
+ private static class TemplateData {
+ final Map<String, TemplateTag> tags = new LinkedHashMap<String, TemplateTag>();
+ final Map<DN, Branch> branches = new LinkedHashMap<DN, Branch>();
+ final Map<String, Template> templates = new LinkedHashMap<String, Template>();
}
/**
- * Parses the provided data as a MakeLDIF template file definition.
+ * Enumeration of elements that act as "container" of other elements.
+ */
+ private enum Element {
+ BRANCH, TEMPLATE;
+
+ String getLabel() {
+ return toString().toLowerCase();
+ }
+ }
+
+ /**
+ * Parses the provided lines as an entry generator template file definition.
*
* @param lines
* The lines that make up the template file.
@@ -611,168 +439,183 @@
* @throws DecodeException
* If any other problem occurs while parsing the template lines.
*/
- public void parse(String[] lines, List<LocalizableMessage> warnings) throws DecodeException {
- // Create temporary variables that will be used to hold the data read.
- LinkedHashMap<String, TemplateTag> templateFileIncludeTags = new LinkedHashMap<String, TemplateTag>();
- LinkedHashMap<String, String> templateFileConstants = new LinkedHashMap<String, String>();
- LinkedHashMap<DN, Branch> templateFileBranches = new LinkedHashMap<DN, Branch>();
- LinkedHashMap<String, Template> templateFileTemplates = new LinkedHashMap<String, Template>();
+ void parse(final String[] lines, final List<LocalizableMessage> warnings) throws DecodeException {
+ TemplateData templateData = new TemplateData();
for (int lineNumber = 0; lineNumber < lines.length; lineNumber++) {
- String line = lines[lineNumber];
+ final String line = replaceConstants(lines[lineNumber], lineNumber, constants, warnings);
- line = replaceConstants(line, lineNumber, templateFileConstants, warnings);
-
- String lowerLine = line.toLowerCase();
+ final String lowerLine = line.toLowerCase();
if ((line.length() == 0) || line.startsWith("#")) {
// This is a comment or a blank line, so we'll ignore it.
continue;
- } else if (lowerLine.startsWith("include ")) {
- // This should be an include definition. The next element should
- // be the
- // name of the class. Load and instantiate it and make sure
- // there are
- // no conflicts.
- String className = line.substring(8).trim();
-
- Class<?> tagClass;
- try {
- tagClass = Class.forName(className);
- } catch (Exception e) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_LOAD_TAG_CLASS.get(className);
- throw DecodeException.fatalError(message, e);
- }
-
- TemplateTag tag;
- try {
- tag = (TemplateTag) tagClass.newInstance();
- } catch (Exception e) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG.get(className);
- throw DecodeException.fatalError(message, e);
- }
-
- String lowerName = tag.getName().toLowerCase();
- if (registeredTags.containsKey(lowerName) || templateFileIncludeTags.containsKey(lowerName)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_TAG_NAME.get(className, tag.getName());
- throw DecodeException.fatalError(message);
- }
-
- templateFileIncludeTags.put(lowerName, tag);
- } else if (lowerLine.startsWith("define ")) {
- // This should be a constant definition. The rest of the line
- // should
- // contain the constant name, an equal sign, and the constant
- // value.
- int equalPos = line.indexOf('=', 7);
- if (equalPos < 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_DEFINE_MISSING_EQUALS.get(lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- String name = line.substring(7, equalPos).trim();
- if (name.length() == 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_DEFINE_NAME_EMPTY.get(lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = name.toLowerCase();
- if (templateFileConstants.containsKey(lowerName)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_CONSTANT_NAME.get(name, lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- String value = line.substring(equalPos + 1);
- if (value.length() == 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_WARNING_DEFINE_VALUE_EMPTY.get(name, lineNumber);
- warnings.add(message);
- }
-
- templateFileConstants.put(lowerName, value);
- } else if (lowerLine.startsWith("branch: ")) {
- int startLineNumber = lineNumber;
- ArrayList<String> lineList = new ArrayList<String>();
- lineList.add(line);
- while (true) {
- lineNumber++;
- if (lineNumber >= lines.length) {
- break;
- }
-
- line = lines[lineNumber];
- if (line.length() == 0) {
- break;
- } else {
- line = replaceConstants(line, lineNumber, templateFileConstants, warnings);
- lineList.add(line);
- }
- }
-
- String[] branchLines = new String[lineList.size()];
- lineList.toArray(branchLines);
-
- Branch b = parseBranchDefinition(branchLines, lineNumber, templateFileIncludeTags, warnings);
- DN branchDN = b.getBranchDN();
- if (templateFileBranches.containsKey(branchDN)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_BRANCH_DN.get(
- String.valueOf(branchDN), startLineNumber);
- throw DecodeException.fatalError(message);
- } else {
- templateFileBranches.put(branchDN, b);
- }
- } else if (lowerLine.startsWith("template: ")) {
- int startLineNumber = lineNumber;
- ArrayList<String> lineList = new ArrayList<String>();
- lineList.add(line);
- while (true) {
- lineNumber++;
- if (lineNumber >= lines.length) {
- break;
- }
-
- line = lines[lineNumber];
- if (line.length() == 0) {
- break;
- } else {
- line = replaceConstants(line, lineNumber, templateFileConstants, warnings);
- lineList.add(line);
- }
- }
-
- String[] templateLines = new String[lineList.size()];
- lineList.toArray(templateLines);
-
- Template t = parseTemplateDefinition(templateLines, startLineNumber, templateFileIncludeTags,
- templateFileTemplates, warnings);
- String lowerName = t.getName().toLowerCase();
- if (templateFileTemplates.containsKey(lowerName)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_TEMPLATE_NAME.get(
- String.valueOf(t.getName()), startLineNumber);
- throw DecodeException.fatalError(message);
- } else {
- templateFileTemplates.put(lowerName, t);
- }
+ } else if (lowerLine.startsWith(INCLUDE_LABEL)) {
+ parseInclude(line, templateData.tags);
+ } else if (lowerLine.startsWith(DEFINE_LABEL)) {
+ parseDefine(lineNumber, line, constants, warnings);
+ } else if (lowerLine.startsWith(BRANCH_LABEL)) {
+ lineNumber = parseBranch(lineNumber, line, lines, templateData, warnings);
+ } else if (lowerLine.startsWith(TEMPLATE_LABEL)) {
+ lineNumber = parseTemplate(lineNumber, line, lines, templateData, warnings);
} else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_UNEXPECTED_TEMPLATE_FILE_LINE.get(line, lineNumber);
- throw DecodeException.fatalError(message);
+ throw DecodeException.fatalError(
+ ERR_ENTRY_GENERATOR_UNEXPECTED_TEMPLATE_FILE_LINE.get(line, lineNumber));
}
}
- // If we've gotten here, then we're almost done. We just need to
- // finalize
- // the branch and template definitions and then update the template file
- // variables.
- for (Branch b : templateFileBranches.values()) {
- b.completeBranchInitialization(templateFileTemplates);
+ // Finalize the branch and template definitions
+ // and then update the template file variables.
+ for (Branch b : templateData.branches.values()) {
+ b.completeBranchInitialization(templateData.templates);
}
- for (Template t : templateFileTemplates.values()) {
- t.completeTemplateInitialization(templateFileTemplates);
+ for (Template t : templateData.templates.values()) {
+ t.completeTemplateInitialization(templateData.templates);
}
- registeredTags.putAll(templateFileIncludeTags);
- constants.putAll(templateFileConstants);
- branches.putAll(templateFileBranches);
- templates.putAll(templateFileTemplates);
+ registeredTags.putAll(templateData.tags);
+ branches.putAll(templateData.branches);
+ templates.putAll(templateData.templates);
+
+ // Initialize iterator on branches and current branch used
+ // to read entries
+ if (branchesIterator == null) {
+ branchesIterator = branches.values().iterator();
+ if (branchesIterator.hasNext()) {
+ currentBranch = branchesIterator.next();
+ }
+ }
+ }
+
+ private void parseInclude(final String line, final Map<String, TemplateTag> templateFileIncludeTags)
+ throws DecodeException {
+ // The next element should be the name of the class.
+ // Load and instantiate it and make sure there are no conflicts.
+ final String className = line.substring(INCLUDE_LABEL.length()).trim();
+
+ Class<?> tagClass = null;
+ try {
+ tagClass = Class.forName(className);
+ } catch (Exception e) {
+ final LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_LOAD_TAG_CLASS.get(className);
+ throw DecodeException.fatalError(message, e);
+ }
+
+ TemplateTag tag;
+ try {
+ tag = (TemplateTag) tagClass.newInstance();
+ } catch (Exception e) {
+ final LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG.get(className);
+ throw DecodeException.fatalError(message, e);
+ }
+
+ String lowerName = tag.getName().toLowerCase();
+ if (registeredTags.containsKey(lowerName) || templateFileIncludeTags.containsKey(lowerName)) {
+ final LocalizableMessage message = ERR_ENTRY_GENERATOR_CONFLICTING_TAG_NAME.get(className, tag.getName());
+ throw DecodeException.fatalError(message);
+ }
+
+ templateFileIncludeTags.put(lowerName, tag);
+ }
+
+ private void parseDefine(final int lineNumber, final String line, final Map<String, String> templateFileConstants,
+ final List<LocalizableMessage> warnings) throws DecodeException {
+ // The rest of the line should contain the constant name,
+ // an equal sign, and the constant value.
+ final int equalPos = line.indexOf('=', DEFINE_LABEL.length());
+ if (equalPos < 0) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_DEFINE_MISSING_EQUALS.get(lineNumber));
+ }
+
+ final String name = line.substring(DEFINE_LABEL.length(), equalPos).trim();
+ if (name.length() == 0) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_DEFINE_NAME_EMPTY.get(lineNumber));
+ }
+
+ final String value = line.substring(equalPos + 1);
+ if (value.length() == 0) {
+ warnings.add(ERR_ENTRY_GENERATOR_WARNING_DEFINE_VALUE_EMPTY.get(name, lineNumber));
+ }
+
+ final String lowerName = name.toLowerCase();
+ if (!templateFileConstants.containsKey(lowerName)) {
+ templateFileConstants.put(lowerName, value);
+ }
+ }
+
+ /**
+ * Parses the complete branch and returns the current line number at the
+ * end.
+ */
+ private int parseBranch(final int startLineNumber, final String startLine, final String[] lines,
+ final TemplateData templateData, final List<LocalizableMessage> warnings) throws DecodeException {
+ final String[] branchLines =
+ parseLinesUntilEndOfBlock(startLineNumber, startLine, lines, warnings);
+ final Branch branch = parseBranchDefinition(branchLines, startLineNumber, templateData.tags, warnings);
+ final DN branchDN = branch.getBranchDN();
+ if (templateData.branches.containsKey(branchDN)) {
+ throw DecodeException.fatalError(
+ ERR_ENTRY_GENERATOR_CONFLICTING_BRANCH_DN.get(String.valueOf(branchDN), startLineNumber));
+ }
+ templateData.branches.put(branchDN, branch);
+ // position to next line after end of branch
+ return startLineNumber + branchLines.length;
+ }
+
+ /**
+ * Parses the complete template and returns the current line number at the
+ * end.
+ */
+ private int parseTemplate(final int startLineNumber, final String startLine, final String[] lines,
+ final TemplateData templateData, final List<LocalizableMessage> warnings) throws DecodeException {
+ final String[] templateLines =
+ parseLinesUntilEndOfBlock(startLineNumber, startLine, lines, warnings);
+ final Template template =
+ parseTemplateDefinition(startLineNumber, templateLines, templateData, warnings);
+ final String lowerName = template.getName().toLowerCase();
+ if (templateData.templates.containsKey(lowerName)) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_CONFLICTING_TEMPLATE_NAME.get(
+ String.valueOf(template.getName()), startLineNumber));
+ }
+ templateData.templates.put(lowerName, template);
+ // position to next line after end of template
+ return startLineNumber + templateLines.length;
+ }
+
+ /**
+ * Parses lines of a block until the block ends (with an empty line) or
+ * lines ends.
+ *
+ * @param startLineNumber
+ * Line number at beginning of block.
+ * @param startLine
+ * First line of block.
+ * @param lines
+ * The list of all lines in the template.
+ * @param warnings
+ * A list into which any warnings identified may be placed.
+ * @return The lines of the block
+ */
+ private String[] parseLinesUntilEndOfBlock(final int startLineNumber, final String startLine,
+ final String[] lines, final List<LocalizableMessage> warnings) {
+ final List<String> lineList = new ArrayList<String>();
+ String line = startLine;
+ lineList.add(line);
+
+ int lineNumber = startLineNumber;
+ while (true) {
+ lineNumber++;
+ if (lineNumber >= lines.length) {
+ break;
+ }
+ line = lines[lineNumber];
+ if (line.length() == 0) {
+ break;
+ }
+ line = replaceConstants(line, lineNumber, constants, warnings);
+ lineList.add(line);
+ }
+ return lineList.toArray(new String[lineList.size()]);
}
/**
@@ -789,27 +632,26 @@
* @return The line in which all constant variables have been replaced with
* their value
*/
- private String replaceConstants(String line, int lineNumber, Map<String, String> constants,
- List<LocalizableMessage> warnings) {
+ private String replaceConstants(final String line, final int lineNumber, final Map<String, String> constants,
+ final List<LocalizableMessage> warnings) {
+ String newLine = line;
int closePos = line.lastIndexOf(']');
// Loop until we've scanned all closing brackets
do {
// Skip escaped closing brackets
- while (closePos > 0 && line.charAt(closePos - 1) == '\\') {
- closePos = line.lastIndexOf(']', closePos - 1);
+ while (closePos > 0 && newLine.charAt(closePos - 1) == '\\') {
+ closePos = newLine.lastIndexOf(']', closePos - 1);
}
if (closePos > 0) {
- StringBuilder lineBuffer = new StringBuilder(line);
- int openPos = line.lastIndexOf('[', closePos);
- // Find the opening bracket. If it's escaped, then it's not a
- // constant
- if ((openPos > 0 && line.charAt(openPos - 1) != '\\') || (openPos == 0)) {
- String constantName = line.substring(openPos + 1, closePos).toLowerCase();
- String constantValue = constants.get(constantName);
+ final StringBuilder lineBuffer = new StringBuilder(newLine);
+ int openPos = newLine.lastIndexOf('[', closePos);
+ // Find the opening bracket.
+ // If it's escaped, then it's not a constant
+ if ((openPos > 0 && newLine.charAt(openPos - 1) != '\\') || (openPos == 0)) {
+ final String constantName = newLine.substring(openPos + 1, closePos).toLowerCase();
+ final String constantValue = constants.get(constantName);
if (constantValue == null) {
- LocalizableMessage message = WARN_ENTRY_GENERATOR_WARNING_UNDEFINED_CONSTANT.get(constantName,
- lineNumber);
- warnings.add(message);
+ warnings.add(WARN_ENTRY_GENERATOR_WARNING_UNDEFINED_CONSTANT.get(constantName, lineNumber));
} else {
lineBuffer.replace(openPos, closePos + 1, constantValue);
}
@@ -817,16 +659,16 @@
if (openPos >= 0) {
closePos = openPos;
}
- line = lineBuffer.toString();
- closePos = line.lastIndexOf(']', closePos);
+ newLine = lineBuffer.toString();
+ closePos = newLine.lastIndexOf(']', closePos);
}
} while (closePos > 0);
- return line;
+ return newLine;
}
/**
- * Parses the information contained in the provided set of lines as a
- * MakeLDIF branch definition.
+ * Parses the information contained in the provided set of lines as a branch
+ * definition.
*
* @param branchLines
* The set of lines containing the branch definition.
@@ -844,80 +686,52 @@
* If a problem occurs during initializing any of the branch
* elements or during processing.
*/
- private Branch parseBranchDefinition(String[] branchLines, int startLineNumber, Map<String, TemplateTag> tags,
- List<LocalizableMessage> warnings) throws DecodeException {
+ private Branch parseBranchDefinition(final String[] branchLines, final int startLineNumber,
+ final Map<String, TemplateTag> tags, final List<LocalizableMessage> warnings) throws DecodeException {
// The first line must be "branch: " followed by the branch DN.
- String dnString = branchLines[0].substring(8).trim();
+ final String dnString = branchLines[0].substring(BRANCH_LABEL.length()).trim();
DN branchDN;
try {
branchDN = DN.valueOf(dnString, schema);
} catch (Exception e) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_DECODE_BRANCH_DN.get(dnString, startLineNumber);
- throw DecodeException.fatalError(message);
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_CANNOT_DECODE_BRANCH_DN.get(
+ dnString, startLineNumber));
}
- // Create a new branch that will be used for the verification process.
- Branch branch = new Branch(this, branchDN, null);
+ final Branch branch = new Branch(this, branchDN, schema);
for (int i = 1; i < branchLines.length; i++) {
- String line = branchLines[i];
- String lowerLine = line.toLowerCase();
- int lineNumber = startLineNumber + i;
+ final String line = branchLines[i];
+ final String lowerLine = line.toLowerCase();
+ final int lineNumber = startLineNumber + i;
if (lowerLine.startsWith("#")) {
// It's a comment, so we should ignore it.
continue;
- } else if (lowerLine.startsWith("subordinatetemplate: ")) {
- // It's a subordinate template, so we'll want to parse the name
- // and the
- // number of entries.
- int colonPos = line.indexOf(':', 21);
- if (colonPos <= 21) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_TEMPLATE_NO_COLON.get(
- lineNumber, dnString);
- throw DecodeException.fatalError(message);
- }
-
- String templateName = line.substring(21, colonPos).trim();
-
- int numEntries;
- try {
- numEntries = Integer.parseInt(line.substring(colonPos + 1).trim());
- if (numEntries < 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_INVALID_NUM_ENTRIES.get(
- lineNumber, dnString, numEntries, templateName);
- throw DecodeException.fatalError(message);
- } else if (numEntries == 0) {
- LocalizableMessage message = WARN_ENTRY_GENERATOR_BRANCH_SUBORDINATE_ZERO_ENTRIES.get(
- lineNumber, dnString, templateName);
- warnings.add(message);
- }
-
- branch.addSubordinateTemplate(templateName, numEntries);
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_CANT_PARSE_NUMENTRIES.get(
- templateName, lineNumber, dnString);
- throw DecodeException.fatalError(message);
- }
+ } else if (lowerLine.startsWith(SUBORDINATE_TEMPLATE_LABEL)) {
+ final Pair<String, Integer> pair =
+ parseSubordinateTemplate(lineNumber, line, Element.BRANCH, dnString, warnings);
+ final String templateName = pair.getFirst();
+ final int numEntries = pair.getSecond();
+ branch.addSubordinateTemplate(templateName, numEntries);
} else {
- TemplateLine templateLine =
- parseTemplateLine(line, lowerLine, lineNumber, branch, null, tags, warnings);
+ final TemplateLine templateLine =
+ parseTemplateLine(line, lineNumber, branch, null, Element.BRANCH, tags, warnings);
branch.addExtraLine(templateLine);
}
}
-
return branch;
}
/**
* Parses the information contained in the provided set of lines as a
- * MakeLDIF template definition.
+ * template definition.
*
- * @param templateLines
- * The set of lines containing the template definition.
* @param startLineNumber
* The line number in the template file on which the first of the
* template lines appears.
+ * @param templateLines
+ * The set of lines containing the template definition.
* @param tags
* The set of defined tags from the template file. Note that this
* does not include the tags that are always registered by
@@ -931,121 +745,75 @@
* If a problem occurs during initializing any of the template
* elements or during processing.
*/
- private Template parseTemplateDefinition(String[] templateLines, int startLineNumber,
- Map<String, TemplateTag> tags, Map<String, Template> definedTemplates, List<LocalizableMessage> warnings)
- throws DecodeException {
- // The first line must be "template: " followed by the template name.
- String templateName = templateLines[0].substring(10).trim();
+ private Template parseTemplateDefinition(final int startLineNumber, final String[] templateLines,
+ final TemplateData templateData, final List<LocalizableMessage> warnings) throws DecodeException {
+ final Map<String, TemplateTag> tags = templateData.tags;
+ final Map<String, Template> definedTemplates = templateData.templates;
- // The next line may start with either "extends: ", "rdnAttr: ", or
- // "subordinateTemplate: ". Keep reading until we find something that's
- // not one of those.
- int arrayLineNumber = 1;
+ // The first line must be "template: " followed by the template name.
+ final String templateName = templateLines[0].substring(TEMPLATE_LABEL.length()).trim();
+
+ // The next line may be with an "extends", a rdn attribute, or
+ // a subordinate template. Keep reading until we find something
+ // that's not one of those.
+ int lineCount = 1;
Template parentTemplate = null;
- AttributeType[] rdnAttributes = null;
- ArrayList<String> subTemplateNames = new ArrayList<String>();
- ArrayList<Integer> entriesPerTemplate = new ArrayList<Integer>();
- for (; arrayLineNumber < templateLines.length; arrayLineNumber++) {
- int lineNumber = startLineNumber + arrayLineNumber;
- String line = templateLines[arrayLineNumber];
- String lowerLine = line.toLowerCase();
+ final List<AttributeType> rdnAttributes = new ArrayList<AttributeType>();
+ final List<String> subordinatesTemplateNames = new ArrayList<String>();
+ final List<Integer> numberOfentriesPerTemplate = new ArrayList<Integer>();
+
+ for (; lineCount < templateLines.length; lineCount++) {
+ final int lineNumber = startLineNumber + lineCount;
+ final String line = templateLines[lineCount];
+ final String lowerLine = line.toLowerCase();
if (lowerLine.startsWith("#")) {
// It's a comment. Ignore it.
continue;
- } else if (lowerLine.startsWith("extends: ")) {
- String parentTemplateName = line.substring(9).trim();
+ } else if (lowerLine.startsWith(EXTENDS_LABEL)) {
+ final String parentTemplateName = line.substring(EXTENDS_LABEL.length()).trim();
parentTemplate = definedTemplates.get(parentTemplateName.toLowerCase());
if (parentTemplate == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TEMPLATE_INVALID_PARENT_TEMPLATE.get(
- parentTemplateName, lineNumber, templateName);
- throw DecodeException.fatalError(message);
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TEMPLATE_INVALID_PARENT_TEMPLATE.get(
+ parentTemplateName, lineNumber, templateName));
}
- } else if (lowerLine.startsWith("rdnattr: ")) {
+ } else if (lowerLine.startsWith(RDNATTR_LABEL)) {
// This is the set of RDN attributes. If there are multiple,
- // they may
- // be separated by plus signs.
- ArrayList<AttributeType> attrList = new ArrayList<AttributeType>();
- String rdnAttrNames = lowerLine.substring(9).trim();
- StringTokenizer tokenizer = new StringTokenizer(rdnAttrNames, "+");
+ // they may be separated by plus signs.
+ final String rdnAttrNames = lowerLine.substring(RDNATTR_LABEL.length()).trim();
+ final StringTokenizer tokenizer = new StringTokenizer(rdnAttrNames, "+");
while (tokenizer.hasMoreTokens()) {
- attrList.add(schema.getAttributeType(tokenizer.nextToken()));
+ rdnAttributes.add(schema.getAttributeType(tokenizer.nextToken()));
}
-
- rdnAttributes = new AttributeType[attrList.size()];
- attrList.toArray(rdnAttributes);
- } else if (lowerLine.startsWith("subordinatetemplate: ")) {
- // It's a subordinate template, so we'll want to parse the name
- // and the
- // number of entries.
- int colonPos = line.indexOf(':', 21);
- if (colonPos <= 21) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TEMPLATE_SUBORDINATE_TEMPLATE_NO_COLON.get(
- lineNumber, templateName);
- throw DecodeException.fatalError(message);
- }
-
- String subTemplateName = line.substring(21, colonPos).trim();
-
- int numEntries;
- try {
- numEntries = Integer.parseInt(line.substring(colonPos + 1).trim());
- if (numEntries < 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TEMPLATE_SUBORDINATE_INVALID_NUM_ENTRIES.get(
- lineNumber, templateName, numEntries, subTemplateName);
- throw DecodeException.fatalError(message);
- } else if (numEntries == 0) {
- LocalizableMessage message = WARN_ENTRY_GENERATOR_TEMPLATE_SUBORDINATE_ZERO_ENTRIES.get(
- lineNumber, templateName, subTemplateName);
- warnings.add(message);
- }
-
- subTemplateNames.add(subTemplateName);
- entriesPerTemplate.add(numEntries);
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TEMPLATE_SUBORDINATE_CANT_PARSE_NUMENTRIES.get(
- subTemplateName, lineNumber, templateName);
- throw DecodeException.fatalError(message);
- }
+ } else if (lowerLine.startsWith(SUBORDINATE_TEMPLATE_LABEL)) {
+ final Pair<String, Integer> pair =
+ parseSubordinateTemplate(lineNumber, line, Element.BRANCH, templateName, warnings);
+ subordinatesTemplateNames.add(pair.getFirst());
+ numberOfentriesPerTemplate.add(pair.getSecond());
} else {
- // It's something we don't recognize, so it must be a template
- // line.
+ // Not recognized, it must be a template line.
break;
}
}
- // Create a new template that will be used for the verification process.
- String[] subordinateTemplateNames = new String[subTemplateNames.size()];
- subTemplateNames.toArray(subordinateTemplateNames);
+ final List<TemplateLine> parentLines =
+ (parentTemplate == null) ? new ArrayList<TemplateLine>() : parentTemplate.getTemplateLines();
- int[] numEntriesPerTemplate = new int[entriesPerTemplate.size()];
- for (int i = 0; i < numEntriesPerTemplate.length; i++) {
- numEntriesPerTemplate[i] = entriesPerTemplate.get(i);
- }
+ final Template template = new Template(this, templateName, rdnAttributes, subordinatesTemplateNames,
+ numberOfentriesPerTemplate, parentLines);
- TemplateLine[] parsedLines;
- if (parentTemplate == null) {
- parsedLines = new TemplateLine[0];
- } else {
- TemplateLine[] parentLines = parentTemplate.getTemplateLines();
- parsedLines = new TemplateLine[parentLines.length];
- System.arraycopy(parentLines, 0, parsedLines, 0, parentLines.length);
- }
-
- Template template = new Template(this, templateName, rdnAttributes, subordinateTemplateNames,
- numEntriesPerTemplate, parsedLines);
-
- for (; arrayLineNumber < templateLines.length; arrayLineNumber++) {
- String line = templateLines[arrayLineNumber];
- String lowerLine = line.toLowerCase();
- int lineNumber = startLineNumber + arrayLineNumber;
+ // Add lines to template
+ for (; lineCount < templateLines.length; lineCount++) {
+ final String line = templateLines[lineCount];
+ final String lowerLine = line.toLowerCase();
if (lowerLine.startsWith("#")) {
- // It's a comment, so we should ignore it.
+ // It's a comment, ignore it.
continue;
} else {
- TemplateLine templateLine = parseTemplateLine(line, lowerLine, lineNumber, null, template, tags,
- warnings);
+ final int lineNumber = startLineNumber + lineCount;
+ final TemplateLine templateLine =
+ parseTemplateLine(line, lineNumber, null, template, Element.TEMPLATE, tags, warnings);
template.addTemplateLine(templateLine);
}
}
@@ -1053,6 +821,52 @@
return template;
}
+ /**
+ * Parses a subordinate template for a template or a branch.
+ * <p>
+ * A subordinate template has a name and a number of entries.
+ *
+ * @param lineNumber
+ * Line number of definition.
+ * @param line
+ * Line containing the definition.
+ * @param element
+ * indicates the kind of element to use in error messages.
+ * @param elementName
+ * Name of the branch or template.
+ * @param warnings
+ * A list into which any warnings identified may be placed.
+ * @return the pair (template name, number of entries in template)
+ */
+ private Pair<String, Integer> parseSubordinateTemplate(final int lineNumber, final String line,
+ final Element element, final String elementName, final List<LocalizableMessage> warnings)
+ throws DecodeException {
+ // It's a subordinate template, so we'll want to parse
+ // the template name and the number of entries.
+ final int colonPos = line.indexOf(':', SUBORDINATE_TEMPLATE_LABEL.length());
+ if (colonPos <= SUBORDINATE_TEMPLATE_LABEL.length()) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_SUBORDINATE_TEMPLATE_NO_COLON.get(
+ lineNumber, element.getLabel(), elementName));
+ }
+
+ final String templateName = line.substring(SUBORDINATE_TEMPLATE_LABEL.length(), colonPos).trim();
+
+ try {
+ final int numEntries = Integer.parseInt(line.substring(colonPos + 1).trim());
+ if (numEntries < 0) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_SUBORDINATE_INVALID_NUM_ENTRIES.get(
+ lineNumber, element.getLabel(), elementName, numEntries, templateName));
+ } else if (numEntries == 0) {
+ warnings.add(WARN_ENTRY_GENERATOR_SUBORDINATE_ZERO_ENTRIES.get(
+ lineNumber, element.getLabel(), elementName, templateName));
+ }
+ return Pair.of(templateName, numEntries);
+ } catch (NumberFormatException nfe) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_SUBORDINATE_CANT_PARSE_NUMENTRIES.get(
+ templateName, lineNumber, element.getLabel(), elementName));
+ }
+ }
+
private static final int PARSING_STATIC_TEXT = 0;
private static final int PARSING_REPLACEMENT_TAG = 1;
private static final int PARSING_ATTRIBUTE_TAG = 2;
@@ -1064,8 +878,6 @@
*
* @param line
* The text of the template line.
- * @param lowerLine
- * The template line in all lowercase characters.
* @param lineNumber
* The line number on which the template line appears.
* @param branch
@@ -1083,37 +895,26 @@
* If a problem occurs during initializing any of the template
* elements or during processing.
*/
- private TemplateLine parseTemplateLine(String line, String lowerLine, int lineNumber, Branch branch,
- Template template, Map<String, TemplateTag> tags, List<LocalizableMessage> warnings)
- throws DecodeException {
+ private TemplateLine parseTemplateLine(final String line, final int lineNumber, final Branch branch,
+ final Template template, final Element element, final Map<String, TemplateTag> tags,
+ final List<LocalizableMessage> warnings) throws DecodeException {
+ final String elementName = element == Element.BRANCH ? branch.getBranchDN().toString() : template.getName();
+
// The first component must be the attribute type, followed by a colon.
- int colonPos = lowerLine.indexOf(':');
+ final String lowerLine = line.toLowerCase();
+ final int colonPos = lowerLine.indexOf(':');
if (colonPos < 0) {
- if (branch == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_NO_COLON_IN_TEMPLATE_LINE.get(lineNumber,
- template.getName());
- throw DecodeException.fatalError(message);
- } else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_NO_COLON_IN_BRANCH_EXTRA_LINE.get(lineNumber,
- String.valueOf(branch.getBranchDN()));
- throw DecodeException.fatalError(message);
- }
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_NO_COLON_IN_TEMPLATE_LINE.get(
+ lineNumber, element.getLabel(), elementName));
} else if (colonPos == 0) {
- if (branch == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_NO_ATTR_IN_TEMPLATE_LINE.get(lineNumber,
- template.getName());
- throw DecodeException.fatalError(message);
- } else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_NO_ATTR_IN_BRANCH_EXTRA_LINE.get(lineNumber,
- String.valueOf(branch.getBranchDN()));
- throw DecodeException.fatalError(message);
- }
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_NO_ATTR_IN_TEMPLATE_LINE.get(
+ lineNumber, element.getLabel(), elementName));
}
- AttributeType attributeType = schema.getAttributeType(lowerLine.substring(0, colonPos));
+ final AttributeType attributeType = schema.getAttributeType(lowerLine.substring(0, colonPos));
// First, check whether the value is an URL value: <attrName>:< <url>
- int length = line.length();
+ final int length = line.length();
int pos = colonPos + 1;
boolean valueIsURL = false;
boolean valueIsBase64 = false;
@@ -1132,24 +933,16 @@
}
if (pos >= length) {
- // We've hit the end of the line with no value. We'll allow it, but
- // add a
- // warning.
- if (branch == null) {
- LocalizableMessage message = WARN_ENTRY_GENERATOR_NO_VALUE_IN_TEMPLATE_LINE.get(lineNumber,
- template.getName());
- warnings.add(message);
- } else {
- LocalizableMessage message = WARN_ENTRY_GENERATOR_NO_VALUE_IN_BRANCH_EXTRA_LINE.get(lineNumber,
- String.valueOf(branch.getBranchDN()));
- warnings.add(message);
- }
+ // We've hit the end of the line with no value.
+ // We'll allow it, but add a warning.
+ warnings.add(WARN_ENTRY_GENERATOR_NO_VALUE_IN_TEMPLATE_LINE.get(
+ lineNumber, element.getLabel(), elementName));
}
int phase = PARSING_STATIC_TEXT;
int previousPhase = PARSING_STATIC_TEXT;
- ArrayList<TemplateTag> tagList = new ArrayList<TemplateTag>();
+ final List<TemplateTag> tagList = new ArrayList<TemplateTag>();
StringBuilder buffer = new StringBuilder();
for (; pos < length; pos++) {
@@ -1199,7 +992,6 @@
parseReplacementTag(buffer.toString(), branch, template, lineNumber, tags, warnings);
tagList.add(t);
buffer = new StringBuilder();
-
phase = PARSING_STATIC_TEXT;
break;
default:
@@ -1242,13 +1034,10 @@
tagList.add(t);
}
} else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_INCOMPLETE_TAG.get(lineNumber);
- throw DecodeException.fatalError(message);
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_INCOMPLETE_TAG.get(lineNumber));
}
- TemplateTag[] tagArray = new TemplateTag[tagList.size()];
- tagList.toArray(tagArray);
- return new TemplateLine(attributeType, lineNumber, tagArray, valueIsURL, valueIsBase64);
+ return new TemplateLine(attributeType, lineNumber, tagList, valueIsURL, valueIsBase64);
}
/**
@@ -1274,53 +1063,45 @@
* @throws DecodeException
* If some problem occurs during processing.
*/
- private TemplateTag parseReplacementTag(String tagString, Branch branch, Template template, int lineNumber,
- Map<String, TemplateTag> tags, List<LocalizableMessage> warnings) throws DecodeException {
+ private TemplateTag parseReplacementTag(final String tagString, final Branch branch, final Template template,
+ final int lineNumber, final Map<String, TemplateTag> tags, final List<LocalizableMessage> warnings)
+ throws DecodeException {
// The components of the replacement tag will be separated by colons,
- // with
- // the first being the tag name and the remainder being arguments.
- StringTokenizer tokenizer = new StringTokenizer(tagString, ":");
- String tagName = tokenizer.nextToken().trim();
- String lowerTagName = tagName.toLowerCase();
+ // with the first being the tag name and the remainder being arguments.
+ final StringTokenizer tokenizer = new StringTokenizer(tagString, ":");
+ final String tagName = tokenizer.nextToken().trim();
+ final String lowerTagName = tagName.toLowerCase();
- TemplateTag t = getTag(lowerTagName);
- if (t == null) {
- t = tags.get(lowerTagName);
- if (t == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_NO_SUCH_TAG.get(tagName, lineNumber);
- throw DecodeException.fatalError(message);
+ TemplateTag tag = getTag(lowerTagName);
+ if (tag == null) {
+ tag = tags.get(lowerTagName);
+ if (tag == null) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_NO_SUCH_TAG.get(tagName, lineNumber));
}
}
- ArrayList<String> argList = new ArrayList<String>();
+ final List<String> args = new ArrayList<String>();
while (tokenizer.hasMoreTokens()) {
- argList.add(tokenizer.nextToken().trim());
+ args.add(tokenizer.nextToken().trim());
}
-
- String[] args = new String[argList.size()];
- argList.toArray(args);
+ final String[] arguments = args.toArray(new String[args.size()]);
TemplateTag newTag;
try {
- newTag = t.getClass().newInstance();
+ newTag = tag.getClass().newInstance();
} catch (Exception e) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_NEW_TAG.get(tagName, lineNumber,
- String.valueOf(e));
- throw DecodeException.fatalError(message, e);
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_NEW_TAG.get(
+ tagName, lineNumber, String.valueOf(e)), e);
}
if (branch == null) {
- newTag.initializeForTemplate(schema, this, template, args, lineNumber, warnings);
+ newTag.initializeForTemplate(schema, this, template, arguments, lineNumber, warnings);
+ } else if (newTag.allowedInBranch()) {
+ newTag.initializeForBranch(schema, this, branch, arguments, lineNumber, warnings);
} else {
- if (newTag.allowedInBranch()) {
- newTag.initializeForBranch(schema, this, branch, args, lineNumber, warnings);
- } else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_NOT_ALLOWED_IN_BRANCH.get(newTag.getName(),
- lineNumber);
- throw DecodeException.fatalError(message);
- }
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_NOT_ALLOWED_IN_BRANCH.get(newTag.getName(),
+ lineNumber));
}
-
return newTag;
}
@@ -1343,197 +1124,234 @@
* @throws DecodeException
* If some other problem occurs during processing.
*/
- private TemplateTag parseAttributeTag(String tagString, Branch branch, Template template, int lineNumber,
- List<LocalizableMessage> warnings) throws DecodeException {
+ private TemplateTag parseAttributeTag(final String tagString, final Branch branch,
+ final Template template, final int lineNumber, final List<LocalizableMessage> warnings)
+ throws DecodeException {
// The attribute tag must have at least one argument, which is the name
- // of
- // the attribute to reference. It may have a second argument, which is
- // the
- // number of characters to use from the attribute value. The arguments
- // will
- // be delimited by colons.
- StringTokenizer tokenizer = new StringTokenizer(tagString, ":");
- ArrayList<String> argList = new ArrayList<String>();
+ // of the attribute to reference. It may have a second argument, which
+ // is the number of characters to use from the attribute value. The
+ // arguments will be delimited by colons.
+ final StringTokenizer tokenizer = new StringTokenizer(tagString, ":");
+ final List<String> args = new ArrayList<String>();
while (tokenizer.hasMoreTokens()) {
- argList.add(tokenizer.nextToken());
+ args.add(tokenizer.nextToken());
}
+ final String[] arguments = args.toArray(new String[args.size()]);
- String[] args = new String[argList.size()];
- argList.toArray(args);
-
- AttributeValueTag tag = new AttributeValueTag();
+ final AttributeValueTag tag = new AttributeValueTag();
if (branch == null) {
- tag.initializeForTemplate(schema, this, template, args, lineNumber, warnings);
+ tag.initializeForTemplate(schema, this, template, arguments, lineNumber, warnings);
} else {
- tag.initializeForBranch(schema, this, branch, args, lineNumber, warnings);
+ tag.initializeForBranch(schema, this, branch, arguments, lineNumber, warnings);
}
-
return tag;
}
/**
- * Retrieves a File object based on the provided path. If the given path is
- * absolute, then that absolute path will be used. If it is relative, then
- * it will first be evaluated relative to the current working directory. If
- * that path doesn't exist, then it will be evaluated relative to the
- * resource path. If that path doesn't exist, then it will be evaluated
- * relative to the directory containing the template file.
+ * Retrieves a file based on the provided path.
+ * <p>
+ * To allow retrieval of a file located in a jar, you must use
+ * {@code getReader()} method instead of this one.
+ * <p>
+ * File is searched successively in two locations :
+ * <ul>
+ * <li>Using the provided path as is.</li>
+ * <li>Using resource path + provided path.</li>
+ * </ul>
*
- * @param path
- * The path provided for the file.
- * @return The File object for the specified path, or <CODE>null</CODE> if
- * the specified file could not be found.
+ * @param filePath
+ * The path provided for the file, which can be absolute or
+ * relative.
+ * @return the file, or <code>null</code> if it could not be found.
*/
- public File getFile(String path) {
- // First, see if the file exists using the given path. This will work if
- // the file is absolute, or it's relative to the current working
- // directory.
- File f = new File(path);
- if (f.exists()) {
- return f;
+ private File getFile(final String filePath) {
+ File file = new File(filePath);
+ // try raw path first
+ if (file.exists()) {
+ return file;
}
-
- // If the provided path was absolute, then use it anyway, even though we
- // couldn't find the file.
- if (f.isAbsolute()) {
- return f;
- }
-
- // Try a path relative to the resource directory.
- String newPath = resourcePath + File.separator + path;
- f = new File(newPath);
- if (f.exists()) {
- return f;
- }
-
- // Try a path relative to the template directory, if it's available.
- if (templatePath != null) {
- newPath = templatePath = File.separator + path;
- f = new File(newPath);
- if (f.exists()) {
- return f;
+ // try using resource path
+ if (resourcePath != null) {
+ file = new File(resourcePath + File.separator + filePath);
+ if (file.exists()) {
+ return file;
}
}
-
return null;
}
/**
- * Retrieves the lines of the specified file as a string array. If the
- * result is already cached, then it will be used. If the result is not
- * cached, then the file data will be cached so that the contents can be
- * re-used if there are multiple references to the same file.
+ * Retrieves a reader based on the provided path.
+ * <p>
+ * The path represent a file path either on the file system or in a jar.
+ * File is searched successively in three locations :
+ * <ul>
+ * <li>Using the provided path on the file system.</li>
+ * <li>Using resource path + provided path on the file system.</li>
+ * <li>Using default resources path + provided path on the file system or in
+ * a jar.</li>
+ * </ul>
*
- * @param file
- * The file for which to retrieve the contents.
- * @return An array containing the lines of the specified file.
+ * @param filePath
+ * The path provided for the file, which can be absolute or
+ * relative.
+ * @return A reader on the file, or <code>null</code> if it could not be
+ * found. It is the responsability of caller to close the returned
+ * reader.
+ */
+ @SuppressWarnings("resource")
+ BufferedReader getReader(final String filePath) {
+ BufferedReader reader = null;
+ File file = new File(filePath);
+ try {
+ if (file.exists()) {
+ // try raw path first
+ reader = new BufferedReader(new FileReader(file));
+ } else if (resourcePath != null) {
+ // try using resource path
+ file = new File(resourcePath + File.separator + filePath);
+ if (file.exists()) {
+ reader = new BufferedReader(new FileReader(file));
+ }
+ }
+ if (reader == null) {
+ // try to find in default resources provided
+ final InputStream stream = TemplateFile.class.getClassLoader().getResourceAsStream(
+ new File(DEFAULT_RESOURCES_PATH, filePath).getPath());
+ if (stream != null) {
+ reader = new BufferedReader(new InputStreamReader(stream));
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Should never happen as we test file existence first.
+ // In any case, nothing to do as we want to return null
+ }
+ return reader;
+ }
+
+ /**
+ * Retrieves the lines of the provided reader, possibly reading them from
+ * memory cache.
+ * <p>
+ * Lines are retrieved from reader at the first call, then cached in memory
+ * for next calls, using the provided identifier.
+ * <p>
+ * Use {@code readFile()} method to avoid caching.
+ *
+ * @param label
+ * Label used as identifier to cache the line read.
+ * @param reader
+ * Reader to parse for lines.
+ * @return a list of lines
* @throws IOException
* If a problem occurs while reading the file.
*/
- public String[] getFileLines(File file) throws IOException {
- String absolutePath = file.getAbsolutePath();
- String[] lines = fileLines.get(absolutePath);
+ String[] getLines(String identifier, final BufferedReader reader) throws IOException {
+ String[] lines = fileLines.get(identifier);
if (lines == null) {
- ArrayList<String> lineList = new ArrayList<String>();
-
- BufferedReader reader = new BufferedReader(new FileReader(file));
- while (true) {
- String line = reader.readLine();
- if (line == null) {
- break;
- } else {
- lineList.add(line);
- }
- }
-
- reader.close();
-
- lines = new String[lineList.size()];
- lineList.toArray(lines);
- lineList.clear();
- fileLines.put(absolutePath, lines);
+ lines = readLines(reader).toArray(new String[] {});
+ fileLines.put(identifier, lines);
}
-
return lines;
}
/**
- * Generates the entries and writes them to the provided entry writer.
+ * Retrieves the lines from the provided reader.
*
- * @param entryWriter
- * The entry writer that should be used to write the entries.
- * @return The result that indicates whether processing should continue.
+ * @param reader
+ * The reader containing the lines.
+ * @return a list of lines
* @throws IOException
- * If an error occurs while writing the entry.
- * @throws DecodeException
- * If some other problem occurs.
+ * If a problem occurs while reading the lines.
*/
- public TagResult generateEntries(EntryWriter entryWriter) throws IOException, DecodeException {
- for (Branch b : branches.values()) {
- TagResult result = b.writeEntries(entryWriter);
- if (!(result.keepProcessingTemplateFile())) {
- return result;
+ private List<String> readLines(final BufferedReader reader) throws IOException {
+ final List<String> lines = new ArrayList<String>();
+ while (true) {
+ final String line = reader.readLine();
+ if (line == null) {
+ break;
}
+ lines.add(line);
}
+ return lines;
+ }
- entryWriter.closeEntryWriter();
- return TagResult.SUCCESS_RESULT;
+ /** Iterator on branches that are used to read entries. */
+ private Iterator<Branch> branchesIterator;
+
+ /** Branch from which entries are currently read. */
+ private Branch currentBranch;
+
+ /** Entry to return when calling {@code nextEntry} method. */
+ private TemplateEntry nextEntry;
+
+ /**
+ * Returns {@code true} if there is another generated entry
+ * to return.
+ *
+ * @return {@code true} if another entry can be returned.
+ */
+ boolean hasNext() {
+ if (nextEntry != null) {
+ return true;
+ }
+ while (currentBranch != null) {
+ if (currentBranch.hasNext()) {
+ nextEntry = currentBranch.nextEntry();
+ return true;
+ }
+ currentBranch = branchesIterator.hasNext() ? branchesIterator.next() : null;
+ }
+ return false;
}
/**
- * Writer of generated entries.
+ * Returns the next generated entry.
+ *
+ * @return The next entry.
+ * @throws NoSuchElementException
+ * If this reader does not contain any more entries.
*/
- public interface EntryWriter {
- /**
- * Writes the provided entry to the appropriate target.
- *
- * @param entry
- * The entry to be written.
- * @return <CODE>true</CODE> if the entry writer will accept additional
- * entries, or <CODE>false</CODE> if no more entries should be
- * written.
- * @throws IOException
- * If a problem occurs while writing the entry to its
- * intended destination.
- * @throws DecodeException
- * If some other problem occurs.
- */
- public boolean writeEntry(TemplateEntry entry) throws IOException, DecodeException;
-
- /**
- * Notifies the entry writer that no more entries will be provided and
- * that any associated cleanup may be performed.
- */
- public void closeEntryWriter();
+ Entry nextEntry() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ final Entry entry = nextEntry.toEntry();
+ nextEntry = null;
+ return entry;
}
/**
* Represents a branch that should be included in the generated results. A
* branch may or may not have subordinate entries.
*/
- static class Branch {
+ static final class Branch {
/** The DN for this branch entry. */
- private DN branchDN;
+ private final DN branchDN;
/**
* The number of entries that should be created below this branch for
* each subordinate template.
*/
- private int[] numEntriesPerTemplate;
+ private final List<Integer> numEntriesPerTemplate;
/** The names of the subordinate templates for this branch. */
- private String[] subordinateTemplateNames;
+ private final List<String> subordinateTemplateNames;
/** The set of subordinate templates for this branch. */
- private Template[] subordinateTemplates;
+ private List<Template> subordinateTemplates;
/** The set of template lines that correspond to the RDN components. */
- private TemplateLine[] rdnLines;
+ private final List<TemplateLine> rdnLines;
/** The set of extra lines that should be included in this branch entry. */
- private TemplateLine[] extraLines;
+ private final List<TemplateLine> extraLines;
- private Schema schema;
+ /** Entry to return when calling {@code nextEntry} method. */
+ private TemplateEntry nextEntry;
+
+ /** Index of subordinate template currently read. */
+ private int currentSubTemplateIndex;
/**
* Creates a new branch with the provided information.
@@ -1544,9 +1362,12 @@
* The DN for this branch entry.
* @param schema
* schema used to create attribute
+ * @throws DecodeException
+ * if a problem occurs during initialization
*/
- public Branch(TemplateFile templateFile, DN branchDN, Schema schema) {
- this(templateFile, branchDN, schema, new String[0], new int[0], new TemplateLine[0]);
+ Branch(final TemplateFile templateFile, final DN branchDN, final Schema schema) throws DecodeException {
+ this(templateFile, branchDN, schema, new ArrayList<String>(), new ArrayList<Integer>(),
+ new ArrayList<TemplateLine>());
}
/**
@@ -1567,56 +1388,37 @@
* @param extraLines
* The set of extra lines that should be included in this
* branch entry.
+ * @throws DecodeException
+ * if a problem occurs during initialization
*/
- public Branch(TemplateFile templateFile, DN branchDN, Schema schema, String[] subordinateTemplateNames,
- int[] numEntriesPerTemplate, TemplateLine[] extraLines) {
+ Branch(final TemplateFile templateFile, final DN branchDN, final Schema schema,
+ final List<String> subordinateTemplateNames, final List<Integer> numEntriesPerTemplate,
+ final List<TemplateLine> extraLines) throws DecodeException {
this.branchDN = branchDN;
- this.schema = schema;
this.subordinateTemplateNames = subordinateTemplateNames;
this.numEntriesPerTemplate = numEntriesPerTemplate;
this.extraLines = extraLines;
- subordinateTemplates = null;
-
- // Get the RDN template lines based just on the entry DN.
- Entry entry = LinkedHashMapEntry.FACTORY.newEntry(branchDN);
-
- ArrayList<LocalizableMessage> warnings = new ArrayList<LocalizableMessage>();
- ArrayList<TemplateLine> lineList = new ArrayList<TemplateLine>();
-
- for (ObjectClass objectClass : Entries.getObjectClasses(entry, schema)) {
- try {
- String[] valueStrings = new String[] { objectClass.getNameOrOID() };
- TemplateTag[] tags = new TemplateTag[1];
- tags[0] = new StaticTextTag();
- tags[0].initializeForBranch(schema, templateFile, this, valueStrings, 0, warnings);
-
- TemplateLine l = new TemplateLine(CoreSchema.getObjectClassAttributeType(), 0, tags);
- lineList.add(l);
- } catch (Exception e) {
- // This should never happen.
- e.printStackTrace();
+ // The RDN template lines are based on the DN.
+ final List<LocalizableMessage> warnings = new ArrayList<LocalizableMessage>();
+ rdnLines = new ArrayList<TemplateLine>();
+ for (final AVA ava : branchDN.rdn()) {
+ final Attribute attribute = ava.toAttribute();
+ for (final ByteString value : attribute.toArray()) {
+ final List<TemplateTag> tags =
+ buildTagListForValue(value.toString(), templateFile, schema, warnings);
+ rdnLines.add(new TemplateLine(attribute.getAttributeDescription().getAttributeType(), 0, tags));
}
}
+ }
- for (Attribute attribute : entry.getAllAttributes()) {
- for (String value : attribute.toArray(new String[attribute.size()])) {
- try {
- String[] valueStrings = new String[] { value };
- TemplateTag[] tags = new TemplateTag[1];
- tags[0] = new StaticTextTag();
- tags[0].initializeForBranch(schema, templateFile, this, valueStrings, 0, warnings);
- lineList.add(
- new TemplateLine(attribute.getAttributeDescription().getAttributeType(), 0, tags));
- } catch (Exception e) {
- // This should never happen.
- e.printStackTrace();
- }
- }
- }
-
- rdnLines = new TemplateLine[lineList.size()];
- lineList.toArray(rdnLines);
+ private List<TemplateTag> buildTagListForValue(final String value, final TemplateFile templateFile,
+ final Schema schema, final List<LocalizableMessage> warnings) throws DecodeException {
+ final StaticTextTag tag = new StaticTextTag();
+ tag.initializeForBranch(schema, templateFile, this, new String[] { value }, 0, warnings);
+ final List<TemplateTag> tags = new ArrayList<TemplateTag>();
+ tags.add(tag);
+ return tags;
}
/**
@@ -1631,66 +1433,24 @@
* If any of the subordinate templates are not defined in
* the template file.
*/
- public void completeBranchInitialization(Map<String, Template> templates) throws DecodeException {
- if (subordinateTemplateNames == null) {
- subordinateTemplateNames = new String[0];
- subordinateTemplates = new Template[0];
- } else {
- subordinateTemplates = new Template[subordinateTemplateNames.length];
- for (int i = 0; i < subordinateTemplates.length; i++) {
- subordinateTemplates[i] = templates.get(subordinateTemplateNames[i].toLowerCase());
- if (subordinateTemplates[i] == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_UNDEFINED_BRANCH_SUBORDINATE.get(
- branchDN.toString(), subordinateTemplateNames[i]);
- throw DecodeException.fatalError(message);
- }
+ private void completeBranchInitialization(final Map<String, Template> templates) throws DecodeException {
+ subordinateTemplates = new ArrayList<Template>();
+ for (int i = 0; i < subordinateTemplateNames.size(); i++) {
+ subordinateTemplates.add(templates.get(subordinateTemplateNames.get(i).toLowerCase()));
+ if (subordinateTemplates.get(i) == null) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_UNDEFINED_BRANCH_SUBORDINATE.get(
+ branchDN.toString(), subordinateTemplateNames.get(i)));
}
}
+
+ nextEntry = buildBranchEntry();
}
- /**
- * Retrieves the DN for this branch entry.
- *
- * @return The DN for this branch entry.
- */
- public DN getBranchDN() {
+ DN getBranchDN() {
return branchDN;
}
/**
- * Retrieves the names of the subordinate templates for this branch.
- *
- * @return The names of the subordinate templates for this branch.
- */
- public String[] getSubordinateTemplateNames() {
- return subordinateTemplateNames;
- }
-
- /**
- * Retrieves the set of subordinate templates used to generate entries
- * below this branch. Note that the subordinate templates will not be
- * available until the <CODE>completeBranchInitialization</CODE> method
- * has been called.
- *
- * @return The set of subordinate templates used to generate entries
- * below this branch.
- */
- public Template[] getSubordinateTemplates() {
- return subordinateTemplates;
- }
-
- /**
- * Retrieves the number of entries that should be created below this
- * branch for each subordinate template.
- *
- * @return The number of entries that should be created below this
- * branch for each subordinate template.
- */
- public int[] getNumEntriesPerTemplate() {
- return numEntriesPerTemplate;
- }
-
- /**
* Adds a new subordinate template to this branch. Note that this should
* not be used after <CODE>completeBranchInitialization</CODE> has been
* called.
@@ -1700,29 +1460,9 @@
* @param numEntries
* The number of entries to create based on the template.
*/
- public void addSubordinateTemplate(String name, int numEntries) {
- String[] newNames = new String[subordinateTemplateNames.length + 1];
- int[] newCounts = new int[numEntriesPerTemplate.length + 1];
-
- System.arraycopy(subordinateTemplateNames, 0, newNames, 0, subordinateTemplateNames.length);
- System.arraycopy(numEntriesPerTemplate, 0, newCounts, 0, numEntriesPerTemplate.length);
-
- newNames[subordinateTemplateNames.length] = name;
- newCounts[numEntriesPerTemplate.length] = numEntries;
-
- subordinateTemplateNames = newNames;
- numEntriesPerTemplate = newCounts;
- }
-
- /**
- * Retrieves the set of extra lines that should be included in this
- * branch entry.
- *
- * @return The set of extra lines that should be included in this branch
- * entry.
- */
- public TemplateLine[] getExtraLines() {
- return extraLines;
+ void addSubordinateTemplate(final String name, final int numEntries) {
+ subordinateTemplateNames.add(name);
+ numEntriesPerTemplate.add(numEntries);
}
/**
@@ -1732,12 +1472,8 @@
* @param line
* The line to add to the set of extra lines for this branch.
*/
- public void addExtraLine(TemplateLine line) {
- TemplateLine[] newExtraLines = new TemplateLine[extraLines.length + 1];
- System.arraycopy(extraLines, 0, newExtraLines, 0, extraLines.length);
- newExtraLines[extraLines.length] = line;
-
- extraLines = newExtraLines;
+ void addExtraLine(final TemplateLine line) {
+ extraLines.add(line);
}
/**
@@ -1747,73 +1483,76 @@
*
* @param attributeType
* The attribute type for which to make the determination.
- * @return <CODE>true</CODE> if the branch does contain the specified
- * attribute type, or <CODE>false</CODE> if it does not.
+ * @return <code>true</code> if the branch does contain the specified
+ * attribute type, or <code>false</code> if it does not.
*/
- public boolean hasAttribute(AttributeType attributeType) {
+ boolean hasAttribute(final AttributeType attributeType) {
if (branchDN.rdn().getAttributeValue(attributeType) != null) {
return true;
}
-
- for (TemplateLine l : extraLines) {
- if (l.getAttributeType().equals(attributeType)) {
+ for (final TemplateLine line : extraLines) {
+ if (line.getAttributeType().equals(attributeType)) {
return true;
}
}
-
return false;
}
/**
- * Writes the entry for this branch, as well as all appropriate
- * subordinate entries.
+ * Returns the entry corresponding to this branch.
*
- * @param entryWriter
- * The entry writer to which the entries should be written.
- * @return The result that indicates whether processing should continue.
- * @throws IOException
- * If a problem occurs while attempting to write to the LDIF
- * writer.
- * @throws DecodeException
- * If some other problem occurs.
+ * @return the entry, or null if it can't be generated
*/
- public TagResult writeEntries(EntryWriter entryWriter) throws IOException, DecodeException {
- // Create a new template entry and populate it based on the RDN
- // attributes and extra lines.
- TemplateEntry entry = new TemplateEntry(this);
-
- for (TemplateLine l : rdnLines) {
- TagResult r = l.generateLine(entry);
- if (!(r.keepProcessingEntry() && r.keepProcessingParent() && r.keepProcessingTemplateFile())) {
- return r;
- }
+ private TemplateEntry buildBranchEntry() {
+ final TemplateEntry entry = new TemplateEntry(this);
+ final List<TemplateLine> lines = new ArrayList<TemplateLine>(rdnLines);
+ lines.addAll(extraLines);
+ for (final TemplateLine line : lines) {
+ line.generateLine(entry);
}
-
- for (TemplateLine l : extraLines) {
- TagResult r = l.generateLine(entry);
- if (!(r.keepProcessingEntry() && r.keepProcessingParent() && r.keepProcessingTemplateFile())) {
- return r;
- }
+ for (int i = 0; i < subordinateTemplates.size(); i++) {
+ subordinateTemplates.get(i).reset(entry.getDN(), numEntriesPerTemplate.get(i));
}
+ return entry;
+ }
- if (!entryWriter.writeEntry(entry)) {
- return TagResult.STOP_PROCESSING;
+ /**
+ * Returns {@code true} if there is another generated entry to return.
+ *
+ * @return {@code true} if another entry can be returned.
+ */
+ boolean hasNext() {
+ if (nextEntry != null) {
+ return true;
}
-
- for (int i = 0; i < subordinateTemplates.length; i++) {
- TagResult r = subordinateTemplates[i].writeEntries(entryWriter, branchDN, numEntriesPerTemplate[i]);
- if (!(r.keepProcessingParent() && r.keepProcessingTemplateFile())) {
- if (r.keepProcessingTemplateFile()) {
- // We don't want to propagate a "stop processing parent"
- // all the way up the chain.
- return TagResult.SUCCESS_RESULT;
+ // get the next entry from current subtemplate
+ if (nextEntry == null) {
+ for (; currentSubTemplateIndex < subordinateTemplates.size(); currentSubTemplateIndex++) {
+ if (subordinateTemplates.get(currentSubTemplateIndex).hasNext()) {
+ nextEntry = subordinateTemplates.get(currentSubTemplateIndex).nextEntry();
+ if (nextEntry != null) {
+ return true;
+ }
}
-
- return r;
}
}
+ return false;
+ }
- return TagResult.SUCCESS_RESULT;
+ /**
+ * Returns the next generated entry.
+ *
+ * @return The next entry.
+ * @throws NoSuchElementException
+ * If this reader does not contain any more entries.
+ */
+ TemplateEntry nextEntry() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ final TemplateEntry entry = nextEntry;
+ nextEntry = null;
+ return entry;
}
}
@@ -1827,54 +1566,25 @@
* The attribute types that are used in the RDN for entries generated
* using this template.
*/
- private org.forgerock.opendj.ldap.schema.AttributeType[] rdnAttributes;
+ private final List<AttributeType> rdnAttributes;
/** The number of entries to create for each subordinate template. */
- private int[] numEntriesPerTemplate;
+ private final List<Integer> numEntriesPerTemplate;
/** The name for this template. */
- private String name;
+ private final String name;
/** The names of the subordinate templates below this template. */
- private String[] subordinateTemplateNames;
+ private final List<String> subTemplateNames;
/** The subordinate templates below this template. */
- private Template[] subordinateTemplates;
+ private List<Template> subTemplates;
/** The template file that contains this template. */
- private TemplateFile templateFile;
+ private final TemplateFile templateFile;
/** The set of template lines for this template. */
- private TemplateLine[] templateLines;
-
- /**
- * Creates a new template with the provided information.
- *
- * @param templateFile
- * The template file that contains this template.
- * @param name
- * The name for this template.
- * @param rdnAttributes
- * The set of attribute types that are used in the RDN for
- * entries generated using this template.
- * @param subordinateTemplateNames
- * The names of the subordinate templates below this
- * template.
- * @param numEntriesPerTemplate
- * The number of entries to create below each subordinate
- * template.
- */
- public Template(TemplateFile templateFile, String name, AttributeType[] rdnAttributes,
- String[] subordinateTemplateNames, int[] numEntriesPerTemplate) {
- this.templateFile = templateFile;
- this.name = name;
- this.rdnAttributes = rdnAttributes;
- this.subordinateTemplateNames = subordinateTemplateNames;
- this.numEntriesPerTemplate = numEntriesPerTemplate;
-
- templateLines = new TemplateLine[0];
- subordinateTemplates = null;
- }
+ private final List<TemplateLine> templateLines;
/**
* Creates a new template with the provided information.
@@ -1895,16 +1605,15 @@
* @param templateLines
* The set of template lines for this template.
*/
- public Template(TemplateFile templateFile, String name, AttributeType[] rdnAttributes,
- String[] subordinateTemplateNames, int[] numEntriesPerTemplate, TemplateLine[] templateLines) {
+ Template(final TemplateFile templateFile, final String name, final List<AttributeType> rdnAttributes,
+ final List<String> subordinateTemplateNames, final List<Integer> numEntriesPerTemplate,
+ final List<TemplateLine> templateLines) {
this.templateFile = templateFile;
this.name = name;
this.rdnAttributes = rdnAttributes;
- this.subordinateTemplateNames = subordinateTemplateNames;
+ this.subTemplateNames = subordinateTemplateNames;
this.numEntriesPerTemplate = numEntriesPerTemplate;
this.templateLines = templateLines;
-
- subordinateTemplates = null;
}
/**
@@ -1920,117 +1629,47 @@
* If any of the subordinate templates are not defined in
* the template file.
*/
- public void completeTemplateInitialization(Map<String, Template> templates) throws DecodeException {
- // Make sure that all of the specified subordinate templates exist.
- if (subordinateTemplateNames == null) {
- subordinateTemplateNames = new String[0];
- subordinateTemplates = new Template[0];
- } else {
- subordinateTemplates = new Template[subordinateTemplateNames.length];
- for (int i = 0; i < subordinateTemplates.length; i++) {
- subordinateTemplates[i] = templates.get(subordinateTemplateNames[i].toLowerCase());
- if (subordinateTemplates[i] == null) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_UNDEFINED_TEMPLATE_SUBORDINATE.get(
- subordinateTemplateNames[i], name);
- throw DecodeException.fatalError(message);
- }
+ void completeTemplateInitialization(final Map<String, Template> templates) throws DecodeException {
+ subTemplates = new ArrayList<Template>();
+ for (final String subordinateName : subTemplateNames) {
+ final Template template = templates.get(subordinateName.toLowerCase());
+ if (template == null) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_UNDEFINED_TEMPLATE_SUBORDINATE.get(
+ this.name, subordinateName));
}
+ subTemplates.add(template);
}
+ ensureAllRDNAttributesAreDefined();
+ }
- // Make sure that all of the RDN attributes are defined.
- HashSet<AttributeType> rdnAttrs = new HashSet<AttributeType>(rdnAttributes.length);
- for (AttributeType t : rdnAttributes) {
- rdnAttrs.add(t);
+ private void ensureAllRDNAttributesAreDefined() throws DecodeException {
+ Set<AttributeType> rdnAttrs = new HashSet<AttributeType>(rdnAttributes);
+ List<AttributeType> templateAttrs = new ArrayList<AttributeType>();
+ for (TemplateLine line : templateLines) {
+ templateAttrs.add(line.getAttributeType());
}
-
- for (TemplateLine l : templateLines) {
- if (rdnAttrs.remove(l.getAttributeType())) {
- if (rdnAttrs.isEmpty()) {
- break;
- }
- }
- }
-
+ rdnAttrs.removeAll(templateAttrs);
if (!rdnAttrs.isEmpty()) {
AttributeType t = rdnAttrs.iterator().next();
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TEMPLATE_MISSING_RDN_ATTR.get(name, t.getNameOrOID());
- throw DecodeException.fatalError(message);
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TEMPLATE_MISSING_RDN_ATTR.get(
+ name, t.getNameOrOID()));
}
}
- /**
- * Retrieves the name for this template.
- *
- * @return The name for this template.
- */
- public String getName() {
+ String getName() {
return name;
}
- /**
- * Retrieves the set of attribute types that are used in the RDN for
- * entries generated using this template.
- *
- * @return The set of attribute types that are used in the RDN for
- * entries generated using this template.
- */
- public AttributeType[] getRDNAttributes() {
+ List<AttributeType> getRDNAttributes() {
return rdnAttributes;
}
- /**
- * Retrieves the names of the subordinate templates used to generate
- * entries below entries created by this template.
- *
- * @return The names of the subordinate templates used to generate
- * entries below entries created by this template.
- */
- public String[] getSubordinateTemplateNames() {
- return subordinateTemplateNames;
- }
-
- /**
- * Retrieves the subordinate templates used to generate entries below
- * entries created by this template.
- *
- * @return The subordinate templates used to generate entries below
- * entries created by this template.
- */
- public Template[] getSubordinateTemplates() {
- return subordinateTemplates;
- }
-
- /**
- * Retrieves the number of entries that should be created for each
- * subordinate template.
- *
- * @return The number of entries that should be created for each
- * subordinate template.
- */
- public int[] getNumEntriesPerTemplate() {
- return numEntriesPerTemplate;
- }
-
- /**
- * Retrieves the set of template lines for this template.
- *
- * @return The set of template lines for this template.
- */
- public TemplateLine[] getTemplateLines() {
+ List<TemplateLine> getTemplateLines() {
return templateLines;
}
- /**
- * Adds the provided template line to this template.
- *
- * @param line
- * The template line to add to this template.
- */
- public void addTemplateLine(TemplateLine line) {
- TemplateLine[] newTemplateLines = new TemplateLine[templateLines.length + 1];
- System.arraycopy(templateLines, 0, newTemplateLines, 0, templateLines.length);
- newTemplateLines[templateLines.length] = line;
- templateLines = newTemplateLines;
+ void addTemplateLine(final TemplateLine line) {
+ templateLines.add(line);
}
/**
@@ -2043,68 +1682,124 @@
* template lines that reference the provided attribute type, or
* <CODE>false</CODE> if not.
*/
- public boolean hasAttribute(AttributeType attributeType) {
- for (TemplateLine l : templateLines) {
- if (l.getAttributeType().equals(attributeType)) {
+ boolean hasAttribute(final AttributeType attributeType) {
+ for (final TemplateLine line : templateLines) {
+ if (line.getAttributeType().equals(attributeType)) {
return true;
}
}
+ return false;
+ }
+ /** parent DN of entries to generate for this template. */
+ private DN parentDN;
+
+ /** Number of entries to generate for this template. */
+ private int numberOfEntries;
+
+ /** Current count of generated entries for this template. */
+ private int entriesCount;
+
+ /** Indicates if current entry has been initialized. */
+ private boolean currentEntryIsInitialized;
+
+ /** Index of current subordinate template to use for current entry. */
+ private int subTemplateIndex;
+
+ /** Entry to return when calling {@code nextEntry} method. */
+ private TemplateEntry nextEntry;
+
+ /**
+ * Reset this template with provided parentDN and number of entries to
+ * generate.
+ * <p>
+ * After a reset, the template can be used again to generate some
+ * entries with a different parent DN and number of entries.
+ *
+ * @param parentDN
+ * The parent DN of entires to generate for this template.
+ * @param numberOfEntries
+ * The number of entries to generate for this template.
+ */
+ void reset(final DN parentDN, final int numberOfEntries) {
+ this.parentDN = parentDN;
+ this.numberOfEntries = numberOfEntries;
+ entriesCount = 0;
+ currentEntryIsInitialized = false;
+ subTemplateIndex = 0;
+ nextEntry = null;
+ }
+
+ /**
+ * Returns an entry for this template.
+ *
+ * @return the entry, or null if it can't be generated
+ */
+ private TemplateEntry buildTemplateEntry() {
+ templateFile.nextFirstAndLastNames();
+ final TemplateEntry templateEntry = new TemplateEntry(this, parentDN);
+
+ for (final TemplateLine line : templateLines) {
+ line.generateLine(templateEntry);
+ }
+ for (int i = 0; i < subTemplates.size(); i++) {
+ subTemplates.get(i).reset(templateEntry.getDN(), numEntriesPerTemplate.get(i));
+ }
+ return templateEntry;
+ }
+
+ /**
+ * Returns {@code true} if there is another generated entry to return.
+ *
+ * @return {@code true} if another entry can be returned.
+ */
+ boolean hasNext() {
+ if (nextEntry != null) {
+ return true;
+ }
+ while (entriesCount < numberOfEntries) {
+ // get the template entry
+ if (!currentEntryIsInitialized) {
+ nextEntry = buildTemplateEntry();
+ if (nextEntry != null) {
+ currentEntryIsInitialized = true;
+ return true;
+ }
+ return false;
+ }
+ // get the next entry from current subtemplate
+ if (nextEntry == null) {
+ for (; subTemplateIndex < subTemplates.size(); subTemplateIndex++) {
+ if (subTemplates.get(subTemplateIndex).hasNext()) {
+ nextEntry = subTemplates.get(subTemplateIndex).nextEntry();
+ if (nextEntry != null) {
+ return true;
+ }
+ }
+ }
+ }
+ // reset for next template entry
+ entriesCount++;
+ currentEntryIsInitialized = false;
+ subTemplateIndex = 0;
+ }
return false;
}
/**
- * Writes the entry for this template, as well as all appropriate
- * subordinate entries.
+ * Returns the next generated entry.
*
- * @param entryWriter
- * The entry writer that will be used to write the entries.
- * @param parentDN
- * The DN of the entry below which the subordinate entries
- * should be generated.
- * @param count
- * The number of entries to generate based on this template.
- * @return The result that indicates whether processing should continue.
- * @throws IOException
- * If a problem occurs while attempting to write to the LDIF
- * writer.
- * @throws DecodeException
- * If some other problem occurs.
+ * @return The next entry.
+ * @throws NoSuchElementException
+ * If this reader does not contain any more entries.
*/
- public TagResult writeEntries(EntryWriter entryWriter, DN parentDN, int count) throws IOException,
- DecodeException {
- for (int i = 0; i < count; i++) {
- templateFile.nextFirstAndLastNames();
- TemplateEntry templateEntry = new TemplateEntry(this, parentDN);
-
- for (TemplateLine l : templateLines) {
- TagResult r = l.generateLine(templateEntry);
- if (!(r.keepProcessingEntry() && r.keepProcessingParent() && r.keepProcessingTemplateFile())) {
- return r;
- }
- }
-
- if (!entryWriter.writeEntry(templateEntry)) {
- return TagResult.STOP_PROCESSING;
- }
-
- for (int j = 0; j < subordinateTemplates.length; j++) {
- TagResult r = subordinateTemplates[j].writeEntries(entryWriter, templateEntry.getDN(),
- numEntriesPerTemplate[j]);
- if (!(r.keepProcessingParent() && r.keepProcessingTemplateFile())) {
- if (r.keepProcessingTemplateFile()) {
- // We don't want to propagate a
- // "stop processing parent"
- // all the way up the chain.
- return TagResult.SUCCESS_RESULT;
- }
-
- return r;
- }
- }
+ TemplateEntry nextEntry() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
}
-
- return TagResult.SUCCESS_RESULT;
+ final TemplateEntry entry = nextEntry;
+ nextEntry = null;
+ return entry;
}
}
@@ -2116,12 +1811,6 @@
/** Template entry that represents a null object. */
static final TemplateEntry NULL_TEMPLATE_ENTRY = new TemplateEntry(null, null);
- /**
- * The branch used to generate this entry (if it is associated with a
- * branch).
- */
- private Branch branch;
-
/** The DN for this template entry, if it is known. */
private DN dn;
@@ -2129,20 +1818,22 @@
* The DN of the parent entry for this template entry, if it is
* available.
*/
- private DN parentDN;
+ private final DN parentDN;
/**
* The set of attributes associated with this template entry, mapped
* from the lowercase name of the attribute to the list of generated
* values.
+ * A list of template values is never empty in the map, it always has
+ * at least one element.
*/
- private LinkedHashMap<AttributeType, ArrayList<TemplateValue>> attributes;
+ private final LinkedHashMap<AttributeType, List<TemplateValue>> attributes;
/**
- * The template used to generate this entry (if it is associated with a
- * template).
+ * The template used to generate this entry if it is associated with a
+ * template.
*/
- private Template template;
+ private final Template template;
/**
* Creates a new template entry that will be associated with the
@@ -2151,13 +1842,11 @@
* @param branch
* The branch to use when creating this template entry.
*/
- public TemplateEntry(Branch branch) {
- this.branch = branch;
-
+ TemplateEntry(final Branch branch) {
dn = branch.getBranchDN();
+ attributes = new LinkedHashMap<AttributeType, List<TemplateValue>>();
template = null;
parentDN = null;
- attributes = new LinkedHashMap<AttributeType, ArrayList<TemplateValue>>();
}
/**
@@ -2169,43 +1858,13 @@
* @param parentDN
* The DN of the parent entry for this template entry.
*/
- public TemplateEntry(Template template, DN parentDN) {
+ TemplateEntry(final Template template, final DN parentDN) {
this.template = template;
this.parentDN = parentDN;
-
- dn = null;
- branch = null;
- attributes = new LinkedHashMap<AttributeType, ArrayList<TemplateValue>>();
+ attributes = new LinkedHashMap<AttributeType, List<TemplateValue>>();
}
- /**
- * Retrieves the branch used to generate this entry.
- *
- * @return The branch used to generate this entry, or <CODE>null</CODE>
- * if it is associated with a template instead of a branch.
- */
- public Branch getBranch() {
- return branch;
- }
-
- /**
- * Retrieves the template used to generate this entry.
- *
- * @return The template used to generate this entry, or
- * <CODE>null</CODE> if it is associated with a branch instead
- * of a template.
- */
- public Template getTemplate() {
- return template;
- }
-
- /**
- * Retrieves the DN of the parent entry for this template entry.
- *
- * @return The DN of the parent entry for this template entry, or
- * <CODE>null</CODE> if there is no parent DN.
- */
- public DN getParentDN() {
+ DN getParentDN() {
return parentDN;
}
@@ -2215,55 +1874,22 @@
* @return The DN for this template entry if it is known, or
* <CODE>null</CODE> if it cannot yet be determined.
*/
- public DN getDN() {
- // TODO : building to review, particularly building RN with multiple
- // AVA
- // using StringBuilder because no facility using other way
+ DN getDN() {
if (dn == null) {
- RDN rdn;
- AttributeType[] rdnAttrs = template.getRDNAttributes();
- if (rdnAttrs.length == 1) {
- AttributeType type = rdnAttrs[0];
- TemplateValue templateValue = getValue(type);
+ final Collection<AVA> avas = new ArrayList<AVA>();
+ for (final AttributeType attrType : template.getRDNAttributes()) {
+ final TemplateValue templateValue = getValue(attrType);
if (templateValue == null) {
return null;
}
- rdn = new RDN(type, templateValue.getValueAsString());
- } else {
- StringBuilder rdnString = new StringBuilder();
- for (int i = 0; i < rdnAttrs.length; i++) {
- AttributeType type = rdnAttrs[i];
- TemplateValue templateValue = getValue(type);
- if (templateValue == null) {
- return null;
- }
- if (i > 0) {
- rdnString.append("+");
- }
- rdnString.append(new AVA(type, templateValue.getValueAsString()).toString());
- }
- rdn = RDN.valueOf(rdnString.toString());
+ avas.add(new AVA(attrType, templateValue.getValueAsString()));
}
- dn = parentDN.child(rdn);
+ dn = parentDN.child(new RDN(avas));
}
return dn;
}
/**
- * Indicates whether this entry contains one or more values for the
- * specified attribute type.
- *
- * @param attributeType
- * The attribute type for which to make the determination.
- * @return <CODE>true</CODE> if this entry contains one or more values
- * for the specified attribute type, or <CODE>false</CODE> if
- * not.
- */
- public boolean hasAttribute(AttributeType attributeType) {
- return attributes.containsKey(attributeType);
- }
-
- /**
* Retrieves the value for the specified attribute, if defined. If the
* specified attribute has multiple values, then the first will be
* returned.
@@ -2273,13 +1899,12 @@
* @return The value for the specified attribute, or <CODE>null</CODE>
* if there are no values for that attribute type.
*/
- public TemplateValue getValue(AttributeType attributeType) {
- ArrayList<TemplateValue> valueList = attributes.get(attributeType);
- if ((valueList == null) || valueList.isEmpty()) {
- return null;
- } else {
- return valueList.get(0);
+ TemplateValue getValue(final AttributeType attributeType) {
+ final List<TemplateValue> values = attributes.get(attributeType);
+ if ((values != null)) {
+ return values.get(0);
}
+ return null;
}
/**
@@ -2292,41 +1917,32 @@
* <CODE>null</CODE> if there are no values for that attribute
* type.
*/
- public List<TemplateValue> getValues(AttributeType attributeType) {
- ArrayList<TemplateValue> valueList = attributes.get(attributeType);
- return valueList;
+ List<TemplateValue> getValues(AttributeType attributeType) {
+ return attributes.get(attributeType);
}
- /**
- * Adds the provided template value to this entry.
- *
- * @param value
- * The value to add to this entry.
- */
- public void addValue(TemplateValue value) {
- ArrayList<TemplateValue> valueList = attributes.get(value.getAttributeType());
- if (valueList == null) {
- valueList = new ArrayList<TemplateValue>();
- valueList.add(value);
- attributes.put(value.getAttributeType(), valueList);
- } else {
- valueList.add(value);
+ void addValue(TemplateValue value) {
+ List<TemplateValue> values = attributes.get(value.getAttributeType());
+ if (values == null) {
+ values = new ArrayList<TemplateValue>();
+ attributes.put(value.getAttributeType(), values);
}
+ values.add(value);
}
/**
- * Returns an entry from this template entry.
+ * Returns an entry built from this template entry.
*
* @return an entry
*/
- public Entry toEntry() {
- Entry entry = LinkedHashMapEntry.FACTORY.newEntry(getDN());
- AttributeFactory attributeFactory = LinkedAttribute.FACTORY;
+ Entry toEntry() {
+ final Entry entry = new LinkedHashMapEntry(getDN());
- for (AttributeType attributeType : attributes.keySet()) {
- ArrayList<TemplateValue> valueList = attributes.get(attributeType);
- Attribute newAttribute = attributeFactory.newAttribute(AttributeDescription.create(attributeType));
- for (TemplateValue value : valueList) {
+ for (final AttributeType attributeType : attributes.keySet()) {
+ final List<TemplateValue> valueList = attributes.get(attributeType);
+ final Attribute newAttribute =
+ new LinkedAttribute(AttributeDescription.create(attributeType));
+ for (final TemplateValue value : valueList) {
newAttribute.add(value.getValueAsString());
}
entry.addAttribute(newAttribute);
@@ -2340,69 +1956,27 @@
* any number of tags to be evaluated.
*/
static class TemplateLine {
- /** The attribute type for this template line. */
- private AttributeType attributeType;
+
+ /** The attribute type to which this template line corresponds. */
+ private final AttributeType attributeType;
/**
* The line number on which this template line appears in the template
* file.
*/
- private int lineNumber;
+ private final int lineNumber;
/** The set of tags for this template line. */
- private TemplateTag[] tags;
+ private final List<TemplateTag> tags;
/** Whether this line corresponds to an URL value or not. */
- private boolean isURL;
+ private final boolean isURL;
/** Whether this line corresponds to a base64 encoded value or not. */
- private boolean isBase64;
+ private final boolean isBase64;
/**
- * Retrieves the attribute type for this template line.
- *
- * @return The attribute type for this template line.
- */
- public AttributeType getAttributeType() {
- return attributeType;
- }
-
- /**
- * Retrieves the line number on which this template line appears in the
- * template file.
- *
- * @return The line number on which this template line appears in the
- * template file.
- */
- public int getLineNumber() {
- return lineNumber;
- }
-
- /**
- * Returns whether the value of this template line corresponds to an URL
- * or not.
- *
- * @return <CODE>true</CODE> if the value of this template line
- * corresponds to an URL and <CODE>false</CODE> otherwise.
- */
- public boolean isURL() {
- return isURL;
- }
-
- /**
- * Returns whether the value of this template line corresponds to a
- * Base64 encoded value or not.
- *
- * @return <CODE>true</CODE> if the value of this template line
- * corresponds to a Base64 encoded value and <CODE>false</CODE>
- * otherwise.
- */
- public boolean isBase64() {
- return isBase64;
- }
-
- /**
- * Creates a new template line with the provided information.
+ * Creates a new template line.
*
* @param attributeType
* The attribute type for this template line.
@@ -2412,12 +1986,12 @@
* @param tags
* The set of tags for this template line.
*/
- public TemplateLine(AttributeType attributeType, int lineNumber, TemplateTag[] tags) {
+ TemplateLine(final AttributeType attributeType, final int lineNumber, final List<TemplateTag> tags) {
this(attributeType, lineNumber, tags, false, false);
}
/**
- * Creates a new template line with the provided information.
+ * Creates a new template line with URL and base64 flags.
*
* @param attributeType
* The attribute type for this template line.
@@ -2432,8 +2006,8 @@
* Whether this template line's value is Base64 encoded or
* not.
*/
- public TemplateLine(AttributeType attributeType, int lineNumber, TemplateTag[] tags, boolean isURL,
- boolean isBase64) {
+ TemplateLine(final AttributeType attributeType, final int lineNumber, final List<TemplateTag> tags,
+ final boolean isURL, final boolean isBase64) {
this.attributeType = attributeType;
this.lineNumber = lineNumber;
this.tags = tags;
@@ -2441,6 +2015,10 @@
this.isBase64 = isBase64;
}
+ AttributeType getAttributeType() {
+ return attributeType;
+ }
+
/**
* Generates the content for this template line and places it in the
* provided template entry.
@@ -2449,19 +2027,16 @@
* The template entry being generated.
* @return The result of generating the template line.
*/
- public TagResult generateLine(TemplateEntry templateEntry) {
- TemplateValue value = new TemplateValue(this);
-
- for (TemplateTag t : tags) {
- TagResult result = t.generateValue(templateEntry, value);
- if (!(result.keepProcessingLine() && result.keepProcessingEntry()
- && result.keepProcessingParent() && result.keepProcessingTemplateFile())) {
+ TagResult generateLine(final TemplateEntry templateEntry) {
+ final TemplateValue value = new TemplateValue(this);
+ for (final TemplateTag tag : tags) {
+ final TagResult result = tag.generateValue(templateEntry, value);
+ if (result != TagResult.SUCCESS) {
return result;
}
}
-
templateEntry.addValue(value);
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
@@ -2469,77 +2044,37 @@
* Represents a value generated from a template line.
*/
static class TemplateValue {
+
/** The generated template value. */
- private StringBuilder templateValue;
+ private final StringBuilder templateValue;
/** The template line used to generate this value. */
- private TemplateLine templateLine;
+ private final TemplateLine templateLine;
- /**
- * Creates a new template value with the provided information.
- *
- * @param templateLine
- * The template line used to generate this value.
- */
- public TemplateValue(TemplateLine templateLine) {
+ TemplateValue(final TemplateLine templateLine) {
this.templateLine = templateLine;
templateValue = new StringBuilder();
}
- /**
- * Retrieves the template line used to generate this value.
- *
- * @return The template line used to generate this value.
- */
- public TemplateLine getTemplateLine() {
- return templateLine;
- }
-
- /**
- * Retrieves the attribute type for this template value.
- *
- * @return The attribute type for this template value.
- */
- public AttributeType getAttributeType() {
+ AttributeType getAttributeType() {
return templateLine.getAttributeType();
}
- /**
- * Retrieves the generated value.
- *
- * @return The generated value.
- */
- public StringBuilder getValue() {
- return templateValue;
- }
-
- /**
- * Retrieves the generated value as String.
- *
- * @return The generated value.
- */
- public String getValueAsString() {
+ /** Returns the generated value as String. */
+ String getValueAsString() {
return templateValue.toString();
}
- /**
- * Appends the provided string to this template value.
- *
- * @param s
- * The string to append.
- */
- public void append(String s) {
+ /** Appends the provided string to this template value. */
+ void append(final String s) {
templateValue.append(s);
}
/**
* Appends the string representation of the provided object to this
* template value.
- *
- * @param o
- * The object to append.
*/
- public void append(Object o) {
+ void append(final Object o) {
templateValue.append(String.valueOf(o));
}
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java
index f91f423..636ed92 100644
--- a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java
@@ -28,7 +28,7 @@
import static com.forgerock.opendj.ldap.CoreMessages.*;
-import java.io.File;
+import java.io.BufferedReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;
@@ -45,6 +45,8 @@
import org.forgerock.opendj.ldif.TemplateFile.TemplateEntry;
import org.forgerock.opendj.ldif.TemplateFile.TemplateValue;
+import com.forgerock.opendj.util.StaticUtils;
+
/**
* Represents a tag that may be used in a template line when generating entries.
* It can be used to generate content.
@@ -56,26 +58,21 @@
/**
* Retrieves the name for this tag.
- *
- * @return The name for this tag.
*/
- public abstract String getName();
+ abstract String getName();
/**
* Indicates whether this tag is allowed for use in the extra lines for
* branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch definitions,
- * or <CODE>false</CODE> if not.
*/
- public abstract boolean allowedInBranch();
+ abstract boolean allowedInBranch();
/**
* Performs any initialization for this tag that may be needed while parsing
* a branch definition.
*
* @param schema
- * schema used to create attributes
+ * The schema used to create attributes.
* @param templateFile
* The template file in which this tag is used.
* @param branch
@@ -88,10 +85,8 @@
* @param warnings
* A list into which any appropriate warning messages may be
* placed.
- * @throws DecodeException
- * if a problem occurs
*/
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
// No implementation required by default.
}
@@ -101,12 +96,12 @@
* a template definition.
*
* @param schema
- * schema used to create attributes
+ * The schema used to create attributes.
* @param templateFile
* The template file in which this tag is used.
* @param template
* The template in which this tag is used.
- * @param arguments
+ * @param tagArguments
* The set of arguments provided for this tag.
* @param lineNumber
* The line number on which this tag appears in the template
@@ -114,11 +109,9 @@
* @param warnings
* A list into which any appropriate warning messages may be
* placed.
- * @throws DecodeException
- * if a problem occurs
*/
- public abstract void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException;
+ abstract void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ String[] tagArguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException;
/**
* Performs any initialization for this tag that may be needed when starting
@@ -127,11 +120,29 @@
* @param parentEntry
* The entry below which the new entries will be generated.
*/
- public void initializeForParent(TemplateEntry parentEntry) {
+ void initializeForParent(TemplateEntry parentEntry) {
// No implementation required by default.
}
/**
+ * Check for an attribute type in a branch or in a template.
+ *
+ * @param attrType
+ * The attribute type to check for.
+ * @param branch
+ * The branch that contains the type, or {@code null}
+ * @param template
+ * The template that contains the type, or {@code null}
+ * @return true if either the branch or the template has the provided
+ * attribute
+ */
+ final boolean hasAttributeTypeInBranchOrTemplate(AttributeType attrType, Branch branch,
+ Template template) {
+ return (branch != null && branch.hasAttribute(attrType))
+ || (template != null && template.hasAttribute(attrType));
+ }
+
+ /**
* Generates the content for this tag by appending it to the provided tag.
*
* @param templateEntry
@@ -141,242 +152,64 @@
* appended.
* @return The result of generating content for this tag.
*/
- public abstract TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue);
+ abstract TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue);
/**
- * Provides information about the result of tag processing.
+ * Represents the result of tag generation.
*/
- static final class TagResult {
- /**
- * A tag result in which all components have a value of
- * <CODE>true</CODE>.
- */
- public static final TagResult SUCCESS_RESULT = new TagResult(true, true, true, true);
-
- /**
- * A tag result that indicates the value should not be included in the
- * entry, but all other processing should continue.
- */
- public static final TagResult OMIT_FROM_ENTRY = new TagResult(false, true, true, true);
-
- /**
- * A tag result in whihc all components have a value of
- * <CODE>false</CODE>.
- */
- public static final TagResult STOP_PROCESSING = new TagResult(false, false, false, false);
-
- /** Indicates whether to keep processing the associated line. */
- private boolean keepProcessingLine;
-
- /** Indicates whether to keep processing the associated entry. */
- private boolean keepProcessingEntry;
-
- /**
- * Indicates whether to keep processing entries below the associated
- * parent.
- */
- private boolean keepProcessingParent;
-
- /** Indicates whether to keep processing entries for the template file. */
- private boolean keepProcessingTemplateFile;
-
- /**
- * Creates a new tag result object with the provided information.
- *
- * @param keepProcessingLine
- * Indicates whether to continue processing for the current
- * line. If not, then the line will not be included in the
- * entry.
- * @param keepProcessingEntry
- * Indicates whether to continue processing for the current
- * entry. If not, then the entry will not be included in the
- * data.
- * @param keepProcessingParent
- * Indicates whether to continue processing entries below the
- * current parent in the template file.
- * @param keepProcessingTemplateFile
- * Indicates whether to continue processing entries for the
- * template file.
- */
- private TagResult(boolean keepProcessingLine, boolean keepProcessingEntry, boolean keepProcessingParent,
- boolean keepProcessingTemplateFile) {
- this.keepProcessingLine = keepProcessingLine;
- this.keepProcessingEntry = keepProcessingEntry;
- this.keepProcessingParent = keepProcessingParent;
- this.keepProcessingTemplateFile = keepProcessingTemplateFile;
- }
-
- /**
- * Indicates whether to continue processing for the current line. If
- * this is <CODE>false</CODE>, then the current line will not be
- * included in the entry. It will have no impact on whehter the entry
- * itself is included in the generated LDIF.
- *
- * @return <CODE>true</CODE> if the line should be included in the
- * entry, or <CODE>false</CODE> if not.
- */
- public boolean keepProcessingLine() {
- return keepProcessingLine;
- }
-
- /**
- * Indicates whether to continue processing for the current entry. If
- * this is <CODE>false</CODE>, then the current entry will not be
- * included in the generated LDIF, and processing will resume with the
- * next entry below the current parent.
- *
- * @return <CODE>true</CODE> if the entry should be included in the
- * generated LDIF, or <CODE>false</CODE> if not.
- */
- public boolean keepProcessingEntry() {
- return keepProcessingEntry;
- }
-
- /**
- * Indicates whether to continue processing entries below the current
- * parent. If this is <CODE>false</CODE>, then the current entry will
- * not be included, and processing will resume below the next parent in
- * the template file.
- *
- * @return <CODE>true</CODE> if processing for the current parent should
- * continue, or <CODE>false</CODE> if not.
- */
- public boolean keepProcessingParent() {
- return keepProcessingParent;
- }
-
- /**
- * Indicates whether to keep processing entries for the template file.
- * If this is <CODE>false</CODE>, then LDIF processing will end
- * immediately (and the current entry will not be included).
- *
- * @return <CODE>true</CODE> if processing for the template file should
- * continue, or <CODE>false</CODE> if not.
- */
- public boolean keepProcessingTemplateFile() {
- return keepProcessingTemplateFile;
- }
+ static enum TagResult {
+ SUCCESS, FAILURE
}
/**
- * This class defines a tag that is used to reference the value of a
- * specified attribute already defined in the entry.
+ * Tag used to reference the value of a specified attribute
+ * already defined in the entry.
*/
static class AttributeValueTag extends TemplateTag {
+
/** The attribute type that specifies which value should be used. */
private AttributeType attributeType;
/** The maximum number of characters to include from the value. */
private int numCharacters;
- /**
- * Creates a new instance of this attribute value tag.
- */
- public AttributeValueTag() {
+ AttributeValueTag() {
attributeType = null;
numCharacters = 0;
}
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "AttributeValue";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if ((arguments.length < 1) || (arguments.length > 2)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 1, 2, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = arguments[0].toLowerCase();
- attributeType = schema.getAttributeType(lowerName);
- if (!branch.hasAttribute(attributeType)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments.length == 2) {
- try {
- numCharacters = Integer.parseInt(arguments[1]);
- if (numCharacters < 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INTEGER_BELOW_LOWER_BOUND.get(
- numCharacters, 0, getName(), lineNumber);
- throw DecodeException.fatalError(message);
- }
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_INTEGER.get(arguments[1],
- getName(), lineNumber);
- throw DecodeException.fatalError(message);
- }
- } else {
- numCharacters = 0;
- }
+ initialize(schema, branch, null, arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template, String[] arguments,
+ int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(schema, null, template, arguments, lineNumber);
+ }
+
+ private void initialize(Schema schema, Branch branch, Template template, String[] arguments, int lineNumber)
+ throws DecodeException {
if ((arguments.length < 1) || (arguments.length > 2)) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
lineNumber, 1, 2, arguments.length);
throw DecodeException.fatalError(message);
}
- String lowerName = arguments[0].toLowerCase();
- attributeType = schema.getAttributeType(lowerName);
- if (!template.hasAttribute(attributeType)) {
+ attributeType = schema.getAttributeType(arguments[0].toLowerCase());
+ if (!hasAttributeTypeInBranchOrTemplate(attributeType, branch, template)) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
throw DecodeException.fatalError(message);
}
@@ -399,135 +232,60 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
- TemplateValue v = templateEntry.getValue(attributeType);
- if (v == null) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TemplateValue value = templateEntry.getValue(attributeType);
+ if (value == null) {
// This is fine -- we just won't append anything.
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
if (numCharacters > 0) {
- String valueString = v.getValueAsString();
+ String valueString = value.getValueAsString();
if (valueString.length() > numCharacters) {
templateValue.append(valueString.substring(0, numCharacters));
} else {
templateValue.append(valueString);
}
} else {
- templateValue.append(v.getValue());
+ templateValue.append(value.getValueAsString());
}
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include the DN of the current
- * entry in the attribute value.
+ * Tag used to include the DN of the current entry in the attribute value.
*/
static class DNTag extends TemplateTag {
+
/** The number of DN components to include. */
private int numComponents;
- /**
- * Creates a new instance of this DN tag.
- */
- public DNTag() {
- numComponents = 0;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "DN";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ final boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ final void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ final void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed for this
- * tag.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber)
+ private void initialize(String[] arguments, int lineNumber)
throws DecodeException {
if (arguments.length == 0) {
numComponents = 0;
@@ -546,61 +304,52 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ return generateValue(templateEntry, templateValue, ",");
+ }
+
+ final TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue,
+ String separator) {
DN dn = templateEntry.getDN();
if ((dn == null) || dn.isRootDN()) {
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
+ String dnAsString = "";
if (numComponents == 0) {
- templateValue.append(dn.toNormalizedString());
+ // Return the DN of the entry
+ dnAsString = dn.toString();
} else if (numComponents > 0) {
- int count = Math.min(numComponents, dn.size());
- templateValue.append(dn.rdn());
- for (int i = 1; i < count; i++) {
- templateValue.append(",");
- templateValue.append(dn.parent(i).rdn());
- }
+ // Return the first numComponents RDNs of the DN
+ dnAsString = dn.localName(numComponents).toString();
} else {
- int size = dn.size();
- int count = Math.min(Math.abs(numComponents), size);
-
- templateValue.append(dn.parent(size - count).rdn());
- for (int i = 1; i < count; i++) {
- templateValue.append(",");
- templateValue.append(dn.parent(size - count + i).rdn());
- }
+ // numComponents is negative
+ // Return the last numComponents RDNs of the DN
+ dnAsString = dn.parent(dn.size() - Math.abs(numComponents)).toString();
}
+ // If expected separator is not standard separator
+ // Then substitute expected to standard
+ if (!separator.equals(",")) {
+ dnAsString = dnAsString.replaceAll(",", separator);
+ }
+ templateValue.append(dnAsString);
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used provide values from a text file.
- * The file should have one value per line. Access to the values may be
- * either at random or in sequential order.
+ * Tag used to provide values from a text file. The file should have one
+ * value per line. Access to the values may be either at random or in
+ * sequential order.
*/
static class FileTag extends TemplateTag {
/**
* Indicates whether the values should be selected sequentially or at
* random.
*/
- private boolean sequential;
-
- /** The file containing the data. */
- private File dataFile;
+ private boolean isSequential = false;
/** The index used for sequential access. */
private int nextIndex;
@@ -608,104 +357,33 @@
/** The random number generator for this tag. */
private Random random;
- /** The array of lines read from the file. */
+ /** The lines read from the file. */
private String[] fileLines;
- /**
- * Creates a new instance of this file tag.
- */
- public FileTag() {
- sequential = false;
- dataFile = null;
- nextIndex = 0;
- random = null;
- fileLines = null;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "File";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber,
- List<LocalizableMessage> warnings) throws DecodeException {
+ private void initialize(TemplateFile templateFile, String[] arguments, int lineNumber)
+ throws DecodeException {
random = templateFile.getRandom();
// There must be at least one argument, and possibly two.
@@ -716,11 +394,27 @@
}
// The first argument should be the path to the file.
- dataFile = templateFile.getFile(arguments[0]);
- if ((dataFile == null) || (!dataFile.exists())) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_FIND_FILE.get(arguments[0], getName(),
- lineNumber);
- throw DecodeException.fatalError(message);
+ final String filePath = arguments[0];
+ BufferedReader dataReader = null;
+ try {
+ dataReader = templateFile.getReader(filePath);
+ if (dataReader == null) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_FIND_FILE.get(filePath, getName(),
+ lineNumber);
+ throw DecodeException.fatalError(message);
+ }
+
+ // See if the file has already been read into memory. If not, then
+ // read it.
+ try {
+ fileLines = templateFile.getLines(filePath, dataReader);
+ } catch (IOException ioe) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_READ_FILE.get(filePath, getName(),
+ lineNumber, String.valueOf(ioe));
+ throw DecodeException.fatalError(message, ioe);
+ }
+ } finally {
+ StaticUtils.closeSilently(dataReader);
}
// If there is a second argument, then it should be either
@@ -728,43 +422,23 @@
// assume "random".
if (arguments.length == 2) {
if (arguments[1].equalsIgnoreCase("sequential")) {
- sequential = true;
+ isSequential = true;
nextIndex = 0;
} else if (arguments[1].equalsIgnoreCase("random")) {
- sequential = false;
+ isSequential = false;
} else {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_FILE_ACCESS_MODE.get(arguments[1],
getName(), lineNumber);
throw DecodeException.fatalError(message);
}
} else {
- sequential = false;
- }
-
- // See if the file has already been read into memory. If not, then
- // read it.
- try {
- fileLines = templateFile.getFileLines(dataFile);
- } catch (IOException ioe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_READ_FILE.get(arguments[0], getName(),
- lineNumber, String.valueOf(ioe));
- throw DecodeException.fatalError(message, ioe);
+ isSequential = false;
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
- if (sequential) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ if (isSequential) {
templateValue.append(fileLines[nextIndex++]);
if (nextIndex >= fileLines.length) {
nextIndex = 0;
@@ -773,170 +447,55 @@
templateValue.append(fileLines[random.nextInt(fileLines.length)]);
}
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include a first name in the
- * attribute value.
+ * Tag used to include a first name in the attribute value.
*/
- static class FirstNameTag extends TemplateTag {
- /** The template file with which this tag is associated. */
- private TemplateFile templateFile;
-
- /**
- * Creates a new instance of this first name tag.
- */
- public FirstNameTag() {
- // No implementation required.
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ static class FirstNameTag extends NameTag {
+ @Override
+ String getName() {
return "First";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return false;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- this.templateFile = templateFile;
-
- if (arguments.length != 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 0, arguments.length);
- throw DecodeException.fatalError(message);
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
templateValue.append(templateFile.getFirstName());
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include a GUID in the attribute
- * value.
+ * Tag used to include a GUID in the attribute value.
*/
static class GUIDTag extends TemplateTag {
- /**
- * Creates a new instance of this GUID tag.
- */
- public GUIDTag() {
- // No implementation required.
- }
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "GUID";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if (arguments.length != 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 0, arguments.length);
- throw DecodeException.fatalError(message);
- }
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
+
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(arguments, lineNumber);
+ }
+
+ private void initialize(String[] arguments, int lineNumber) throws DecodeException {
if (arguments.length != 0) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
0, arguments.length);
@@ -944,408 +503,140 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
templateValue.append(UUID.randomUUID().toString());
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to base presence of one attribute
- * on the absence of another attribute and/or attribute value.
+ * Base tag to use to base presence of one attribute on the absence/presence
+ * of another attribute and/or attribute value.
*/
- static class IfAbsentTag extends TemplateTag {
+ abstract static class IfTag extends TemplateTag {
/** The attribute type for which to make the determination. */
- private AttributeType attributeType;
+ AttributeType attributeType;
/** The value for which to make the determination. */
- private String assertionValue;
+ String assertionValue;
- /**
- * Creates a new instance of this ifabsent tag.
- */
- public IfAbsentTag() {
- attributeType = null;
- assertionValue = null;
+ @Override
+ final boolean allowedInBranch() {
+ return true;
}
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ final void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(schema, branch, null, arguments, lineNumber);
+ }
+
+ @Override
+ final void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(schema, null, template, arguments, lineNumber);
+ }
+
+ private void initialize(Schema schema, Branch branch, Template template, String[] arguments, int lineNumber)
+ throws DecodeException {
+ if ((arguments.length < 1) || (arguments.length > 2)) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
+ lineNumber, 1, 2, arguments.length);
+ throw DecodeException.fatalError(message);
+ }
+
+ attributeType = schema.getAttributeType(arguments[0].toLowerCase());
+ if (!hasAttributeTypeInBranchOrTemplate(attributeType, branch, template)) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
+ throw DecodeException.fatalError(message);
+ }
+
+ if (arguments.length == 2) {
+ assertionValue = arguments[1];
+ } else {
+ assertionValue = null;
+ }
+ }
+ }
+
+ /**
+ * Tag used to base presence of one attribute on the absence of another
+ * attribute and/or attribute value.
+ */
+ static class IfAbsentTag extends IfTag {
+ @Override
+ String getName() {
return "IfAbsent";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return true;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
- int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if ((arguments.length < 1) || (arguments.length > 2)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 1, 2, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = arguments[0].toLowerCase();
- AttributeType t = schema.getAttributeType(lowerName);
- if (!branch.hasAttribute(t)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments.length == 2) {
- assertionValue = arguments[1];
- } else {
- assertionValue = null;
- }
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
- @Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if ((arguments.length < 1) || (arguments.length > 2)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 1, 2, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = arguments[0].toLowerCase();
- attributeType = schema.getAttributeType(lowerName);
- if (!template.hasAttribute(attributeType)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments.length == 2) {
- assertionValue = arguments[1];
- } else {
- assertionValue = null;
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
List<TemplateValue> values = templateEntry.getValues(attributeType);
- if ((values == null) || values.isEmpty()) {
- return TagResult.SUCCESS_RESULT;
+ if (values == null) {
+ return TagResult.SUCCESS;
}
-
if (assertionValue == null) {
- return TagResult.OMIT_FROM_ENTRY;
- } else {
- for (TemplateValue v : values) {
- if (assertionValue.equals(v.getValueAsString())) {
- return TagResult.OMIT_FROM_ENTRY;
- }
- }
-
- return TagResult.SUCCESS_RESULT;
+ return TagResult.FAILURE;
}
+ for (TemplateValue v : values) {
+ if (assertionValue.equals(v.getValueAsString())) {
+ return TagResult.FAILURE;
+ }
+ }
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to base presence of one attribute
- * on the presence of another attribute and/or attribute value.
+ * Tag used to base presence of one attribute on the presence of another
+ * attribute and/or attribute value.
*/
- static class IfPresentTag extends TemplateTag {
- /** The attribute type for which to make the determination. */
- private AttributeType attributeType;
-
- /** The value for which to make the determination. */
- private String assertionValue;
-
- /**
- * Creates a new instance of this ifpresent tag.
- */
- public IfPresentTag() {
- attributeType = null;
- assertionValue = null;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ static class IfPresentTag extends IfTag {
+ @Override
+ String getName() {
return "IfPresent";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return true;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
- int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if ((arguments.length < 1) || (arguments.length > 2)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 1, 2, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = arguments[0].toLowerCase();
- AttributeType t = schema.getAttributeType(lowerName);
- if (!branch.hasAttribute(t)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments.length == 2) {
- assertionValue = arguments[1];
- } else {
- assertionValue = null;
- }
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
- @Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if ((arguments.length < 1) || (arguments.length > 2)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 1, 2, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- String lowerName = arguments[0].toLowerCase();
- attributeType = schema.getAttributeType(lowerName);
- if (!template.hasAttribute(attributeType)) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNDEFINED_ATTRIBUTE.get(arguments[0], lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments.length == 2) {
- assertionValue = arguments[1];
- } else {
- assertionValue = null;
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
List<TemplateValue> values = templateEntry.getValues(attributeType);
if ((values == null) || values.isEmpty()) {
- return TagResult.OMIT_FROM_ENTRY;
+ return TagResult.FAILURE;
}
if (assertionValue == null) {
- return TagResult.SUCCESS_RESULT;
- } else {
- for (TemplateValue v : values) {
- if (assertionValue.equals(v.getValueAsString())) {
- return TagResult.SUCCESS_RESULT;
- }
- }
-
- return TagResult.OMIT_FROM_ENTRY;
+ return TagResult.SUCCESS;
}
+ for (TemplateValue v : values) {
+ if (assertionValue.equals(v.getValueAsString())) {
+ return TagResult.SUCCESS;
+ }
+ }
+ return TagResult.FAILURE;
}
}
/**
- * This class defines a tag that is used to include a last name in the
- * attribute value.
+ * Tag used to include a last name in the attribute value.
*/
- static class LastNameTag extends TemplateTag {
- /** The template file with which this tag is associated. */
- private TemplateFile templateFile;
-
- /**
- * Creates a new instance of this last name tag.
- */
- public LastNameTag() {
- // No implementation required.
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ static class LastNameTag extends NameTag {
+ @Override
+ String getName() {
return "Last";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return false;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- this.templateFile = templateFile;
-
- if (arguments.length != 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 0, arguments.length);
- throw DecodeException.fatalError(message);
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
templateValue.append(templateFile.getLastName());
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that may be used to select a value from a
- * pre-defined list, optionally defining weights for each value that can
- * impact the likelihood of a given item being selected.
+ * Tag used to select a value from a pre-defined list, optionally defining
+ * weights for each value that can impact the likelihood of a given item
+ * being selected.
* <p>
* The items to include in the list should be specified as arguments to the
* tag. If the argument ends with a semicolon followed by an integer, then
@@ -1365,139 +656,58 @@
/** The random number generator for this tag. */
private Random random;
- /**
- * Creates a new instance of this list tag.
- */
- public ListTag() {
- // No implementation required.
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "List";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber, warnings);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber, warnings);
}
- /**
- * Performs any initialization for this tag that may be needed for this
- * tag.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber,
+ private void initialize(TemplateFile templateFile, String[] arguments, int lineNumber,
List<LocalizableMessage> warnings) throws DecodeException {
if (arguments.length == 0) {
throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_LIST_NO_ARGUMENTS.get(lineNumber));
}
-
valueStrings = new String[arguments.length];
valueWeights = new int[arguments.length];
cumulativeWeight = 0;
random = templateFile.getRandom();
for (int i = 0; i < arguments.length; i++) {
- String s = arguments[i];
-
+ String value = arguments[i];
int weight = 1;
- int semicolonPos = s.lastIndexOf(';');
+ int semicolonPos = value.lastIndexOf(';');
if (semicolonPos >= 0) {
try {
- weight = Integer.parseInt(s.substring(semicolonPos + 1));
- s = s.substring(0, semicolonPos);
- } catch (Exception e) {
- warnings.add(WARN_ENTRY_GENERATOR_TAG_LIST_INVALID_WEIGHT.get(lineNumber, s));
+ weight = Integer.parseInt(value.substring(semicolonPos + 1));
+ value = value.substring(0, semicolonPos);
+ } catch (NumberFormatException e) {
+ warnings.add(WARN_ENTRY_GENERATOR_TAG_LIST_INVALID_WEIGHT.get(lineNumber, value));
}
}
-
cumulativeWeight += weight;
- valueStrings[i] = s;
+ valueStrings[i] = value;
valueWeights[i] = cumulativeWeight;
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
int selectedWeight = random.nextInt(cumulativeWeight) + 1;
for (int i = 0; i < valueWeights.length; i++) {
if (selectedWeight <= valueWeights[i]) {
@@ -1505,62 +715,48 @@
break;
}
}
-
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include the DN of the parent
- * entry in the attribute value.
+ * Base tag to use to include a first name or last name in the attribute
+ * value.
*/
- static class ParentDNTag extends TemplateTag {
- /**
- * Creates a new instance of this parent DN tag.
- */
- public ParentDNTag() {
- // No implementation required.
- }
+ static abstract class NameTag extends TemplateTag {
+ /** The template file with which this tag is associated. */
+ TemplateFile templateFile;
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
- return "ParentDN";
- }
-
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ final boolean allowedInBranch() {
return false;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ final void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ this.templateFile = templateFile;
+
+ if (arguments.length != 0) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
+ 0, arguments.length);
+ throw DecodeException.fatalError(message);
+ }
+ }
+ }
+
+ /**
+ * Base tag to use to include the DN of the parent entry in the attribute value.
+ */
+ static abstract class ParentTag extends TemplateTag {
+
+ @Override
+ final boolean allowedInBranch() {
+ return false;
+ }
+
+ @Override
+ final void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
if (arguments.length != 0) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
@@ -1568,129 +764,66 @@
throw DecodeException.fatalError(message);
}
}
+ }
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ /**
+ * Tag used to include the DN of the parent entry in the attribute value.
+ */
+ static class ParentDNTag extends ParentTag {
+
+ @Override
+ String getName() {
+ return "ParentDN";
+ }
+
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
DN parentDN = templateEntry.getParentDN();
if ((parentDN == null) || parentDN.isRootDN()) {
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
-
templateValue.append(parentDN);
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to indicate that a value should
- * only be included in a percentage of the entries.
+ * Tag used to indicate that a value should only be included in a percentage
+ * of the entries.
*/
static class PresenceTag extends TemplateTag {
- /** The percentage of the entries in which this attribute value should */
- /** appear. */
+ /**
+ * The percentage of the entries in which this attribute value should
+ * appear.
+ */
private int percentage;
/** The random number generator for this tag. */
private Random random;
- /**
- * Creates a new instance of this presence tag.
- */
- public PresenceTag() {
- percentage = 100;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "Presence";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(templateFile, arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(templateFile, arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed for this
- * tag.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber)
+ private void initialize(TemplateFile templateFile, String[] arguments, int lineNumber)
throws DecodeException {
random = templateFile.getRandom();
@@ -1702,14 +835,14 @@
try {
percentage = Integer.parseInt(arguments[0]);
-
if (percentage < 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INTEGER_BELOW_LOWER_BOUND.get(percentage, 0,
- getName(), lineNumber);
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INTEGER_BELOW_LOWER_BOUND.get(percentage,
+ 0, getName(), lineNumber);
throw DecodeException.fatalError(message);
- } else if (percentage > 100) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INTEGER_ABOVE_UPPER_BOUND.get(percentage, 100,
- getName(), lineNumber);
+ }
+ if (percentage > 100) {
+ LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INTEGER_ABOVE_UPPER_BOUND.get(percentage,
+ 100, getName(), lineNumber);
throw DecodeException.fatalError(message);
}
} catch (NumberFormatException nfe) {
@@ -1719,31 +852,20 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
int intValue = random.nextInt(100);
if (intValue < percentage) {
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
} else {
- return TagResult.OMIT_FROM_ENTRY;
+ return TagResult.FAILURE;
}
}
}
/**
- * This class defines a tag that may be used to generate random values. It
- * has a number of subtypes based on the type of information that should be
- * generated, including:
+ * Tag used to generate random values. It has a number of subtypes based on
+ * the type of information that should be generated, including:
* <UL>
* <LI>alpha:length</LI>
* <LI>alpha:minlength:maxlength</LI>
@@ -1764,32 +886,31 @@
* </UL>
*/
static class RandomTag extends TemplateTag {
- /**
- * The value that indicates that the value is to be generated from a
- * fixed number of characters from a given character set.
- */
- public static final int RANDOM_TYPE_CHARS_FIXED = 1;
- /**
- * The value that indicates that the value is to be generated from a
- * variable number of characters from a given character set.
- */
- public static final int RANDOM_TYPE_CHARS_VARIABLE = 2;
-
- /**
- * The value that indicates that the value should be a random number.
- */
- public static final int RANDOM_TYPE_NUMERIC = 3;
-
- /**
- * The value that indicates that the value should be a random month.
- */
- public static final int RANDOM_TYPE_MONTH = 4;
-
- /**
- * The value that indicates that the value should be a telephone number.
- */
- public static final int RANDOM_TYPE_TELEPHONE = 5;
+ static enum RandomType {
+ /**
+ * Generates values from a fixed number of characters from a given
+ * character set.
+ */
+ CHARS_FIXED,
+ /**
+ * Generates values from a variable number of characters from a given
+ * character set.
+ */
+ CHARS_VARIABLE,
+ /**
+ * Generates numbers.
+ */
+ NUMERIC,
+ /**
+ * Generates months (as text).
+ */
+ MONTH,
+ /**
+ * Generates telephone numbers.
+ */
+ TELEPHONE
+ }
/**
* The character set that will be used for alphabetic characters.
@@ -1831,7 +952,7 @@
/** The number of characters between the minimum and maximum length */
/** (inclusive). */
- private int lengthRange;
+ private int lengthRange = 1;
/** The maximum number of characters to include in the value. */
private int maxLength;
@@ -1840,7 +961,7 @@
private int minLength;
/** The type of random value that should be generated. */
- private int randomType;
+ private RandomType randomType;
/** The maximum numeric value that should be generated. */
private long maxValue;
@@ -1852,110 +973,34 @@
* The number of values between the minimum and maximum value
* (inclusive).
*/
- private long valueRange;
+ private long valueRange = 1L;
/** The random number generator for this tag. */
private Random random;
- /**
- * Creates a new instance of this random tag.
- */
- public RandomTag() {
- characterSet = null;
- decimalFormat = null;
- lengthRange = 1;
- maxLength = 0;
- minLength = 0;
- randomType = 0;
- maxValue = 0L;
- minValue = 0L;
- valueRange = 1L;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "Random";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber, warnings);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber, warnings);
+ initialize(templateFile, arguments, lineNumber, warnings);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing either a branch or template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber,
+ private void initialize(TemplateFile templateFile, String[] arguments, int lineNumber,
List<LocalizableMessage> warnings) throws DecodeException {
random = templateFile.getRandom();
@@ -1974,7 +1019,7 @@
decodeLength(arguments, 1, lineNumber, warnings);
} else if (randomTypeString.equals("numeric")) {
if (numArgs == 2) {
- randomType = RANDOM_TYPE_CHARS_FIXED;
+ randomType = RandomType.CHARS_FIXED;
characterSet = NUMERIC_CHARS;
try {
@@ -1994,7 +1039,7 @@
throw DecodeException.fatalError(message, nfe);
}
} else if ((numArgs == 3) || (numArgs == 4)) {
- randomType = RANDOM_TYPE_NUMERIC;
+ randomType = RandomType.NUMERIC;
if (numArgs == 4) {
try {
@@ -2054,7 +1099,7 @@
characterSet = BASE64_CHARS;
decodeLength(arguments, 1, lineNumber, warnings);
} else if (randomTypeString.equals("month")) {
- randomType = RANDOM_TYPE_MONTH;
+ randomType = RandomType.MONTH;
if (numArgs == 1) {
maxLength = 0;
@@ -2077,7 +1122,7 @@
throw DecodeException.fatalError(message);
}
} else if (randomTypeString.equals("telephone")) {
- randomType = RANDOM_TYPE_TELEPHONE;
+ randomType = RandomType.TELEPHONE;
} else {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_UNKNOWN_RANDOM_TYPE.get(lineNumber,
randomTypeString);
@@ -2108,7 +1153,7 @@
if (numArgs == 2) {
// There is a fixed number of characters in the value.
- randomType = RANDOM_TYPE_CHARS_FIXED;
+ randomType = RandomType.CHARS_FIXED;
try {
minLength = Integer.parseInt(arguments[startPos]);
@@ -2128,7 +1173,7 @@
}
} else if (numArgs == 3) {
// There are minimum and maximum lengths.
- randomType = RANDOM_TYPE_CHARS_VARIABLE;
+ randomType = RandomType.CHARS_VARIABLE;
try {
minLength = Integer.parseInt(arguments[startPos]);
@@ -2168,33 +1213,23 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
switch (randomType) {
- case RANDOM_TYPE_CHARS_FIXED:
+ case CHARS_FIXED:
for (int i = 0; i < minLength; i++) {
templateValue.append(characterSet[random.nextInt(characterSet.length)]);
}
break;
- case RANDOM_TYPE_CHARS_VARIABLE:
+ case CHARS_VARIABLE:
int numChars = random.nextInt(lengthRange) + minLength;
for (int i = 0; i < numChars; i++) {
templateValue.append(characterSet[random.nextInt(characterSet.length)]);
}
break;
- case RANDOM_TYPE_NUMERIC:
+ case NUMERIC:
long randomValue = ((random.nextLong() & 0x7FFFFFFFFFFFFFFFL) % valueRange) + minValue;
if (decimalFormat == null) {
templateValue.append(randomValue);
@@ -2203,7 +1238,7 @@
}
break;
- case RANDOM_TYPE_MONTH:
+ case MONTH:
String month = MONTHS[random.nextInt(MONTHS.length)];
if ((maxLength == 0) || (month.length() <= maxLength)) {
templateValue.append(month);
@@ -2212,7 +1247,7 @@
}
break;
- case RANDOM_TYPE_TELEPHONE:
+ case TELEPHONE:
templateValue.append("+1 ");
for (int i = 0; i < 3; i++) {
templateValue.append(NUMERIC_CHARS[random.nextInt(NUMERIC_CHARS.length)]);
@@ -2228,89 +1263,38 @@
break;
}
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include the RDN of the current
- * entry in the attribute value.
+ * Tag used to include the RDN of the current entry in the attribute value.
*/
static class RDNTag extends TemplateTag {
- /**
- * Creates a new instance of this RDN tag.
- */
- public RDNTag() {
- // No implementation required.
- }
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "RDN";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if (arguments.length != 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 0, arguments.length);
- throw DecodeException.fatalError(message);
- }
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template, String[] arguments,
+ int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(arguments, lineNumber);
+ }
+
+ private void initialize(String[] arguments, int lineNumber) throws DecodeException {
if (arguments.length != 0) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
0, arguments.length);
@@ -2318,35 +1302,25 @@
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
DN dn = templateEntry.getDN();
if ((dn == null) || dn.isRootDN()) {
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
} else {
templateValue.append(dn.rdn());
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
}
/**
- * This class defines a tag that is used to include a
- * sequentially-incrementing integer in the generated values.
+ * Tag that is used to include a sequentially-incrementing integer in the
+ * generated values.
*/
static class SequentialTag extends TemplateTag {
/** Indicates whether to reset for each parent. */
- private boolean resetOnNewParents;
+ private boolean resetOnNewParents = true;
/** The initial value in the sequence. */
private int initialValue;
@@ -2354,515 +1328,156 @@
/** The next value in the sequence. */
private int nextValue;
- /**
- * Creates a new instance of this sequential tag.
- */
- public SequentialTag() {
- // No implementation required.
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "Sequential";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed for this
- * tag.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @throws DecodeException
- * If a problem occurs while initializing this tag.
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber)
- throws DecodeException {
- switch (arguments.length) {
- case 0:
- initialValue = 0;
- nextValue = 0;
- resetOnNewParents = true;
- break;
- case 1:
- try {
- initialValue = Integer.parseInt(arguments[0]);
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_INTEGER.get(arguments[0],
- getName(), lineNumber);
- throw DecodeException.fatalError(message);
+ private void initialize(String[] arguments, int lineNumber) throws DecodeException {
+ if (arguments.length < 0 || arguments.length > 2) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(
+ getName(), lineNumber, 0, 2, arguments.length));
+ }
+ if (arguments.length > 0) {
+ initializeValue(arguments[0], lineNumber);
+ if (arguments.length > 1) {
+ initializeReset(arguments[1], lineNumber);
}
-
- nextValue = initialValue;
- resetOnNewParents = true;
- break;
- case 2:
- try {
- initialValue = Integer.parseInt(arguments[0]);
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_INTEGER.get(arguments[0],
- getName(), lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- if (arguments[1].equalsIgnoreCase("true")) {
- resetOnNewParents = true;
- } else if (arguments[1].equalsIgnoreCase("false")) {
- resetOnNewParents = false;
- } else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_BOOLEAN.get(arguments[1],
- getName(), lineNumber);
- throw DecodeException.fatalError(message);
- }
-
- nextValue = initialValue;
- break;
- default:
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 0, 2, arguments.length);
- throw DecodeException.fatalError(message);
}
}
- /**
- * Performs any initialization for this tag that may be needed when
- * starting to generate entries below a new parent.
- *
- * @param parentEntry
- * The entry below which the new entries will be generated.
- */
- public void initializeForParent(TemplateEntry parentEntry) {
+ private void initializeReset(String resetValue, int lineNumber) throws DecodeException {
+ if (resetValue.equalsIgnoreCase("true")) {
+ resetOnNewParents = true;
+ } else if (resetValue.equalsIgnoreCase("false")) {
+ resetOnNewParents = false;
+ } else {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_BOOLEAN.get(
+ resetValue, getName(), lineNumber));
+ }
+ }
+
+ private void initializeValue(String value, int lineNumber) throws DecodeException {
+ try {
+ initialValue = Integer.parseInt(value);
+ } catch (NumberFormatException nfe) {
+ throw DecodeException.fatalError(ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_INTEGER.get(
+ value, getName(), lineNumber));
+ }
+ nextValue = initialValue;
+ }
+
+ @Override
+ void initializeForParent(TemplateEntry parentEntry) {
if (resetOnNewParents) {
nextValue = initialValue;
}
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
templateValue.append(nextValue++);
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to hold static text (i.e., text
- * that appears outside of any tag).
+ * Tag that is used to hold static text (i.e., text that appears outside of
+ * any tag).
*/
static class StaticTextTag extends TemplateTag {
- /** The static text to include in the LDIF. */
- private String text;
+ /** The static text to include. */
+ private String text = "";
- /**
- * Creates a new instance of this static text tag.
- */
- public StaticTextTag() {
- text = "";
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "StaticText";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
+ @Override
+ boolean allowedInBranch() {
return true;
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
+ void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if (arguments.length != 1) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 1, arguments.length);
- throw DecodeException.fatalError(message);
- }
-
- text = arguments[0];
+ initialize(arguments, lineNumber);
}
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
+ void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
+ initialize(arguments, lineNumber);
+ }
+
+ private void initialize(String[] arguments, int lineNumber) throws DecodeException {
if (arguments.length != 1) {
LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
1, arguments.length);
throw DecodeException.fatalError(message);
}
-
text = arguments[0];
}
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ @Override
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
templateValue.append(text);
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
/**
- * This class defines a tag that is used to include the DN of the current
- * entry in the attribute value, with underscores in place of the commas.
+ * Tag used to include the DN of the current entry in the attribute value,
+ * with underscores in place of the commas.
*/
- static class UnderscoreDNTag extends TemplateTag {
- /** The number of DN components to include. */
- private int numComponents;
+ static class UnderscoreDNTag extends DNTag {
- /**
- * Creates a new instance of this DN tag.
- */
- public UnderscoreDNTag() {
- numComponents = 0;
- }
-
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "_DN";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return true;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a branch definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param branch
- * The branch in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForBranch(Schema schema, TemplateFile templateFile, Branch branch, String[] arguments,
- int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
- @Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- initializeInternal(templateFile, arguments, lineNumber);
- }
-
- /**
- * Performs any initialization for this tag that may be needed for this
- * tag.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @throws DecodeException
- * TODO
- */
- private void initializeInternal(TemplateFile templateFile, String[] arguments, int lineNumber)
- throws DecodeException {
- if (arguments.length == 0) {
- numComponents = 0;
- } else if (arguments.length == 1) {
- try {
- numComponents = Integer.parseInt(arguments[0]);
- } catch (NumberFormatException nfe) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_INTEGER.get(arguments[0],
- getName(), lineNumber);
- throw DecodeException.fatalError(message);
- }
- } else {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(getName(),
- lineNumber, 0, 1, arguments.length);
- throw DecodeException.fatalError(message);
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
- DN dn = templateEntry.getDN();
- if ((dn == null) || dn.isRootDN()) {
- return TagResult.SUCCESS_RESULT;
- }
-
- if (numComponents == 0) {
- templateValue.append(dn.rdn());
- for (int i = 1; i < dn.size(); i++) {
- templateValue.append("_");
- templateValue.append(dn.parent(i).rdn());
- }
- } else if (numComponents > 0) {
- int count = Math.min(numComponents, dn.size());
- templateValue.append(dn.rdn());
- for (int i = 1; i < count; i++) {
- templateValue.append(",");
- templateValue.append(dn.parent(i).rdn());
- }
- } else {
- int size = dn.size();
- int count = Math.min(Math.abs(numComponents), size);
-
- templateValue.append(dn.parent(size - count).rdn());
- for (int i = 1; i < count; i++) {
- templateValue.append(",");
- templateValue.append(dn.parent(size - count + i).rdn());
- }
- }
-
- return TagResult.SUCCESS_RESULT;
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ return generateValue(templateEntry, templateValue, "_");
}
}
/**
- * This class defines a tag that is used to include the DN of the parent
- * entry in the attribute value, with underscores in place of commas.
+ * Tag used to include the DN of the parent entry in the attribute value,
+ * with underscores in place of commas.
*/
- static class UnderscoreParentDNTag extends TemplateTag {
- /**
- * Creates a new instance of this underscore parent DN tag.
- */
- public UnderscoreParentDNTag() {
- // No implementation required.
- }
+ static class UnderscoreParentDNTag extends ParentTag {
- /**
- * Retrieves the name for this tag.
- *
- * @return The name for this tag.
- */
- public String getName() {
+ @Override
+ String getName() {
return "_ParentDN";
}
- /**
- * Indicates whether this tag is allowed for use in the extra lines for
- * branches.
- *
- * @return <CODE>true</CODE> if this tag may be used in branch
- * definitions, or <CODE>false</CODE> if not.
- */
- public boolean allowedInBranch() {
- return false;
- }
-
- /**
- * Performs any initialization for this tag that may be needed while
- * parsing a template definition.
- *
- * @param templateFile
- * The template file in which this tag is used.
- * @param template
- * The template in which this tag is used.
- * @param arguments
- * The set of arguments provided for this tag.
- * @param lineNumber
- * The line number on which this tag appears in the template
- * file.
- * @param warnings
- * A list into which any appropriate warning messages may be
- * placed.
- */
@Override
- public void initializeForTemplate(Schema schema, TemplateFile templateFile, Template template,
- String[] arguments, int lineNumber, List<LocalizableMessage> warnings) throws DecodeException {
- if (arguments.length != 0) {
- LocalizableMessage message = ERR_ENTRY_GENERATOR_TAG_INVALID_ARGUMENT_COUNT.get(getName(), lineNumber,
- 0, arguments.length);
- throw DecodeException.fatalError(message);
- }
- }
-
- /**
- * Generates the content for this tag by appending it to the provided
- * tag.
- *
- * @param templateEntry
- * The entry for which this tag is being generated.
- * @param templateValue
- * The template value to which the generated content should
- * be appended.
- * @return The result of generating content for this tag.
- */
- public TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
+ TagResult generateValue(TemplateEntry templateEntry, TemplateValue templateValue) {
DN parentDN = templateEntry.getParentDN();
if ((parentDN == null) || parentDN.isRootDN()) {
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
templateValue.append(parentDN.rdn());
for (int i = 1; i < parentDN.size(); i++) {
@@ -2870,7 +1485,7 @@
templateValue.append(parentDN.parent(i).rdn());
}
- return TagResult.SUCCESS_RESULT;
+ return TagResult.SUCCESS;
}
}
}
diff --git a/opendj3/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj3/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index 47396b9..a09f7d8 100755
--- a/opendj3/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj3/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1434,9 +1434,6 @@
ERR_ENTRY_GENERATOR_TAG_CANNOT_PARSE_AS_BOOLEAN=Cannot parse value "%s" as \
a Boolean value for tag %s on line %d of the template file. The value must \
be either 'true' or 'false'
-ERR_ENTRY_GENERATOR_UNDEFINED_BRANCH_SUBORDINATE=The branch with entry DN \
- '%s' references a subordinate template named '%s' which is not defined in the \
- template file
ERR_ENTRY_GENERATOR_CANNOT_LOAD_TAG_CLASS=Unable to load class %s for use \
as a MakeLDIF tag
ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_TAG=Cannot instantiate class %s as a \
@@ -1450,9 +1447,6 @@
%d is missing an equal sign to delimit the constant name from the value
ERR_ENTRY_GENERATOR_DEFINE_NAME_EMPTY=The constant definition on line %d \
does not include a name for the constant
-ERR_ENTRY_GENERATOR_CONFLICTING_CONSTANT_NAME=The definition for constant \
- %s on line %d conflicts with an earlier constant definition included in the \
- template
ERR_ENTRY_GENERATOR_WARNING_DEFINE_VALUE_EMPTY=Constant %s defined on line \
%d has not been assigned a value
ERR_ENTRY_GENERATOR_CONFLICTING_BRANCH_DN=The branch definition %s starting \
@@ -1468,18 +1462,21 @@
template file
ERR_ENTRY_GENERATOR_CANNOT_DECODE_BRANCH_DN=Unable to decode branch DN "%s" \
on line %d of the template file
-ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_TEMPLATE_NO_COLON=Subordinate \
- template definition on line %d for branch %s is missing a colon to separate \
+ERR_ENTRY_GENERATOR_UNDEFINED_BRANCH_SUBORDINATE=The branch with entry DN \
+ '%s' references a subordinate template named '%s' which is not defined in the \
+ template file
+ERR_ENTRY_GENERATOR_SUBORDINATE_TEMPLATE_NO_COLON=Subordinate \
+ template definition on line %d for %s %s is missing a colon to separate \
the template name from the number of entries
-ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_INVALID_NUM_ENTRIES=Subordinate \
- template definition on line %d for branch %s specified invalid number of \
+ERR_ENTRY_GENERATOR_SUBORDINATE_INVALID_NUM_ENTRIES=Subordinate \
+ template definition on line %d for %s %s specified invalid number of \
entries %d for template %s
-WARN_ENTRY_GENERATOR_BRANCH_SUBORDINATE_ZERO_ENTRIES=Subordinate template \
- definition on line %d for branch %s specifies that zero entries of type %s \
+WARN_ENTRY_GENERATOR_SUBORDINATE_ZERO_ENTRIES=Subordinate template \
+ definition on line %d for %s %s specifies that zero entries of type %s \
should be generated
-ERR_ENTRY_GENERATOR_BRANCH_SUBORDINATE_CANT_PARSE_NUMENTRIES=Unable to \
+ERR_ENTRY_GENERATOR_SUBORDINATE_CANT_PARSE_NUMENTRIES=Unable to \
parse the number of entries for template %s as an integer for the subordinate \
- template definition on line %d for branch %s
+ template definition on line %d for %s %s
ERR_ENTRY_GENERATOR_TEMPLATE_SUBORDINATE_TEMPLATE_NO_COLON=Subordinate \
template definition on line %d for template %s is missing a colon to separate \
the template name from the number of entries
@@ -1494,22 +1491,14 @@
template definition on line %d for template %s
ERR_ENTRY_GENERATOR_TEMPLATE_MISSING_RDN_ATTR=The template named %s \
includes RDN attribute %s that is not assigned a value in that template
-ERR_ENTRY_GENERATOR_NO_COLON_IN_BRANCH_EXTRA_LINE=There is no colon to \
- separate the attribute name from the value pattern on line %d of the template \
- file in the definition for branch %s
-ERR_ENTRY_GENERATOR_NO_ATTR_IN_BRANCH_EXTRA_LINE=There is no attribute name \
- before the colon on line %d of the template file in the definition for branch \
- %s
-WARN_ENTRY_GENERATOR_NO_VALUE_IN_BRANCH_EXTRA_LINE=The value pattern for \
- line %d of the template file in the definition for branch %s is empty
ERR_ENTRY_GENERATOR_NO_COLON_IN_TEMPLATE_LINE=There is no colon to separate \
the attribute name from the value pattern on line %d of the template file in \
- the definition for template %s
+ the definition for %s %s
ERR_ENTRY_GENERATOR_NO_ATTR_IN_TEMPLATE_LINE=There is no attribute name \
before the colon on line %d of the template file in the definition for \
- template %s
+ template %s %s
WARN_ENTRY_GENERATOR_NO_VALUE_IN_TEMPLATE_LINE=The value pattern for line \
- %d of the template file in the definition for template %s is empty
+ %d of the template file in the definition for %s %s is empty
ERR_ENTRY_GENERATOR_NO_SUCH_TAG=An undefined tag %s is referenced on line \
%d of the template file
ERR_ENTRY_GENERATOR_CANNOT_INSTANTIATE_NEW_TAG=An unexpected error occurred \
@@ -1526,6 +1515,8 @@
the template file references an unknown random type of %s
ERR_ENTRY_GENERATOR_COULD_NOT_FIND_TEMPLATE_FILE=Could not find template \
file %s
+ERR_ENTRY_GENERATOR_COULD_NOT_FIND_NAME_FILE=Could not find names resource \
+ file %s
ERR_ENTRY_GENERATOR_TAG_CANNOT_FIND_FILE=Cannot find file %s referenced by \
tag %s on line %d of the template file
ERR_ENTRY_GENERATOR_TAG_INVALID_FILE_ACCESS_MODE=Invalid file access mode \
diff --git a/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template b/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template
index 0b3655f..3f5b1e3 100644
--- a/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template
+++ b/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template
@@ -3,8 +3,12 @@
define numusers=10000
branch: [suffix]
+objectClass: top
+objectClass: domainComponent
branch: ou=People,[suffix]
+objectClass: top
+objectClass: organizationalUnit
subordinateTemplate: person:[numusers]
template: person
diff --git a/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/people_and_groups.template b/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/people_and_groups.template
new file mode 100644
index 0000000..0f2c423
--- /dev/null
+++ b/opendj3/opendj-core/src/main/resources/org/forgerock/opendj/ldif/people_and_groups.template
@@ -0,0 +1,62 @@
+define suffix=dc=example,dc=com
+define maildomain=example.com
+define numusers=10
+define numous=10
+define numgroup=5
+
+branch: [suffix]
+subordinateTemplate: ous:[numous]
+
+template: ous
+subordinateTemplate: People:1
+subordinateTemplate: Groups:1
+rdnAttr: ou
+objectclass: top
+objectclass: organizationalUnit
+ou: Organization_<sequential:1>
+description: This is {ou}
+
+template: People
+rdnAttr: ou
+subordinateTemplate: person:[numusers]
+objectclass: top
+objectclass: organizationalUnit
+ou: People
+
+template: Groups
+subordinateTemplate: groupOfName:[numgroup]
+rdnAttr: ou
+objectclass: top
+objectclass: organizationalUnit
+ou: Groups
+
+template: person
+rdnAttr: uid
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: <first>
+sn: <last>
+cn: {givenName} {sn}
+initials: {givenName:1}<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}
+employeeNumber: <sequential:0>
+uid: user.{employeeNumber}
+mail: {uid}@[maildomain]
+userPassword: password
+telephoneNumber: <random:telephone>
+homePhone: <random:telephone>
+pager: <random:telephone>
+mobile: <random:telephone>
+street: <random:numeric:5> <file:streets> Street
+l: <file:cities>
+st: <file:states>
+postalCode: <random:numeric:5>
+postalAddress: {cn}${street}${l}, {st} {postalCode}
+description: This is the description for {cn}.
+
+template: groupOfName
+rdnAttr: cn
+objectClass: top
+objectClass: groupOfNames
+cn: Group_<sequential:1>
\ No newline at end of file
diff --git a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
index 4961c05..82a7e29 100644
--- a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
+++ b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
@@ -32,8 +32,8 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.util.Arrays;
import java.util.Iterator;
-
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.Schema;
@@ -48,19 +48,19 @@
public final class RDNTestCase extends TypesTestCase {
// Domain component attribute type.
- private static final AttributeType AT_DC;
+ private static final AttributeType ATTR_TYPE_DC;
// Common name attribute type.
- private static final AttributeType AT_CN;
+ private static final AttributeType ATTR_TYPE_CN;
// Test attribute value.
- private static final AVA AV_DC_ORG;
+ private static final AVA ATTR_VALUE_DC_ORG;
static {
- AT_DC = Schema.getCoreSchema().getAttributeType("dc");
- AT_CN = Schema.getCoreSchema().getAttributeType("cn");
+ ATTR_TYPE_DC = Schema.getCoreSchema().getAttributeType("dc");
+ ATTR_TYPE_CN = Schema.getCoreSchema().getAttributeType("cn");
// Set the avas.
- AV_DC_ORG = new AVA(AT_DC, ByteString.valueOf("org"));
+ ATTR_VALUE_DC_ORG = new AVA(ATTR_TYPE_DC, ByteString.valueOf("org"));
}
// org bytestring.
@@ -211,13 +211,13 @@
*/
@Test
public void testConstructor() throws Exception {
- final RDN rdn = new RDN(AT_DC, ORG);
+ final RDN rdn = new RDN(ATTR_TYPE_DC, ORG);
assertEquals(rdn.size(), 1);
assertEquals(rdn.isMultiValued(), false);
- assertEquals(rdn.getFirstAVA().getAttributeType(), AT_DC);
- assertEquals(rdn.getFirstAVA().getAttributeType().getNameOrOID(), AT_DC.getNameOrOID());
- assertEquals(rdn.getFirstAVA(), AV_DC_ORG);
+ assertEquals(rdn.getFirstAVA().getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(rdn.getFirstAVA().getAttributeType().getNameOrOID(), ATTR_TYPE_DC.getNameOrOID());
+ assertEquals(rdn.getFirstAVA(), ATTR_VALUE_DC_ORG);
}
/**
@@ -230,9 +230,51 @@
public void testConstructorWithString() throws Exception {
final RDN rdn = new RDN("dc", "org");
assertEquals(rdn.size(), 1);
- assertEquals(rdn.getFirstAVA().getAttributeType(), AT_DC);
+ assertEquals(rdn.getFirstAVA().getAttributeType(), ATTR_TYPE_DC);
assertEquals(rdn.getFirstAVA().getAttributeType().getNameOrOID(), "dc");
- assertEquals(rdn.getFirstAVA(), AV_DC_ORG);
+ assertEquals(rdn.getFirstAVA(), ATTR_VALUE_DC_ORG);
+ }
+
+ @Test
+ public void testConstructorWithAVA() throws Exception {
+ final RDN rdn = new RDN(new AVA("dc", "org"));
+ assertEquals(rdn.size(), 1);
+ assertEquals(rdn.getFirstAVA().getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(rdn.getFirstAVA(), ATTR_VALUE_DC_ORG);
+ }
+
+ @Test
+ public void testConstructorWithMultipleAVAs() throws Exception {
+ AVA example = new AVA("dc", "example");
+ AVA org = new AVA("dc", "org");
+
+ final RDN rdn = new RDN(example, org);
+ assertEquals(rdn.size(), 2);
+ Iterator<AVA> rdnIt = rdn.iterator();
+ AVA firstAva = rdnIt.next();
+ assertEquals(firstAva.getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(firstAva, example);
+
+ AVA secondAva = rdnIt.next();
+ assertEquals(secondAva.getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(secondAva, org);
+ }
+
+ @Test
+ public void testConstructorWithCollectionOfAVAs() throws Exception {
+ AVA example = new AVA("dc", "example");
+ AVA org = new AVA("dc", "org");
+
+ final RDN rdn = new RDN(Arrays.asList(example, org));
+ assertEquals(rdn.size(), 2);
+ Iterator<AVA> rdnIt = rdn.iterator();
+ AVA firstAva = rdnIt.next();
+ assertEquals(firstAva.getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(firstAva, example);
+
+ AVA secondAva = rdnIt.next();
+ assertEquals(secondAva.getAttributeType(), ATTR_TYPE_DC);
+ assertEquals(secondAva, org);
}
/**
@@ -298,7 +340,7 @@
*/
@Test
public void testDuplicateSingle() {
- final RDN rdn1 = new RDN(AT_DC, ORG);
+ final RDN rdn1 = new RDN(ATTR_TYPE_DC, ORG);
final RDN rdn2 = RDN.valueOf("dc=org");
assertFalse(rdn1 == rdn2);
@@ -338,7 +380,7 @@
*/
@Test
public void testEqualityNonRDN() {
- final RDN rdn = new RDN(AT_DC, ORG);
+ final RDN rdn = new RDN(ATTR_TYPE_DC, ORG);
assertFalse(rdn.equals("this isn't an RDN"));
}
@@ -351,7 +393,7 @@
*/
@Test
public void testEqualityNull() {
- final RDN rdn = new RDN(AT_DC, ORG);
+ final RDN rdn = new RDN(ATTR_TYPE_DC, ORG);
assertFalse(rdn.equals(null));
}
@@ -368,8 +410,8 @@
assertTrue(rdn.isMultiValued());
assertEquals(rdn.size(), 2);
final Iterator<AVA> it = rdn.iterator();
- assertEquals(it.next().getAttributeType().getNameOrOID(), AT_DC.getNameOrOID());
- assertEquals(it.next().getAttributeType().getNameOrOID(), AT_CN.getNameOrOID());
+ assertEquals(it.next().getAttributeType().getNameOrOID(), ATTR_TYPE_DC.getNameOrOID());
+ assertEquals(it.next().getAttributeType().getNameOrOID(), ATTR_TYPE_CN.getNameOrOID());
}
/**
diff --git a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java
index 60cb5ef..4ec433b 100644
--- a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java
+++ b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java
@@ -29,16 +29,18 @@
import static org.fest.assertions.Assertions.*;
import static org.forgerock.opendj.ldap.TestCaseUtils.getTestFilePath;
-import static org.forgerock.opendj.ldif.EntryGenerator.*;
+import static org.forgerock.opendj.ldap.schema.CoreSchema.*;
import java.io.File;
import java.io.FileInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.SdkTestCase;
@@ -47,10 +49,13 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import com.forgerock.opendj.util.StaticUtils;
+
@SuppressWarnings("javadoc")
public class EntryGeneratorTestCase extends SdkTestCase {
- private static final String TEMPLATE_FILE_PATH = "org/forgerock/opendj/ldif/example.template";
+ private static final String BASIC_TEMPLATE_PATH = "org/forgerock/opendj/ldif/example.template";
+ private static final String SUBTEMPLATES_TEMPLATE_PATH = "org/forgerock/opendj/ldif/people_and_groups.template";
private String resourcePath;
private Schema schema;
@@ -58,40 +63,92 @@
public void setUp() throws Exception {
// path of directory in src/main/resources must be obtained from a file
// otherwise it may search in the wrong directory
- resourcePath = new File(getTestFilePath(TEMPLATE_FILE_PATH)).getParent();
+ resourcePath = new File(getTestFilePath(BASIC_TEMPLATE_PATH)).getParent();
schema = Schema.getDefaultSchema();
}
- @Test
- public void testReaderWithTemplateFile() throws Exception {
- String templatePath = getTestFilePath(TEMPLATE_FILE_PATH);
- EntryGenerator reader = newReader(templatePath).setResourcePath(resourcePath).build();
+ /**
+ * This test is a facility to print generated entries to stdout and should
+ * always be disabled.
+ * Turn it on locally if you need to see the output.
+ */
+ @Test(enabled = false)
+ public void printEntriesToStdOut() throws Exception {
+ String path = SUBTEMPLATES_TEMPLATE_PATH;
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator(getTestFilePath(path)).setResourcePath(resourcePath);
+ while (generator.hasNext()) {
+ System.out.println(generator.readEntry());
+ }
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
- checkReader(reader, 10000);
- reader.close();
}
@Test
- public void testReaderWithTemplateStream() throws Exception {
+ public void testCreateWithDefaultTemplateFile() throws Exception {
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator();
+ assertThat(generator.hasNext()).isTrue();
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Could not find template file unknown.*")
+ public void testCreateWithMissingTemplateFile() throws Exception {
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator("unknown/path");
+ generator.hasNext();
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
+ }
+
+ @Test
+ public void testCreateWithSetConstants() throws Exception {
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator().setConstant("numusers", 1);
+ generator.readEntry();
+ generator.readEntry();
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("uid=user.0,ou=People,dc=example,dc=com");
+ assertThat(generator.hasNext()).as("should have no more entries").isFalse();
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
+ }
+
+ @DataProvider(name = "generators")
+ public Object[][] createGenerators() throws Exception {
+ Object[][] generators = new Object[3][2];
+
+ String templatePath = getTestFilePath(BASIC_TEMPLATE_PATH);
+ generators[0][0] = new EntryGenerator(templatePath).setResourcePath(resourcePath);
+ generators[0][1] = 10000;
+
InputStream stream = new FileInputStream(
- new File(getTestFilePath(TEMPLATE_FILE_PATH)));
- EntryGenerator reader = newReader(stream).setResourcePath(resourcePath).build();
+ new File(templatePath));
+ generators[1][0] = new EntryGenerator(stream).setResourcePath(resourcePath);
+ generators[1][1] = 10000;
- checkReader(reader, 10000);
- reader.close();
- }
-
-
- @Test
- public void testReaderWithTemplateLines() throws Exception {
- EntryGenerator reader = newReader(
+ generators[2][0] = new EntryGenerator(
"define suffix=dc=example,dc=com",
"define maildomain=example.com",
"define numusers=2",
"",
"branch: [suffix]",
+ "objectClass: top",
+ "objectClass: domainComponent",
"",
"branch: ou=People,[suffix]",
+ "objectClass: top",
+ "objectClass: organizationalUnit",
"subordinateTemplate: person:[numusers]",
"",
"template: person",
@@ -118,41 +175,196 @@
"postalCode: <random:numeric:5>",
"postalAddress: {cn}${street}${l}, {st} {postalCode}",
"description: This is the description for {cn}.")
- .setResourcePath(resourcePath).build();
+ .setResourcePath(resourcePath);
+ generators[2][1] = 2;
- checkReader(reader, 2);
- reader.close();
+ return generators;
}
/**
- * Check the content of the reader for basic case.
+ * Test the generated DNs.
*
* Expecting 2 entries and then numberOfUsers entries.
*/
- private void checkReader(EntryGenerator reader, int numberOfUsers) throws Exception {
- assertThat(reader.hasNext()).isTrue();
- assertThat(reader.readEntry().getName().toString()).isEqualTo("dc=example,dc=com");
- assertThat(reader.hasNext()).isTrue();
- assertThat(reader.readEntry().getName().toString()).isEqualTo("ou=People,dc=example,dc=com");
- for (int i = 0; i < numberOfUsers; i++) {
- assertThat(reader.hasNext()).isTrue();
- assertThat(reader.readEntry().getName().toString()).
- isEqualTo("uid=user." + i + ",ou=People,dc=example,dc=com");
+ @Test(dataProvider = "generators")
+ public void testGeneratedDNs(EntryGenerator generator, int numberOfUsers) throws Exception {
+ try {
+ assertThat(generator.hasNext()).isTrue();
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("dc=example,dc=com");
+ assertThat(generator.hasNext()).isTrue();
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("ou=People,dc=example,dc=com");
+ for (int i = 0; i < numberOfUsers; i++) {
+ assertThat(generator.hasNext()).isTrue();
+ assertThat(generator.readEntry().getName().toString()).
+ isEqualTo("uid=user." + i + ",ou=People,dc=example,dc=com");
+ }
+ assertThat(generator.hasNext()).as("should have no more entries").isFalse();
+ } finally {
+ StaticUtils.closeSilently(generator);
}
- assertThat(reader.hasNext()).as("should have no more entries").isFalse();
}
- @Test(expectedExceptions = IOException.class,
- expectedExceptionsMessageRegExp = ".*Could not find template file unknown.*")
- public void testMissingTemplateFile() throws Exception {
- newReader("unknown").setResourcePath(resourcePath).build();
+ /**
+ * Test the complete content of top entry.
+ */
+ @Test(dataProvider = "generators")
+ public void testTopEntry(EntryGenerator generator, int numberOfUsers) throws Exception {
+ try {
+ Entry topEntry = generator.readEntry();
+ assertThat(topEntry.getName().toString()).isEqualTo("dc=example,dc=com");
+
+ Attribute dcAttribute = topEntry.getAttribute(getDCAttributeType().getNameOrOID());
+ assertThat(dcAttribute).isNotNull();
+ assertThat(dcAttribute.firstValueAsString()).isEqualTo("example");
+
+ checkEntryObjectClasses(topEntry, "top", "domainComponent");
+ } finally {
+ StaticUtils.closeSilently(generator);
+
+ }
}
- @Test(expectedExceptions = DecodeException.class,
- expectedExceptionsMessageRegExp = ".*Cannot find file streets.*")
- public void testMissingResourceFile() throws Exception {
- // fail to find first resource file which is 'streets'
- newReader(getTestFilePath(TEMPLATE_FILE_PATH)).setResourcePath("unknown").build();
+ /**
+ * Test the complete content of second entry.
+ */
+ @Test(dataProvider = "generators")
+ public void testSecondEntry(EntryGenerator generator, int numberOfUsers) throws Exception {
+ try {
+ generator.readEntry(); // skip top entry
+ Entry entry = generator.readEntry();
+ assertThat(entry.getName().toString()).isEqualTo("ou=People,dc=example,dc=com");
+
+ Attribute dcAttribute = entry.getAttribute(getOUAttributeType().getNameOrOID());
+ assertThat(dcAttribute).isNotNull();
+ assertThat(dcAttribute.firstValueAsString()).isEqualTo("People");
+
+ checkEntryObjectClasses(entry, "top", "organizationalUnit");
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
+ }
+
+ /**
+ * Test the complete content of first user entry.
+ */
+ @Test(dataProvider = "generators")
+ public void testFirstUserEntry(EntryGenerator generator, int numberOfUsers) throws Exception {
+ try {
+ generator.readEntry(); // skip top entry
+ generator.readEntry(); // skip ou entry
+ Entry entry = generator.readEntry();
+ assertThat(entry.getName().toString()).isEqualTo("uid=user.0,ou=People,dc=example,dc=com");
+
+ checkPresenceOfAttributes(entry, "givenName", "sn", "cn", "initials",
+ "employeeNumber", "uid", "mail", "userPassword", "telephoneNumber",
+ "homePhone", "pager", "mobile", "street", "l", "st", "postalCode",
+ "postalAddress", "description");
+ assertThat(entry.getAttribute("cn").firstValueAsString()).isEqualTo(
+ entry.getAttribute("givenName").firstValueAsString() + " "
+ + entry.getAttribute("sn").firstValueAsString());
+
+ checkEntryObjectClasses(entry, "top", "person", "organizationalPerson", "inetOrgPerson");
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
+ }
+
+ private void checkEntryObjectClasses(Entry entry, String...objectClasses) {
+ Attribute ocAttribute = entry.getAttribute(getObjectClassAttributeType().getNameOrOID());
+ assertThat(ocAttribute).isNotNull();
+ Iterator<ByteString> it = ocAttribute.iterator();
+ for (int i = 0; i < objectClasses.length; i++) {
+ assertThat(it.next().toString()).isEqualTo(objectClasses[i]);
+ }
+ assertThat(it.hasNext()).isFalse();
+ }
+
+ private void checkPresenceOfAttributes(Entry entry, String... attributes) {
+ for (int i = 0; i < attributes.length; i++) {
+ assertThat(entry.getAttribute(attributes[i])).isNotNull();
+ }
+ }
+
+ /**
+ * Test a template with subtemplates, ensuring all expected DNs are generated.
+ */
+ @Test
+ public void testTemplateWithSubTemplates() throws Exception {
+ int numberOfUsers = 10;
+ int numberOfGroups = 5;
+ int numberOfOUs = 10;
+ EntryGenerator generator = new EntryGenerator(
+ "define suffix=dc=example,dc=com",
+ "define maildomain=example.com",
+ "define numusers=" + numberOfUsers,
+ "define numous=" + numberOfOUs,
+ "define numgroup=" + numberOfGroups,
+ "",
+ "branch: [suffix]",
+ "subordinateTemplate: ous:[numous]",
+ "",
+ "template: ous",
+ "subordinateTemplate: People:1",
+ "subordinateTemplate: Groups:1",
+ "rdnAttr: ou",
+ "objectclass: top",
+ "objectclass: organizationalUnit",
+ "ou: Organization_<sequential:1>",
+ "",
+ "template: People",
+ "rdnAttr: ou",
+ "subordinateTemplate: person:[numusers]",
+ "objectclass: top",
+ "objectclass: organizationalUnit",
+ "ou: People",
+ "",
+ "template: Groups",
+ "subordinateTemplate: groupOfName:[numgroup]",
+ "rdnAttr: ou",
+ "objectclass: top",
+ "objectclass: organizationalUnit",
+ "ou: Groups",
+ "",
+ "template: person",
+ "rdnAttr: uid",
+ "objectClass: top",
+ "objectClass: inetOrgPerson",
+ "cn: <first> <last>",
+ "employeeNumber: <sequential:0>",
+ "uid: user.{employeeNumber}",
+ "",
+ "template: groupOfName",
+ "rdnAttr: cn",
+ "objectClass: top",
+ "objectClass: groupOfNames",
+ "cn: Group_<sequential:1>"
+ ).setResourcePath(resourcePath);
+
+ try {
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("dc=example,dc=com");
+ int countUsers = 0;
+ int countGroups = 1;
+ for (int i = 1; i <= numberOfOUs; i++) {
+ String dnOU = "ou=Organization_" + i + ",dc=example,dc=com";
+ assertThat(generator.readEntry().getName().toString()).isEqualTo(dnOU);
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("ou=People," + dnOU);
+ for (int j = countUsers; j < countUsers + numberOfUsers; j++) {
+ assertThat(generator.readEntry().getName().toString()).isEqualTo(
+ "uid=user." + j + ",ou=People," + dnOU);
+
+ }
+ countUsers += numberOfUsers;
+ assertThat(generator.readEntry().getName().toString()).isEqualTo("ou=Groups," + dnOU);
+ for (int j = countGroups; j < countGroups + numberOfGroups; j++) {
+ assertThat(generator.readEntry().getName().toString()).isEqualTo(
+ "cn=Group_" + j + ",ou=Groups," + dnOU);
+ }
+ countGroups += numberOfGroups;
+ }
+ assertThat(generator.hasNext()).isFalse();
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
}
/**
@@ -160,7 +372,7 @@
* generating templates reports the correct line.
*/
@Test()
- public void testParseFileTemplate() throws Exception {
+ public void testMissingVariableErrorReport() throws Exception {
String[] lines = {
/* 0 */"template: template",
/* 1 */"a: {missingVar}",
@@ -172,7 +384,7 @@
// Test must show "missingVar" missing on line 1.
// Previous behaviour showed "missingVar" on line 5.
- TemplateFile templateFile = new TemplateFile(schema, resourcePath);
+ TemplateFile templateFile = new TemplateFile(schema, null, resourcePath);
List<LocalizableMessage> warns = new ArrayList<LocalizableMessage>();
try {
@@ -218,7 +430,7 @@
*/
@Test(dataProvider = "validTemplates")
public void testParsingEscapeCharInTemplate(String testName, String[] lines) throws Exception {
- TemplateFile templateFile = new TemplateFile(schema, resourcePath);
+ TemplateFile templateFile = new TemplateFile(schema, null, resourcePath);
List<LocalizableMessage> warns = new ArrayList<LocalizableMessage>();
templateFile.parse(lines, warns);
assertThat(warns).isEmpty();
@@ -367,14 +579,18 @@
@Test(dataProvider = "templatesToTestEscapeChars", dependsOnMethods = { "testParsingEscapeCharInTemplate" })
public void testEscapeCharsFromTemplate(String testName, String[] lines, String attrName, String expectedValue)
throws Exception {
- EntryGenerator reader = newReader(lines).setResourcePath(resourcePath).build();
- Entry topEntry = reader.readEntry();
- Entry entry = reader.readEntry();
- reader.close();
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator(lines).setResourcePath(resourcePath);
+ Entry topEntry = generator.readEntry();
+ Entry entry = generator.readEntry();
- assertThat(topEntry).isNotNull();
- assertThat(entry).isNotNull();
- assertThat(entry.getAttribute(attrName).firstValueAsString()).isEqualTo(expectedValue);
+ assertThat(topEntry).isNotNull();
+ assertThat(entry).isNotNull();
+ assertThat(entry.getAttribute(attrName).firstValueAsString()).isEqualTo(expectedValue);
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
}
/**
@@ -394,15 +610,19 @@
// The value below combines variable, randoms and escaped chars.
// The resulting value is "Foo <?>{1}Bar" where ? is a letter
// from [A-Z].
- "cn: Foo \\<<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>\\>\\{1\\}{sn}", "", };
+ "cn: Foo \\<<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>\\>\\{1\\}{sn}",
+ "" };
+ EntryGenerator generator = null;
+ try {
+ generator = new EntryGenerator(lines).setResourcePath(resourcePath);
+ Entry topEntry = generator.readEntry();
+ Entry entry = generator.readEntry();
- EntryGenerator reader = newReader(lines).setResourcePath(resourcePath).build();
- Entry topEntry = reader.readEntry();
- Entry entry = reader.readEntry();
- reader.close();
-
- assertThat(topEntry).isNotNull();
- assertThat(entry).isNotNull();
- assertThat(entry.getAttribute("cn").firstValueAsString()).matches("Foo <[A-Z]>\\{1\\}Bar");
+ assertThat(topEntry).isNotNull();
+ assertThat(entry).isNotNull();
+ assertThat(entry.getAttribute("cn").firstValueAsString()).matches("Foo <[A-Z]>\\{1\\}Bar");
+ } finally {
+ StaticUtils.closeSilently(generator);
+ }
}
}
diff --git a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/TemplateTagTestcase.java b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/TemplateTagTestcase.java
new file mode 100644
index 0000000..d838a2d
--- /dev/null
+++ b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/ldif/TemplateTagTestcase.java
@@ -0,0 +1,293 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2013 ForgeRock AS.
+ */
+package org.forgerock.opendj.ldif;
+
+import static org.fest.assertions.Assertions.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.SdkTestCase;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldif.TemplateFile.Template;
+import org.forgerock.opendj.ldif.TemplateFile.TemplateEntry;
+import org.forgerock.opendj.ldif.TemplateFile.TemplateLine;
+import org.forgerock.opendj.ldif.TemplateFile.TemplateValue;
+import org.forgerock.opendj.ldif.TemplateTag.AttributeValueTag;
+import org.forgerock.opendj.ldif.TemplateTag.IfAbsentTag;
+import org.forgerock.opendj.ldif.TemplateTag.IfPresentTag;
+import org.forgerock.opendj.ldif.TemplateTag.TagResult;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class TemplateTagTestcase extends SdkTestCase {
+
+ private static final int LINE_NUMBER = 10;
+ private static final TemplateFile NULL_TEMPLATE_FILE = null;
+ private static final List<LocalizableMessage> NULL_WARNINGS = null;
+ private static final TemplateValue NULL_VALUE = null;
+ private static final TemplateLine NULL_LINE = null;
+
+ @Test
+ public void testIfAbsentTag() throws Exception {
+ TemplateTag tag = new IfAbsentTag();
+ String org = "org";
+ tagWithArguments(tag, "dc", org); // dc=org should be absent
+
+ // org value is absent
+ assertThat(tag.generateValue(templateEntry("v1", "v2"), NULL_VALUE)).isEqualTo(TagResult.SUCCESS);
+
+ // org value is present
+ assertThat(tag.generateValue(templateEntry(org, "v"), NULL_VALUE)).isEqualTo(TagResult.FAILURE);
+ assertThat(tag.generateValue(templateEntry("v", org), NULL_VALUE)).isEqualTo(TagResult.FAILURE);
+ assertThat(tag.generateValue(templateEntry(org), NULL_VALUE)).isEqualTo(TagResult.FAILURE);
+ }
+
+ @Test
+ public void testIfAbsentTagWithNoValue() throws Exception {
+ TemplateTag tag = new IfAbsentTag();
+ tagWithArguments(tag, "dc"); // dc should be absent
+
+ assertThat(tag.generateValue(templateEntry("v"), NULL_VALUE)).isEqualTo(TagResult.FAILURE);
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Invalid number of arguments.*")
+ public void testIfAbsentTagTooManyArguments() throws Exception {
+ tagWithArguments(new IfAbsentTag(), "dc", "org1", "org2"); // too many args
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Invalid number of arguments.*")
+ public void testIfAbsentTagNotEnoughArguments() throws Exception {
+ tagWithArguments(new IfAbsentTag()); // zero args
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Undefined attribute.*")
+ public void testIfAbsentTagNoAttribute() throws Exception {
+ tagWithArguments(new IfAbsentTag(), templateWithNoAttribute(), "dc");
+ }
+
+ @Test
+ public void testDNTagRootDN() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag);
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.rootDN()), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("");
+ }
+
+ @Test
+ public void testDNTagZeroComponent() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag);
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("ou=users,dc=example,dc=test");
+ }
+
+ @Test
+ public void testUnderscoreDNTagZeroComponent() throws Exception {
+ TemplateTag tag = new TemplateTag.UnderscoreDNTag();
+ tagWithArguments(tag);
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("ou=users_dc=example_dc=test");
+ }
+
+ @Test
+ public void testDNTagOneComponent() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag, "1");
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("ou=users");
+ }
+
+ @Test
+ public void testDNTagTwoComponent() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag, "2");
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("ou=users,dc=example");
+ }
+
+ @Test
+ public void testDNTagMinusOneComponent() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag, "-1");
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("dc=test");
+ }
+
+ @Test
+ public void testDNTagMinusTwoComponents() throws Exception {
+ TemplateTag tag = new TemplateTag.DNTag();
+ tagWithArguments(tag, "-2");
+
+ TemplateValue value = new TemplateValue(NULL_LINE);
+ tag.generateValue(templateEntry(DN.valueOf("ou=users,dc=example,dc=test")), value);
+
+ assertThat(value.getValueAsString()).isEqualTo("dc=example,dc=test");
+ }
+
+ @Test
+ public void testIfPresentTag() throws Exception {
+ TemplateTag tag = new TemplateTag.IfPresentTag();
+ String org = "org";
+ tagWithArguments(tag, "dc", org); // dc=org should be present
+
+ // org value is absent
+ assertThat(tag.generateValue(templateEntry("v1", "v2"), NULL_VALUE)).isEqualTo(TagResult.FAILURE);
+
+ // org value is present
+ assertThat(tag.generateValue(templateEntry(org, "v"), NULL_VALUE)).isEqualTo(TagResult.SUCCESS);
+ assertThat(tag.generateValue(templateEntry("v", org), NULL_VALUE)).isEqualTo(TagResult.SUCCESS);
+ assertThat(tag.generateValue(templateEntry(org), NULL_VALUE)).isEqualTo(TagResult.SUCCESS);
+ }
+
+ @Test
+ public void testIfPresentTagWithNoValue() throws Exception {
+ TemplateTag tag = new TemplateTag.IfPresentTag();
+ tagWithArguments(tag, "dc"); // dc=org should be present
+
+ assertThat(tag.generateValue(templateEntry("org"), NULL_VALUE)).isEqualTo(TagResult.SUCCESS);
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Invalid number of arguments.*")
+ public void testIfPresentTagTooManyArguments() throws Exception {
+ tagWithArguments(new IfPresentTag(), "1", "2", "3"); // too many args
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Invalid number of arguments.*")
+ public void testIfPresentTagNotEnoughArguments() throws Exception {
+ tagWithArguments(new IfPresentTag()); // zero args
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Undefined attribute.*")
+ public void testIfPresentTagNoAttribute() throws Exception {
+ tagWithArguments(new IfPresentTag(), templateWithNoAttribute(), "dc");
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Invalid number of arguments.*")
+ public void testAttributeValueTagTooManyArguments() throws Exception {
+ tagWithArguments(new AttributeValueTag(), "dc", "2", "3"); // too many args
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*below the lowest allowed value.*")
+ public void testAttributeValueTagBelowLowerBound() throws Exception {
+ tagWithArguments(new AttributeValueTag(), "dc", "-1");
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Cannot parse value.*")
+ public void testAttributeValueTagNotANumber() throws Exception {
+ tagWithArguments(new AttributeValueTag(), "dc", "notanumber");
+ }
+
+ @Test(expectedExceptions = DecodeException.class,
+ expectedExceptionsMessageRegExp = ".*Undefined attribute.*")
+ public void testAttributeValueTagNoAttribute() throws Exception {
+ tagWithArguments(new AttributeValueTag(), templateWithNoAttribute(), "dc");
+ }
+
+ /** Helper method to initialize tags with template having any attribute and some arguments*/
+ private void tagWithArguments(TemplateTag tag, String... arguments) throws DecodeException {
+ tagWithArguments(tag, templateWithAnyAttribute(), arguments);
+ }
+
+ /** Helper method to initialize tags with template and some arguments*/
+ private void tagWithArguments(TemplateTag tag, Template template, String... arguments)
+ throws DecodeException {
+ tag.initializeForTemplate(Schema.getDefaultSchema(), NULL_TEMPLATE_FILE, template,
+ arguments, LINE_NUMBER, NULL_WARNINGS);
+ }
+
+ /** Helper method to build a template entry containing the provided values. */
+ private TemplateEntry templateEntry(String... values) {
+ TemplateEntry templateEntry = mock(TemplateEntry.class);
+ List<TemplateValue> templateValues = new ArrayList<TemplateValue>();
+ for (String value : values) {
+ templateValues.add(templateValue(value));
+ }
+ when(templateEntry.getValues(any(AttributeType.class))).thenReturn(templateValues);
+ return templateEntry;
+ }
+
+ /** Helper method to build a template entry with the provided DN. */
+ private TemplateEntry templateEntry(DN dn) {
+ TemplateEntry templateEntry = mock(TemplateEntry.class);
+ when(templateEntry.getDN()).thenReturn(dn);
+ return templateEntry;
+ }
+
+ /** Helper method to build a template value from provided string. */
+ private TemplateValue templateValue(String value) {
+ TemplateValue templateVal = new TemplateFile.TemplateValue(null);
+ templateVal.append(value);
+ return templateVal;
+ }
+
+ /** Helper method to build a template that always return true on attribute type check */
+ private Template templateWithAnyAttribute() {
+ Template template = mock(Template.class);
+ when(template.hasAttribute(any(AttributeType.class))).thenReturn(true);
+ return template;
+ }
+
+ /** Helper method to build a template that always return false on attribute type check */
+ private Template templateWithNoAttribute() {
+ Template template = mock(Template.class);
+ when(template.hasAttribute(any(AttributeType.class))).thenReturn(false);
+ return template;
+ }
+}
--
Gitblit v1.10.0