/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.studio.ldapbrowser.core.model.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.directory.api.ldap.model.constants.SchemaConstants; import org.apache.directory.api.ldap.model.schema.AttributeType; import org.apache.directory.studio.connection.core.Connection; import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages; import org.apache.directory.studio.ldapbrowser.core.events.EmptyValueAddedEvent; import org.apache.directory.studio.ldapbrowser.core.events.EmptyValueDeletedEvent; import org.apache.directory.studio.ldapbrowser.core.events.EntryModificationEvent; import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry; import org.apache.directory.studio.ldapbrowser.core.events.ValueAddedEvent; import org.apache.directory.studio.ldapbrowser.core.events.ValueDeletedEvent; import org.apache.directory.studio.ldapbrowser.core.events.ValueModifiedEvent; import org.apache.directory.studio.ldapbrowser.core.internal.search.LdapSearchPageScoreComputer; import org.apache.directory.studio.ldapbrowser.core.model.AttributeDescription; import org.apache.directory.studio.ldapbrowser.core.model.IAttribute; import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection; import org.apache.directory.studio.ldapbrowser.core.model.IEntry; import org.apache.directory.studio.ldapbrowser.core.model.IValue; import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils; import org.eclipse.search.ui.ISearchPageScoreComputer; /** * Default implementation of IAttribute. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class Attribute implements IAttribute { /** The serialVersionUID. */ private static final long serialVersionUID = -5679384884002589786L; /** The attribute description */ private AttributeDescription attributeDescription; /** The entry this attribute belongs to */ private IEntry entry; /** The values */ private List<IValue> valueList; /** * Creates an new instance of Attribute with the given description * and no value. * * @param entry * The entry of this attribute, mustn't be null * @param description * The attribute descrption, mustn't be null. */ public Attribute( IEntry entry, String description ) { assert entry != null; assert description != null; this.entry = entry; this.attributeDescription = new AttributeDescription( description ); this.valueList = new ArrayList<IValue>(); } /** * {@inheritDoc} */ public IEntry getEntry() { return entry; } /** * {@inheritDoc} */ public boolean isConsistent() { if ( valueList.isEmpty() ) { return false; } for ( IValue value : valueList ) { if ( value.isEmpty() ) { return false; } } return true; } /** * {@inheritDoc} */ public boolean isMustAttribute() { if ( isObjectClassAttribute() ) { return true; } else { Collection<AttributeType> mustAtds = SchemaUtils.getMustAttributeTypeDescriptions( entry ); return mustAtds.contains( getAttributeTypeDescription() ); } } /** * {@inheritDoc} */ public boolean isMayAttribute() { return !isObjectClassAttribute() && !isMustAttribute() && !isOperationalAttribute(); } /** * {@inheritDoc} */ public boolean isOperationalAttribute() { return getAttributeTypeDescription() == null || SchemaUtils.isOperational( getAttributeTypeDescription() ); } /** * {@inheritDoc} */ public boolean isObjectClassAttribute() { return SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( getDescription() ); } /** * {@inheritDoc} */ public boolean isString() { return !isBinary(); } /** * {@inheritDoc} */ public boolean isBinary() { return SchemaUtils.isBinary( getAttributeTypeDescription(), getEntry().getBrowserConnection().getSchema() ); } /** * {@inheritDoc} */ public void addEmptyValue() { IValue emptyValue = new Value( this ); valueList.add( emptyValue ); attributeModified( new EmptyValueAddedEvent( getEntry().getBrowserConnection(), getEntry(), this, emptyValue ) ); } /** * {@inheritDoc} */ public void deleteEmptyValue() { for ( Iterator<IValue> it = this.valueList.iterator(); it.hasNext(); ) { IValue value = it.next(); if ( value.isEmpty() ) { it.remove(); attributeModified( new EmptyValueDeletedEvent( getEntry().getBrowserConnection(), getEntry(), this, value ) ); return; } } } /** * Fires an EntryModificationEvent. * * @param event the EntryModificationEvent */ private void attributeModified( EntryModificationEvent event ) { EventRegistry.fireEntryUpdated( event, getEntry() ); } /** * Checks if the given value is valid. * * @param value the value to check * @throws IllegalArgumentException if the value is not valid */ private void checkValue( IValue value ) throws IllegalArgumentException { if ( value == null ) { throw new IllegalArgumentException( BrowserCoreMessages.model__empty_value ); } if ( !value.getAttribute().equals( this ) ) { throw new IllegalArgumentException( BrowserCoreMessages.model__values_attribute_is_not_myself ); } } /** * Deletes the given value from value list. * * @param valueToDelete the value to delete * @return true if deleted */ private boolean internalDeleteValue( IValue valueToDelete ) { for ( Iterator<IValue> it = valueList.iterator(); it.hasNext(); ) { IValue value = it.next(); if ( value.equals( valueToDelete ) ) { it.remove(); return true; } } return false; } /** * {@inheritDoc} */ public void addValue( IValue valueToAdd ) throws IllegalArgumentException { checkValue( valueToAdd ); valueList.add( valueToAdd ); attributeModified( new ValueAddedEvent( getEntry().getBrowserConnection(), getEntry(), this, valueToAdd ) ); } /** * {@inheritDoc} */ public void deleteValue( IValue valueToDelete ) throws IllegalArgumentException { checkValue( valueToDelete ); if ( internalDeleteValue( valueToDelete ) ) { attributeModified( new ValueDeletedEvent( getEntry().getBrowserConnection(), getEntry(), this, valueToDelete ) ); } } /** * {@inheritDoc} */ public void modifyValue( IValue oldValue, IValue newValue ) throws IllegalArgumentException { checkValue( oldValue ); checkValue( newValue ); internalDeleteValue( oldValue ); valueList.add( newValue ); attributeModified( new ValueModifiedEvent( getEntry().getBrowserConnection(), getEntry(), this, oldValue, newValue ) ); } /** * {@inheritDoc} */ public IValue[] getValues() { return ( IValue[] ) valueList.toArray( new IValue[0] ); } /** * {@inheritDoc} */ public int getValueSize() { return valueList.size(); } /** * {@inheritDoc} */ public String getDescription() { return getAttributeDescription().getDescription(); } /** * {@inheritDoc} */ public String getType() { return getAttributeDescription().getParsedAttributeType(); } /** * {@inheritDoc} */ public String toString() { return getDescription(); } /** * {@inheritDoc} */ public boolean equals( Object o ) { // check argument if ( !( o instanceof IAttribute ) ) { return false; } IAttribute a = ( IAttribute ) o; // compare entries if ( !getEntry().equals( a.getEntry() ) ) { return false; } // compare attribute description return getDescription().equals( a.getDescription() ); } /** * {@inheritDoc} */ public int hashCode() { return getDescription().hashCode(); } /** * {@inheritDoc} */ public byte[][] getBinaryValues() { List<byte[]> binaryValueList = new ArrayList<byte[]>(); IValue[] values = getValues(); for ( IValue value : values ) { binaryValueList.add( value.getBinaryValue() ); } return binaryValueList.toArray( new byte[0][] ); } /** * {@inheritDoc} */ public String getStringValue() { if ( getValueSize() > 0 ) { return ( ( IValue ) valueList.get( 0 ) ).getStringValue(); } else { return null; } } /** * {@inheritDoc} */ public String[] getStringValues() { List<String> stringValueList = new ArrayList<String>(); IValue[] values = getValues(); for ( IValue value : values ) { stringValueList.add( value.getStringValue() ); } return stringValueList.toArray( new String[stringValueList.size()] ); } /** * {@inheritDoc} */ public AttributeType getAttributeTypeDescription() { return getEntry().getBrowserConnection().getSchema().getAttributeTypeDescription( getType() ); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public Object getAdapter( Class adapter ) { Class<?> clazz = ( Class<?> ) adapter; if ( clazz.isAssignableFrom( ISearchPageScoreComputer.class ) ) { return new LdapSearchPageScoreComputer(); } if ( clazz.isAssignableFrom( Connection.class ) ) { return getEntry().getBrowserConnection().getConnection(); } if ( clazz.isAssignableFrom( IBrowserConnection.class ) ) { return getEntry().getBrowserConnection(); } if ( clazz.isAssignableFrom( IEntry.class ) ) { return getEntry(); } if ( clazz.isAssignableFrom( IAttribute.class ) ) { return this; } return null; } /** * {@inheritDoc} */ public AttributeDescription getAttributeDescription() { return attributeDescription; } }