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 to for multiple purposes.  
025 * <li>It can represent an event containing a list of items that have been published
026 * <li>It can represent an event containing a list of retracted (deleted) items.
027 * <li>It can represent a request to delete a list of items.
028 * <li>It can represent a request to get existing items.
029 * 
030 * <p><b>Please note, this class is used for internal purposes, and is not required for usage of 
031 * pubsub functionality.</b>
032 * 
033 * @author Robin Collier
034 */
035public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension
036{
037        protected ItemsElementType type;
038        protected Boolean notify;
039        protected List<? extends ExtensionElement> items;
040
041        public enum ItemsElementType
042        {
043                /** An items element, which has an optional <b>max_items</b> attribute when requesting items */
044                items(PubSubElementType.ITEMS, "max_items"),
045                
046                /** A retract element, which has an optional <b>notify</b> attribute when publishing deletions */
047                retract(PubSubElementType.RETRACT, "notify");
048                
049                private PubSubElementType elem;
050                private String att;
051                
052                private ItemsElementType(PubSubElementType nodeElement, String attribute)
053                {
054                        elem = nodeElement;
055                        att = attribute;
056                }
057                
058                public PubSubElementType getNodeElement()
059                {
060                        return elem;
061                }
062
063                public String getElementAttribute()
064                {
065                        return att;
066                }
067        }
068
069        /**
070         * Construct an instance with a list representing items that have been published or deleted.
071         * 
072         * <p>Valid scenarios are:
073         * <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
074         * optional value for the <b>max_items</b> attribute.
075         * <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
076         * only id's and an optional value for the <b>notify</b> attribute.
077         * <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and 
078         * attributeValue = <code>null</code>
079         * <li>Items deleted event -  itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and 
080         * attributeValue = <code>null</code> 
081         * 
082         * @param itemsType Type of representation
083         * @param nodeId The node to which the items are being sent or deleted
084         * @param items The list of {@link Item} or {@link RetractItem}
085         */
086        public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends ExtensionElement> items)
087        {
088                super(itemsType.getNodeElement(), nodeId);
089                type = itemsType;
090                this.items = items;
091        }
092        
093        /**
094         * Construct an instance with a list representing items that have been published or deleted.
095         * 
096         * <p>Valid scenarios are:
097         * <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
098         * optional value for the <b>max_items</b> attribute.
099         * <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
100         * only id's and an optional value for the <b>notify</b> attribute.
101         * <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and 
102         * attributeValue = <code>null</code>
103         * <li>Items deleted event -  itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and 
104         * attributeValue = <code>null</code> 
105         * 
106         * @param nodeId The node to which the items are being sent or deleted
107         * @param items The list of {@link Item} or {@link RetractItem}
108         */
109        public ItemsExtension(String nodeId, List<? extends ExtensionElement> items, boolean notify)
110        {
111                super(ItemsElementType.retract.getNodeElement(), nodeId);
112                type = ItemsElementType.retract;
113                this.items = items; 
114                this.notify = notify;
115        }
116        
117        /**
118         * Get the type of element
119         * 
120         * @return The element type
121         */
122        public ItemsElementType getItemsElementType()
123        {
124                return type;
125        }
126        
127        @SuppressWarnings("unchecked")
128        public List<ExtensionElement> getExtensions()
129        {
130                return (List<ExtensionElement>)getItems();
131        }
132        
133        /**
134         * Gets the items related to the type of request or event.
135         * 
136         * return List of {@link Item}, {@link RetractItem}, or null
137         */
138        public List<? extends ExtensionElement> getItems()
139        {
140                return items;
141        }
142
143        /**
144         * Gets the value of the optional attribute related to the {@link ItemsElementType}.
145         * 
146         * @return The attribute value
147         */
148        public boolean getNotify()
149        {
150                return notify;
151        }
152        
153        @Override
154        public CharSequence toXML()
155        {
156                if ((items == null) || (items.size() == 0))
157                {
158                        return super.toXML();
159                }
160                else
161                {
162                        StringBuilder builder = new StringBuilder("<");
163                        builder.append(getElementName());
164                        builder.append(" node='");
165                        builder.append(getNode());
166                        
167                        if (notify != null)
168                        {
169                                builder.append("' ");
170                                builder.append(type.getElementAttribute());
171                                builder.append("='");
172                                builder.append(notify.equals(Boolean.TRUE) ? 1 : 0);
173                                builder.append("'>");
174                        }
175                        else
176                        {
177                                builder.append("'>");
178                                for (ExtensionElement item : items)
179                                {
180                                        builder.append(item.toXML());
181                                }
182                        }
183                        
184                        builder.append("</");
185                        builder.append(getElementName());
186                        builder.append(">");
187                        return builder.toString();
188                }
189        }
190
191        @Override
192        public String toString()
193        {
194                return getClass().getName() + "Content [" + toXML() + "]";
195        }
196
197}