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.types; 028 029import java.util.Collection; 030import java.util.Set; 031 032import org.forgerock.opendj.ldap.ByteString; 033import org.forgerock.opendj.ldap.DecodeException; 034import org.forgerock.opendj.ldap.schema.MatchingRule; 035 036/** An abstract base class for implementing new types of {@link Attribute}. */ 037@org.opends.server.types.PublicAPI( 038 stability = org.opends.server.types.StabilityLevel.UNCOMMITTED, 039 mayInstantiate = false, 040 mayExtend = false, 041 mayInvoke = true) 042public abstract class AbstractAttribute implements Attribute 043{ 044 /** Creates a new abstract attribute. */ 045 protected AbstractAttribute() 046 { 047 // No implementation required. 048 } 049 050 /** 051 * {@inheritDoc} 052 * <p> 053 * This implementation iterates through each attribute value in the 054 * provided collection, checking to see if this attribute contains 055 * the value using {@link #contains(ByteString)}. 056 */ 057 @Override 058 public boolean containsAll(Collection<ByteString> values) 059 { 060 for (ByteString value : values) 061 { 062 if (!contains(value)) 063 { 064 return false; 065 } 066 } 067 return true; 068 } 069 070 @Override 071 public final boolean equals(Object o) 072 { 073 if (this == o) 074 { 075 return true; 076 } 077 if (!(o instanceof Attribute)) 078 { 079 return false; 080 } 081 082 Attribute a = (Attribute) o; 083 return getAttributeType().equals(a.getAttributeType()) 084 && valuesEqual(a) 085 && optionsEqual(a.getOptions()); 086 } 087 088 private boolean valuesEqual(Attribute a) 089 { 090 if (size() != a.size()) 091 { 092 return false; 093 } 094 095 for (ByteString v : a) 096 { 097 if (!contains(v)) 098 { 099 return false; 100 } 101 } 102 return true; 103 } 104 105 /** 106 * {@inheritDoc} 107 * <p> 108 * This implementation returns the primary name associated with this 109 * attribute's attribute type or, if there is no primary name, the 110 * attribute type's OID. 111 */ 112 @Override 113 public String getName() 114 { 115 return getAttributeType().getNameOrOID(); 116 } 117 118 /** 119 * {@inheritDoc} 120 * <p> 121 * This implementation returns this attribute's name if there are no 122 * attribute options, otherwise it constructs a string comprising of 123 * this attribute's name followed by a semi-colon and a semi-colon 124 * separated list of its attribute options. 125 */ 126 @Override 127 public String getNameWithOptions() 128 { 129 if (!hasOptions()) 130 { 131 return getName(); 132 } 133 134 StringBuilder buffer = new StringBuilder(); 135 buffer.append(getName()); 136 for (String option : getOptions()) 137 { 138 buffer.append(';'); 139 buffer.append(option); 140 } 141 return buffer.toString(); 142 } 143 144 /** 145 * {@inheritDoc} 146 * <p> 147 * This implementation returns {@code true} if the provided 148 * collection of options is {@code null} or empty. If the 149 * collection is non-empty and this attribute does not have any 150 * options then it returns {@code false}. Otherwise, {@code true} is 151 * returned if all the provided options are present. 152 */ 153 @Override 154 public boolean hasAllOptions(Collection<String> options) 155 { 156 return AttributeDescription.containsAllOptions(getOptions(), options); 157 } 158 159 @Override 160 public int hashCode() 161 { 162 int hashCode = getAttributeType().hashCode(); 163 for (ByteString value : this) 164 { 165 try 166 { 167 MatchingRule eqRule = getAttributeType().getEqualityMatchingRule(); 168 hashCode += eqRule.normalizeAttributeValue(value).hashCode(); 169 } 170 catch (DecodeException e) 171 { 172 hashCode += value.hashCode(); 173 } 174 } 175 return hashCode; 176 } 177 178 /** 179 * {@inheritDoc} 180 * <p> 181 * This implementation calls {@link #getOptions()} to 182 * retrieve this attribute's set of options and then compares them 183 * one at a time against the provided option. All comparisons are 184 * case insensitive. 185 */ 186 @Override 187 public boolean hasOption(String option) 188 { 189 return AttributeDescription.containsOption(getOptions(), option); 190 } 191 192 /** 193 * {@inheritDoc} 194 * <p> 195 * This implementation retrieves the set of options associated with 196 * this attribute and tests to see if it is empty. 197 */ 198 @Override 199 public boolean hasOptions() 200 { 201 return !getOptions().isEmpty(); 202 } 203 204 /** 205 * {@inheritDoc} 206 * <p> 207 * This implementation returns <code>true</code> if the 208 * {@link #size()} of this attribute is zero. 209 */ 210 @Override 211 public boolean isEmpty() 212 { 213 return size() == 0; 214 } 215 216 @Override 217 public boolean isReal() 218 { 219 return !isVirtual(); 220 } 221 222 /** 223 * {@inheritDoc} 224 * <p> 225 * This implementation returns !{@link #hasOptions()} if the 226 * provided set of options is <code>null</code>. Otherwise it 227 * checks that the size of the provided set of options is equal to 228 * the size of this attribute's options, return <code>false</code> 229 * if the sizes differ. If the sizes are the same then each option 230 * in the provided set is checked using 231 * {@link #hasOption(String)} and <code>true</code> is 232 * returned if all the provided options are present. 233 */ 234 @Override 235 public boolean optionsEqual(Set<String> options) 236 { 237 if (options != null) 238 { 239 return getOptions().size() == options.size() 240 && hasAllOptions(options); 241 } 242 return !hasOptions(); 243 } 244 245 @Override 246 public final String toString() 247 { 248 StringBuilder buffer = new StringBuilder(); 249 toString(buffer); 250 return buffer.toString(); 251 } 252}