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 2006-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017package org.opends.server.replication.plugin;
018
019import static org.forgerock.util.Reject.*;
020
021import org.forgerock.opendj.ldap.ByteString;
022import org.forgerock.opendj.ldap.DecodeException;
023import org.forgerock.opendj.ldap.schema.AttributeType;
024import org.opends.server.replication.common.CSN;
025
026/** AttrValueHistorical is the historical information of the modification of one attribute value. */
027public class AttrValueHistorical
028{
029  private AttributeType attributeType;
030  private ByteString value;
031  private ByteString normalizedValue;
032  private CSN valueDeleteTime;
033  private CSN valueUpdateTime;
034
035  /**
036   * Build an AttrValueHistorical for a provided attribute value, providing
037   * the last time the provided value is either updated or deleted.
038   * @param value    the provided attribute value
039   * @param attributeType the provided attribute type
040   * @param csnUpdate last time when this value was updated
041   * @param csnDelete last time when this value for deleted
042   */
043  public AttrValueHistorical(ByteString value, AttributeType attributeType, CSN csnUpdate, CSN csnDelete)
044  {
045    this.value = value;
046    this.attributeType = checkNotNull(attributeType);
047    this.valueUpdateTime = csnUpdate;
048    this.valueDeleteTime = csnDelete;
049  }
050
051  @Override
052  public boolean equals(Object obj)
053  {
054    if (obj instanceof AttrValueHistorical)
055    {
056      AttrValueHistorical objVal = (AttrValueHistorical) obj;
057      try
058      {
059        return getNormalizedValue().equals(objVal.getNormalizedValue());
060      }
061      catch (DecodeException e)
062      {
063        return value.equals(objVal.getAttributeValue());
064      }
065    }
066    return false;
067  }
068
069  @Override
070  public int hashCode()
071  {
072    try
073    {
074      return getNormalizedValue().hashCode();
075    }
076    catch (DecodeException e)
077    {
078      return value.hashCode();
079    }
080  }
081
082  private ByteString getNormalizedValue() throws DecodeException
083  {
084    if (normalizedValue == null)
085    {
086      normalizedValue = attributeType.getEqualityMatchingRule().normalizeAttributeValue(value);
087    }
088    return normalizedValue;
089  }
090
091  /**
092   * Get the last time when the value was deleted.
093   * @return the last time when the value was deleted
094   */
095  public CSN getValueDeleteTime()
096  {
097    return valueDeleteTime;
098  }
099
100  /**
101   * Get the last time when the value was updated.
102   * @return the last time when the value was updated
103   */
104  public CSN getValueUpdateTime()
105  {
106    return valueUpdateTime;
107  }
108
109  /**
110   * Get the attributeValue for which this object was generated.
111   * @return the value for which this object was generated
112   */
113  public ByteString getAttributeValue()
114  {
115    return value;
116  }
117
118  /**
119   * Check if the value associated with this object was updated.
120   * @return true if the value associated with this object was updated
121   */
122  public boolean isUpdate()
123  {
124    return valueUpdateTime != null;
125  }
126
127  @Override
128  public String toString()
129  {
130    if (valueUpdateTime != null)
131    {
132      return valueDeleteTime != null
133          // valueUpdateTime and valueDeleteTime should have the same value
134          ? valueUpdateTime + ":replace:" + value
135          : valueUpdateTime + ":add:" + value;
136    }
137    else
138    {
139      return valueDeleteTime != null
140          ? valueDeleteTime + ":delete:" + value
141          : "????:" + value;
142    }
143  }
144}