001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.tools.makeldif;
028import org.forgerock.i18n.LocalizableMessage;
029
030
031
032import java.io.File;
033import java.io.IOException;
034import java.util.List;
035import java.util.Random;
036
037import org.opends.server.types.InitializationException;
038
039import static org.opends.messages.ToolMessages.*;
040
041
042
043/**
044 * This class defines a tag that is used provide values from a text file.  The
045 * file should have one value per line.  Access to the values may be either at
046 * random or in sequential order.
047 */
048public class FileTag
049       extends Tag
050{
051  /** Indicates whether the values should be selected sequentially or at random. */
052  private boolean sequential;
053
054  /** The file containing the data. */
055  private File dataFile;
056
057  /** The index used for sequential access. */
058  private int nextIndex;
059
060  /** The random number generator for this tag. */
061  private Random random;
062
063  /** The array of lines read from the file. */
064  private String[] fileLines;
065
066
067
068  /**
069   * Creates a new instance of this file tag.
070   */
071  public FileTag()
072  {
073    sequential = false;
074    dataFile   = null;
075    nextIndex  = 0;
076    random     = null;
077    fileLines  = null;
078  }
079
080
081
082  /**
083   * Retrieves the name for this tag.
084   *
085   * @return  The name for this tag.
086   */
087  public String getName()
088  {
089    return "File";
090  }
091
092
093
094  /**
095   * Indicates whether this tag is allowed for use in the extra lines for
096   * branches.
097   *
098   * @return  <CODE>true</CODE> if this tag may be used in branch definitions,
099   *          or <CODE>false</CODE> if not.
100   */
101  public boolean allowedInBranch()
102  {
103    return true;
104  }
105
106
107
108  /**
109   * Performs any initialization for this tag that may be needed while parsing
110   * a branch definition.
111   *
112   * @param  templateFile  The template file in which this tag is used.
113   * @param  branch        The branch in which this tag is used.
114   * @param  arguments     The set of arguments provided for this tag.
115   * @param  lineNumber    The line number on which this tag appears in the
116   *                       template file.
117   * @param  warnings      A list into which any appropriate warning messages
118   *                       may be placed.
119   *
120   * @throws  InitializationException  If a problem occurs while initializing
121   *                                   this tag.
122   */
123  public void initializeForBranch(TemplateFile templateFile, Branch branch,
124                                  String[] arguments, int lineNumber,
125                                  List<LocalizableMessage> warnings)
126         throws InitializationException
127  {
128    initializeInternal(templateFile, arguments, lineNumber, warnings);
129  }
130
131
132
133  /**
134   * Performs any initialization for this tag that may be needed while parsing
135   * a template definition.
136   *
137   * @param  templateFile  The template file in which this tag is used.
138   * @param  template      The template in which this tag is used.
139   * @param  arguments     The set of arguments provided for this tag.
140   * @param  lineNumber    The line number on which this tag appears in the
141   *                       template file.
142   * @param  warnings      A list into which any appropriate warning messages
143   *                       may be placed.
144   *
145   * @throws  InitializationException  If a problem occurs while initializing
146   *                                   this tag.
147   */
148  public void initializeForTemplate(TemplateFile templateFile,
149                                    Template template, String[] arguments,
150                                    int lineNumber, List<LocalizableMessage> warnings)
151         throws InitializationException
152  {
153    initializeInternal(templateFile, arguments, lineNumber, warnings);
154  }
155
156
157
158  /**
159   * Performs any initialization for this tag that may be needed.
160   *
161   * @param  templateFile  The template file in which this tag is used.
162   * @param  arguments     The set of arguments provided for this tag.
163   * @param  lineNumber    The line number on which this tag appears in the
164   *                       template file.
165   * @param  warnings      A list into which any appropriate warning messages
166   *                       may be placed.
167   *
168   * @throws  InitializationException  If a problem occurs while initializing
169   *                                   this tag.
170   */
171  private void initializeInternal(TemplateFile templateFile, String[] arguments,
172                                  int lineNumber, List<LocalizableMessage> warnings)
173          throws InitializationException
174  {
175    random = templateFile.getRandom();
176
177
178    // There must be at least one argument, and possibly two.
179    if (arguments.length < 1 || arguments.length > 2)
180    {
181      LocalizableMessage message = ERR_MAKELDIF_TAG_INVALID_ARGUMENT_RANGE_COUNT.get(
182          getName(), lineNumber, 1, 2, arguments.length);
183      throw new InitializationException(message);
184    }
185
186
187    // The first argument should be the path to the file.
188    dataFile = templateFile.getFile(arguments[0]);
189    if (dataFile == null || !dataFile.exists())
190    {
191      LocalizableMessage message = ERR_MAKELDIF_TAG_CANNOT_FIND_FILE.get(
192          arguments[0], getName(), lineNumber);
193      throw new InitializationException(message);
194    }
195
196
197    // If there is a second argument, then it should be either "sequential" or
198    // "random".  If there isn't one, then we should assume "random".
199    if (arguments.length == 2)
200    {
201      if (arguments[1].equalsIgnoreCase("sequential"))
202      {
203        sequential = true;
204        nextIndex  = 0;
205      }
206      else if (arguments[1].equalsIgnoreCase("random"))
207      {
208        sequential = false;
209      }
210      else
211      {
212        LocalizableMessage message = ERR_MAKELDIF_TAG_INVALID_FILE_ACCESS_MODE.get(
213            arguments[1], getName(), lineNumber);
214        throw new InitializationException(message);
215      }
216    }
217    else
218    {
219      sequential = false;
220    }
221
222
223    // See if the file has already been read into memory.  If not, then read it.
224    try
225    {
226      fileLines = templateFile.getFileLines(dataFile);
227    }
228    catch (IOException ioe)
229    {
230      LocalizableMessage message = ERR_MAKELDIF_TAG_CANNOT_READ_FILE.get(
231          arguments[0], getName(), lineNumber, ioe);
232      throw new InitializationException(message, ioe);
233    }
234  }
235
236
237
238  /**
239   * Generates the content for this tag by appending it to the provided tag.
240   *
241   * @param  templateEntry  The entry for which this tag is being generated.
242   * @param  templateValue  The template value to which the generated content
243   *                        should be appended.
244   *
245   * @return  The result of generating content for this tag.
246   */
247  public TagResult generateValue(TemplateEntry templateEntry,
248                                 TemplateValue templateValue)
249  {
250    if (sequential)
251    {
252      templateValue.append(fileLines[nextIndex++]);
253      if (nextIndex >= fileLines.length)
254      {
255        nextIndex = 0;
256      }
257    }
258    else
259    {
260      templateValue.append(fileLines[random.nextInt(fileLines.length)]);
261    }
262
263    return TagResult.SUCCESS_RESULT;
264  }
265}
266