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        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     * @param notify
115     */
116    public ItemsExtension(String nodeId, List<? extends ExtensionElement> items, boolean notify)
117    {
118        super(ItemsElementType.retract.getNodeElement(), nodeId);
119        type = ItemsElementType.retract;
120        this.items = items; 
121        this.notify = notify;
122    }
123
124    /**
125     * Get the type of element.
126     * 
127     * @return The element type
128     */
129    public ItemsElementType getItemsElementType()
130    {
131        return type;
132    }
133
134    @Override
135    @SuppressWarnings("unchecked")
136    public List<ExtensionElement> getExtensions()
137    {
138        return (List<ExtensionElement>) getItems();
139    }
140
141    /**
142     * Gets the items related to the type of request or event.
143     * 
144     * @return List of {@link Item}, {@link RetractItem}, or null
145     */
146    public List<? extends ExtensionElement> getItems()
147    {
148        return items;
149    }
150
151    /**
152     * Gets the value of the optional attribute related to the {@link ItemsElementType}.
153     * 
154     * @return The attribute value
155     */
156    public boolean getNotify()
157    {
158        return notify;
159    }
160
161    @Override
162    public CharSequence toXML()
163    {
164        if ((items == null) || (items.size() == 0))
165        {
166            return super.toXML();
167        }
168        else
169        {
170            StringBuilder builder = new StringBuilder("<");
171            builder.append(getElementName());
172            builder.append(" node='");
173            builder.append(getNode());
174
175            if (notify != null)
176            {
177                builder.append("' ");
178                builder.append(type.getElementAttribute());
179                builder.append("='");
180                builder.append(notify.equals(Boolean.TRUE) ? 1 : 0);
181                builder.append("'>");
182            }
183            else
184            {
185                builder.append("'>");
186                for (ExtensionElement item : items)
187                {
188                    builder.append(item.toXML());
189                }
190            }
191
192            builder.append("</");
193            builder.append(getElementName());
194            builder.append('>');
195            return builder.toString();
196        }
197    }
198
199    @Override
200    public String toString()
201    {
202        return getClass().getName() + "Content [" + toXML() + "]";
203    }
204
205}