001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.pubsub;
018
019import java.util.List;
020
021import org.jivesoftware.smack.packet.ExtensionElement;
022
023/**
024 * This class is used for multiple purposes.
025 * <ul>
026 * <li>It can represent an event containing a list of items that have been published
027 * <li>It can represent an event containing a list of retracted (deleted) items.
028 * <li>It can represent a request to delete a list of items.
029 * <li>It can represent a request to get existing items.
030 * </ul>
031 * 
032 * <p><b>Please note, this class is used for internal purposes, and is not required for usage of 
033 * pubsub functionality.</b></p>
034 * 
035 * @author Robin Collier
036 */
037public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension
038{
039    protected ItemsElementType type;
040    protected Boolean notify;
041    protected List<? extends ExtensionElement> items;
042
043    public enum ItemsElementType
044    {
045        /** An items element, which has an optional <b>max_items</b> attribute when requesting items. */
046        items(PubSubElementType.ITEMS, "max_items"),
047
048        /** A retract element, which has an optional <b>notify</b> attribute when publishing deletions. */
049        retract(PubSubElementType.RETRACT, "notify");
050
051        private final PubSubElementType elem;
052        private final String att;
053
054        private ItemsElementType(PubSubElementType nodeElement, String attribute)
055        {
056            elem = nodeElement;
057            att = attribute;
058        }
059
060        public PubSubElementType getNodeElement()
061        {
062            return elem;
063        }
064
065        public String getElementAttribute()
066        {
067            return att;
068        }
069    }
070
071    /**
072     * Construct an instance with a list representing items that have been published or deleted.
073     * 
074     * <p>Valid scenarios are:</p>
075     * <ul>
076     * <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
077     * optional value for the <b>max_items</b> attribute.
078     * <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
079     * only id's and an optional value for the <b>notify</b> attribute.
080     * <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and 
081     * attributeValue = <code>null</code>
082     * <li>Items deleted event -  itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and 
083     * attributeValue = <code>null</code> 
084     * </ul>
085     * 
086     * @param itemsType Type of representation
087     * @param nodeId The node to which the items are being sent or deleted
088     * @param items The list of {@link Item} or {@link RetractItem}
089     */
090    public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends ExtensionElement> items)
091    {
092        super(itemsType.getNodeElement(), nodeId);
093        type = itemsType;
094        this.items = items;
095    }
096
097    /**
098     * Construct an instance with a list representing items that have been published or deleted.
099     * 
100     * <p>Valid scenarios are:</p>
101     * <ul>
102     * <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
103     * optional value for the <b>max_items</b> attribute.
104     * <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
105     * only id's and an optional value for the <b>notify</b> attribute.
106     * <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and 
107     * attributeValue = <code>null</code>
108     * <li>Items deleted event -  itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and 
109     * attributeValue = <code>null</code>
110     * </ul>
111     * 
112     * @param nodeId The node to which the items are being sent or deleted
113     * @param items The list of {@link Item} or {@link RetractItem}
114     */
115    public ItemsExtension(String nodeId, List<? extends ExtensionElement> items, boolean notify)
116    {
117        super(ItemsElementType.retract.getNodeElement(), nodeId);
118        type = ItemsElementType.retract;
119        this.items = items; 
120        this.notify = notify;
121    }
122
123    /**
124     * Get the type of element.
125     * 
126     * @return The element type
127     */
128    public ItemsElementType getItemsElementType()
129    {
130        return type;
131    }
132
133    @Override
134    @SuppressWarnings("unchecked")
135    public List<ExtensionElement> getExtensions()
136    {
137        return (List<ExtensionElement>)getItems();
138    }
139
140    /**
141     * Gets the items related to the type of request or event.
142     * 
143     * return List of {@link Item}, {@link RetractItem}, or null
144     */
145    public List<? extends ExtensionElement> getItems()
146    {
147        return items;
148    }
149
150    /**
151     * Gets the value of the optional attribute related to the {@link ItemsElementType}.
152     * 
153     * @return The attribute value
154     */
155    public boolean getNotify()
156    {
157        return notify;
158    }
159
160    @Override
161    public CharSequence toXML()
162    {
163        if ((items == null) || (items.size() == 0))
164        {
165            return super.toXML();
166        }
167        else
168        {
169            StringBuilder builder = new StringBuilder("<");
170            builder.append(getElementName());
171            builder.append(" node='");
172            builder.append(getNode());
173
174            if (notify != null)
175            {
176                builder.append("' ");
177                builder.append(type.getElementAttribute());
178                builder.append("='");
179                builder.append(notify.equals(Boolean.TRUE) ? 1 : 0);
180                builder.append("'>");
181            }
182            else
183            {
184                builder.append("'>");
185                for (ExtensionElement item : items)
186                {
187                    builder.append(item.toXML());
188                }
189            }
190
191            builder.append("</");
192            builder.append(getElementName());
193            builder.append('>');
194            return builder.toString();
195        }
196    }
197
198    @Override
199    public String toString()
200    {
201        return getClass().getName() + "Content [" + toXML() + "]";
202    }
203
204}