001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2015-2016 ForgeRock AS.
016 */
017package org.opends.guitools.controlpanel.datamodel;
018
019import static org.opends.server.backends.pluggable.SuffixContainer.*;
020
021import java.util.Collections;
022import java.util.Set;
023import java.util.SortedSet;
024import java.util.TreeSet;
025
026import org.forgerock.opendj.ldap.schema.AttributeType;
027import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn.IndexType;
028
029/**
030 * The class used to describe the index configuration (the normal index: the one
031 * used to improve search performance on a given attribute).
032 */
033public class IndexDescriptor extends AbstractIndexDescriptor
034{
035
036  private static final String[] DATABASE_INDEXES = new String[] {
037    DN2ID_INDEX_NAME, ID2CHILDREN_COUNT_NAME, ID2CHILDREN_INDEX_NAME, ID2SUBTREE_INDEX_NAME };
038
039  private final SortedSet<IndexType> types = new TreeSet<>();
040  private final boolean isDatabaseIndex;
041  private final int entryLimit;
042  private final AttributeType attr;
043  private int hashCode;
044
045  /**
046   * Constructor of the index descriptor.
047   *
048   * @param indexName
049   *          name of the index.
050   */
051  public IndexDescriptor(String indexName)
052  {
053    this(indexName, null, null, Collections.EMPTY_SET, -1);
054  }
055
056  /**
057   * Constructor of the index descriptor.
058   *
059   * @param name
060   *          name of the index.
061   * @param attr
062   *          the attribute type associated with the index attribute.
063   * @param backend
064   *          the backend where the index is defined.
065   * @param types
066   *          the type of indexes (equality, substring, etc.).
067   * @param entryLimit
068   *          the entry limit for the index.
069   */
070  public IndexDescriptor(
071      String name, AttributeType attr, BackendDescriptor backend, Set<IndexType> types, int entryLimit)
072  {
073    super(name, backend);
074    this.attr = attr;
075    this.types.addAll(types);
076    isDatabaseIndex = isDatabaseIndex(name);
077    this.entryLimit = entryLimit;
078    recalculateHashCode();
079  }
080
081  /**
082   * Returns the attribute type associated with the index attribute.
083   *
084   * @return the attribute type associated with the index attribute.
085   */
086  public AttributeType getAttributeType()
087  {
088    return attr;
089  }
090
091  @Override
092  public int compareTo(AbstractIndexDescriptor o)
093  {
094    return getName().toLowerCase().compareTo(o.getName().toLowerCase());
095  }
096
097  @Override
098  public int hashCode()
099  {
100    return hashCode;
101  }
102
103  /**
104   * Returns the type of indexes (equality, substring, etc.).
105   *
106   * @return the type of indexes (equality, substring, etc.).
107   */
108  public SortedSet<IndexType> getTypes()
109  {
110    return new TreeSet<>(types);
111  }
112
113  /**
114   * Tells whether this is a database index or not. Database indexes are not
115   * modifiable and for internal use only.
116   *
117   * @return <CODE>true</CODE> if this is a database index and
118   *         <CODE>false</CODE> otherwise.
119   */
120  public boolean isDatabaseIndex()
121  {
122    return isDatabaseIndex;
123  }
124
125  /**
126   * Tells whether the provide index name corresponds to a database index or
127   * not. Database indexes are not modifiable and for internal use only.
128   *
129   * @return <CODE>true</CODE> if the provide index name corresponds to a
130   *         database index and <CODE>false</CODE> otherwise.
131   */
132  private boolean isDatabaseIndex(final String indexName)
133  {
134    for (final String dbIndex : DATABASE_INDEXES)
135    {
136      if (indexName.equalsIgnoreCase(dbIndex))
137      {
138        return true;
139      }
140    }
141    return false;
142  }
143
144  @Override
145  public boolean equals(Object o)
146  {
147    if (o == this)
148    {
149      return true;
150    }
151    if (!(o instanceof IndexDescriptor))
152    {
153      return false;
154    }
155    final IndexDescriptor index = (IndexDescriptor)o;
156    return index.getName().equalsIgnoreCase(getName())
157        && index.isDatabaseIndex() == isDatabaseIndex()
158        && index.getTypes().equals(getTypes())
159        && index.getEntryLimit() == getEntryLimit()
160        && backendIdEqual(index);
161  }
162
163  private boolean backendIdEqual(IndexDescriptor index)
164  {
165    BackendDescriptor backend1 = getBackend();
166    BackendDescriptor backend2 = index.getBackend();
167    return backend1 != null && backend2 != null && backend1.getBackendID().equals(backend2.getBackendID());
168  }
169
170  /**
171   * Returns the entry limit of the index.
172   *
173   * @return the entry limit of the index.
174   */
175  public int getEntryLimit()
176  {
177    return entryLimit;
178  }
179
180  @Override
181  protected void recalculateHashCode()
182  {
183    final StringBuilder sb = new StringBuilder();
184    for (final IndexType t : types)
185    {
186      sb.append(t).append(",");
187    }
188    if (getBackend() != null)
189    {
190      sb.append(getBackend().getBackendID());
191    }
192    hashCode = (getName()+sb+entryLimit).hashCode();
193  }
194}