001/*
002 * Copyright 2017-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2017-2019 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util.args;
022
023
024
025import java.io.Serializable;
026import java.util.List;
027
028import com.unboundid.util.NotMutable;
029import com.unboundid.util.OID;
030import com.unboundid.util.ThreadSafety;
031import com.unboundid.util.ThreadSafetyLevel;
032
033import static com.unboundid.util.args.ArgsMessages.*;
034
035
036
037/**
038 * This class provides an implementation of an argument value validator that
039 * ensures that values can be parsed as valid object identifiers.
040 */
041@NotMutable()
042@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
043public final class OIDArgumentValueValidator
044       extends ArgumentValueValidator
045       implements Serializable
046{
047  /**
048   * The serial version UID for this serializable class.
049   */
050  private static final long serialVersionUID = 2195078137238476902L;
051
052
053
054  // Indicates whether to perform strict validation.
055  private final boolean isStrict;
056
057
058
059  /**
060   * Creates a new OID address argument value validator that will only accept
061   * strictly valid numeric OIDs.
062   */
063  public OIDArgumentValueValidator()
064  {
065    this(true);
066  }
067
068
069
070  /**
071   * Creates a new OID address argument value validator that will only accept
072   * valid numeric OIDs.
073   *
074   * @param  isStrict  Indicates whether to perform strict validation.  If this
075   *                   is {@code false}, then the validator will only sure that
076   *                   each value is a dotted list of digits that does not start
077   *                   or end with a period and does not contain two consecutive
078   *                   periods.  If this is {@code true}, then it will also
079   *                   ensure that it contains at least two components, that the
080   *                   value of the first component is not greater than two,
081   *                   and that the value of the second component is not greater
082   *                   than 39 if the value of the first component is zero or
083   *                   one.
084   */
085  public OIDArgumentValueValidator(final boolean isStrict)
086  {
087    this.isStrict = isStrict;
088  }
089
090
091
092  /**
093   * Indicates whether this validator is configured to operate in strict mode.
094   * If it not operating in strict mode, then it will only ensure that each
095   * value is is a dotted list of digits that does not start or end with a
096   * period and does not contain two consecutive periods.  If it is strict, then
097   * it will also ensure that it contains at least two components, that the
098   * value of the first component is not greater than two, and that the value of
099   * the second component is not greater than 39 if the value of the first
100   * component is zero or one.
101   *
102   * @return  {@code true} if this validator is configured to operate in strict
103   *          mode, or {@code false} if not.
104   */
105  public boolean isStrict()
106  {
107    return isStrict;
108  }
109
110
111
112  /**
113   * {@inheritDoc}
114   */
115  @Override()
116  public void validateArgumentValue(final Argument argument,
117                                    final String valueString)
118         throws ArgumentException
119  {
120    if (valueString.isEmpty())
121    {
122      throw new ArgumentException(ERR_OID_VALIDATOR_EMPTY.get(valueString,
123           argument.getIdentifierString()));
124    }
125
126    if (valueString.startsWith(".") || valueString.endsWith("."))
127    {
128      throw new ArgumentException(
129           ERR_OID_VALIDATOR_STARTS_OR_ENDS_WITH_PERIOD.get(valueString,
130                argument.getIdentifierString()));
131    }
132
133    if (valueString.contains(".."))
134    {
135      throw new ArgumentException(
136           ERR_OID_VALIDATOR_CONSECUTIVE_PERIODS.get(valueString,
137                argument.getIdentifierString()));
138    }
139
140    final OID oid = new OID(valueString);
141    if (! oid.isValidNumericOID())
142    {
143      throw new ArgumentException(
144           ERR_OID_VALIDATOR_ILLEGAL_CHARACTER.get(valueString,
145                argument.getIdentifierString()));
146    }
147
148    if (! isStrict)
149    {
150      return;
151    }
152
153    final List<Integer> components = oid.getComponents();
154    if (components.size() < 2)
155    {
156      throw new ArgumentException(
157           ERR_OID_VALIDATOR_NOT_ENOUGH_COMPONENTS.get(valueString,
158                argument.getIdentifierString()));
159    }
160
161    final int firstComponent = components.get(0);
162    final int secondComponent = components.get(1);
163    switch (firstComponent)
164    {
165      case 0:
166      case 1:
167        if (secondComponent > 39)
168        {
169          throw new ArgumentException(
170               ERR_OID_VALIDATOR_ILLEGAL_SECOND_COMPONENT.get(valueString,
171                    argument.getIdentifierString()));
172        }
173        break;
174
175      case 2:
176        // We don't need to do any more validation.
177        break;
178
179      default:
180        // Invalid value for the first component.
181        throw new ArgumentException(
182             ERR_OID_VALIDATOR_ILLEGAL_FIRST_COMPONENT.get(valueString,
183                  argument.getIdentifierString()));
184    }
185  }
186
187
188
189  /**
190   * Retrieves a string representation of this argument value validator.
191   *
192   * @return  A string representation of this argument value validator.
193   */
194  @Override()
195  public String toString()
196  {
197    final StringBuilder buffer = new StringBuilder();
198    toString(buffer);
199    return buffer.toString();
200  }
201
202
203
204  /**
205   * Appends a string representation of this argument value validator to the
206   * provided buffer.
207   *
208   * @param  buffer  The buffer to which the string representation should be
209   *                 appended.
210   */
211  public void toString(final StringBuilder buffer)
212  {
213    buffer.append("OIDArgumentValueValidator(isStrict=");
214    buffer.append(isStrict);
215    buffer.append(')');
216  }
217}