wffweb/src/main/java/com/webfirmframework/wffweb/tag/html/AbstractHtml.java
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);

        // 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.