private boolean addAttributesLockless(final boolean updateClient,
            final AbstractAttribute... attributes) {

        boolean listenerInvoked = false;

        if (attributesMap == null) {
            synchronized (this) {
                if (attributesMap == null) {
                    attributesMap = new ConcurrentHashMap<>(attributes.length);
                }
            }
        }

        if (this.attributes != null) {
            for (final AbstractAttribute attribute : this.attributes) {
                attributesMap.put(attribute.getAttributeName(), attribute);
            }
        }

        for (final AbstractAttribute attribute : attributes) {
            attribute.setOwnerTag(this);
            final AbstractAttribute previous = attributesMap
                    .put(attribute.getAttributeName(), attribute);
            if (previous != null && !attribute.equals(previous)) {
                previous.unsetOwnerTag(this);
            }
        }

        this.attributes = new AbstractAttribute[attributesMap.size()];
        attributesMap.values().toArray(this.attributes);
        setModified(true);
        sharedObject.setChildModified(true);

        // invokeListener
        if (updateClient) {
            final AttributeAddListener attributeAddListener = sharedObject
                    .getAttributeAddListener(ACCESS_OBJECT);
            if (attributeAddListener != null) {
                final AttributeAddListener.AddEvent event = new AttributeAddListener.AddEvent();
                event.setAddedToTag(this);
                event.setAddedAttributes(attributes);
                attributeAddListener.addedAttributes(event);
                listenerInvoked = true;
            }
        }

        return listenerInvoked;
    }
private boolean addAttributesLockless(final boolean updateClient,
            final AbstractAttribute... attributes) {

        boolean listenerInvoked = false;

        if (attributesMap == null) {
            synchronized (this) {
                if (attributesMap == null) {
                    attributesMap = new ConcurrentHashMap<>(attributes.length);
                }
            }
        }

        if (this.attributes != null) {
            for (final AbstractAttribute attribute : this.attributes) {
                attributesMap.put(attribute.getAttributeName(), attribute);
            }
        }

        for (final AbstractAttribute attribute : attributes) {
            attribute.setOwnerTag(this);
            final AbstractAttribute previous = attributesMap
                    .put(attribute.getAttributeName(), attribute);
            if (previous != null && !attribute.equals(previous)) {
                previous.unsetOwnerTag(this);
            }
        }

        this.attributes = new AbstractAttribute[attributesMap.size()];
        attributesMap.values().toArray(this.attributes);
        setModified(true);
        sharedObject.setChildModified(true);

        
        if (updateClient) {
            final AttributeAddListener attributeAddListener = sharedObject
                    .getAttributeAddListener(ACCESS_OBJECT);
            if (attributeAddListener != null) {
                final AttributeAddListener.AddEvent event = new AttributeAddListener.AddEvent();
                event.setAddedToTag(this);
                event.setAddedAttributes(attributes);
                attributeAddListener.addedAttributes(event);
                listenerInvoked = true;
            }
        }

        return listenerInvoked;
    }
private boolean addAttributesLockless ( final boolean updateClient , final AbstractAttribute ... attributes ) { boolean listenerInvoked = false ; if ( attributesMap == null ) { synchronized ( this ) { if ( attributesMap == null ) { attributesMap = new ConcurrentHashMap <> ( attributes . length ) ; } } } if ( this . attributes != null ) { for ( final AbstractAttribute attribute : this . attributes ) { attributesMap . put ( attribute . getAttributeName ( ) , attribute ) ; } } for ( final AbstractAttribute attribute : attributes ) { attribute . setOwnerTag ( this ) ; final AbstractAttribute previous = attributesMap . put ( attribute . getAttributeName ( ) , attribute ) ; if ( previous != null && ! attribute . equals ( previous ) ) { previous . unsetOwnerTag ( this ) ; } } this . attributes = new AbstractAttribute [ attributesMap . size ( ) ] ; attributesMap . values ( ) . toArray ( this . attributes ) ; setModified ( true ) ; sharedObject . setChildModified ( true ) ; // invokeListener if ( updateClient ) { final AttributeAddListener attributeAddListener = sharedObject . getAttributeAddListener ( ACCESS_OBJECT ) ; if ( attributeAddListener != null ) { final AttributeAddListener . AddEvent event = new AttributeAddListener . AddEvent ( ) ; event . setAddedToTag ( this ) ; event . setAddedAttributes ( attributes ) ; attributeAddListener . addedAttributes ( event ) ; listenerInvoked = true ; } } return listenerInvoked ; }
adds the given attributes to this tag.

@param updateClient
true to update client browser page if it is
available. The default value is true but it will
be ignored if there is no client browser page.
@param attributes
attributes to add
@since 3.0.1 initial implementation
@author WFF
@return true if the listener invoked else false. DO NOT confuse it with
whether attributes are added.
adds the given attributes to this tag .