001/**
002 *
003 * Copyright 2006-2007 Jive Software.
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.privacy.packet;
018
019import java.util.*;
020
021import org.jivesoftware.smack.packet.IQ;
022import org.jivesoftware.smackx.privacy.PrivacyListManager;
023
024/**
025 * A Privacy IQ Packet, is used by the {@link org.jivesoftware.smackx.privacy.PrivacyListManager}
026 * and {@link org.jivesoftware.smackx.privacy.provider.PrivacyProvider} to allow and block
027 * communications from other users. It contains the appropriate structure to suit
028 * user-defined privacy lists. Different configured Privacy packages are used in the
029 * server & manager communication in order to:
030 * <ul>
031 * <li>Retrieving one's privacy lists. 
032 * <li>Adding, removing, and editing one's privacy lists. 
033 * <li>Setting, changing, or declining active lists. 
034 * <li>Setting, changing, or declining the default list (i.e., the list that is active by default). 
035 * </ul>
036 * Privacy Items can handle different kind of blocking communications based on JID, group, 
037 * subscription type or globally {@link PrivacyItem}
038 * 
039 * @author Francisco Vives
040 */
041public class Privacy extends IQ {
042        /** declineActiveList is true when the user declines the use of the active list **/
043        private boolean declineActiveList=false;
044        /** activeName is the name associated with the active list set for the session **/
045        private String activeName;
046        /** declineDefaultList is true when the user declines the use of the default list **/
047        private boolean declineDefaultList=false;
048        /** defaultName is the name of the default list that applies to the user as a whole **/
049        private String defaultName;
050        /** itemLists holds the set of privacy items classified in lists. It is a map where the 
051         * key is the name of the list and the value a collection with privacy items. **/
052        private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
053
054    /**
055     * Set or update a privacy list with privacy items.
056     *
057     * @param listName the name of the new privacy list.
058     * @param listItem the {@link PrivacyItem} that rules the list.
059     * @return the privacy List.
060     */
061    public List<PrivacyItem> setPrivacyList(String listName, List<PrivacyItem> listItem) {
062        // Add new list to the itemLists
063        this.getItemLists().put(listName, listItem);
064        return listItem;
065    }
066
067    /**
068     * Set the active list based on the default list.
069     *
070     * @return the active List.
071     */
072    public List<PrivacyItem> setActivePrivacyList() {
073        this.setActiveName(this.getDefaultName());
074        return this.getItemLists().get(this.getActiveName());
075    }
076
077    /**
078     * Deletes an existing privacy list. If the privacy list being deleted was the default list 
079     * then the user will end up with no default list. Therefore, the user will have to set a new 
080     * default list.
081     *
082     * @param listName the name of the list being deleted.
083     */
084    public void deletePrivacyList(String listName) {
085        // Remove the list from the cache
086        this.getItemLists().remove(listName);
087
088        // Check if deleted list was the default list
089        if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
090                this.setDefaultName(null);
091        }
092    }
093
094    /**
095     * Returns the active privacy list or <tt>null</tt> if none was found.
096     *
097     * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
098     */
099    public List<PrivacyItem> getActivePrivacyList() {
100        // Check if we have the default list
101        if (this.getActiveName() == null) {
102                return null;
103        } else {
104                return this.getItemLists().get(this.getActiveName());
105        }
106    }
107
108    /**
109     * Returns the default privacy list or <tt>null</tt> if none was found.
110     *
111     * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
112     */
113    public List<PrivacyItem> getDefaultPrivacyList() {
114        // Check if we have the default list
115        if (this.getDefaultName() == null) {
116                return null;
117        } else {
118                return this.getItemLists().get(this.getDefaultName());
119        }
120    }
121
122    /**
123     * Returns a specific privacy list.
124     *
125     * @param listName the name of the list to get.
126     * @return a List with {@link PrivacyItem}
127     */
128    public List<PrivacyItem> getPrivacyList(String listName) {
129        return this.getItemLists().get(listName);
130    }
131
132    /**
133     * Returns the privacy item in the specified order.
134     *
135     * @param listName the name of the privacy list.
136     * @param order the order of the element.
137     * @return a List with {@link PrivacyItem}
138     */
139    public PrivacyItem getItem(String listName, int order) {
140        Iterator<PrivacyItem> values = getPrivacyList(listName).iterator();
141        PrivacyItem itemFound = null;
142        while (itemFound == null && values.hasNext()) {
143                PrivacyItem element = values.next();
144                        if (element.getOrder() == order) {
145                                itemFound = element;
146                        }
147                }
148        return itemFound;
149    }
150
151    /**
152     * Sets a given privacy list as the new user default list.
153     *
154     * @param newDefault the new default privacy list.
155     * @return if the default list was changed.
156     */
157    public boolean changeDefaultList(String newDefault) {
158        if (this.getItemLists().containsKey(newDefault)) {
159           this.setDefaultName(newDefault);
160           return true;
161        } else {
162                return false; 
163        }
164    }
165
166    /**
167     * Remove the list.
168     *
169     * @param listName name of the list to remove.
170     */
171     public void deleteList(String listName) {
172         this.getItemLists().remove(listName);
173     }
174
175    /**
176     * Returns the name associated with the active list set for the session. Communications
177     * will be verified against the active list.
178     *
179     * @return the name of the active list.
180     */
181        public String getActiveName() {
182                return activeName;
183        }
184
185    /**
186     * Sets the name associated with the active list set for the session. Communications
187     * will be verified against the active list.
188     * 
189     * @param activeName is the name of the active list.
190     */
191        public void setActiveName(String activeName) {
192                this.activeName = activeName;
193        }
194
195    /**
196     * Returns the name of the default list that applies to the user as a whole. Default list is 
197     * processed if there is no active list set for the target session/resource to which a stanza 
198     * is addressed, or if there are no current sessions for the user.
199     * 
200     * @return the name of the default list.
201     */
202        public String getDefaultName() {
203                return defaultName;
204        }
205
206    /**
207     * Sets the name of the default list that applies to the user as a whole. Default list is 
208     * processed if there is no active list set for the target session/resource to which a stanza 
209     * is addressed, or if there are no current sessions for the user.
210     * 
211     * If there is no default list set, then all Privacy Items are processed.
212     * 
213     * @param defaultName is the name of the default list.
214     */
215        public void setDefaultName(String defaultName) {
216                this.defaultName = defaultName;
217        }
218
219    /**
220     * Returns the collection of privacy list that the user holds. A Privacy List contains a set of 
221     * rules that define if communication with the list owner is allowed or denied. 
222     * Users may have zero, one or more privacy items.
223     * 
224     * @return a map where the key is the name of the list and the value the 
225     * collection of privacy items.
226     */
227        public Map<String, List<PrivacyItem>> getItemLists() {
228                return itemLists;
229        }
230
231    /** 
232     * Returns whether the receiver allows or declines the use of an active list.
233     * 
234     * @return the decline status of the list.
235     */
236        public boolean isDeclineActiveList() {
237                return declineActiveList;
238        }
239
240    /** 
241     * Sets whether the receiver allows or declines the use of an active list.
242     * 
243     * @param declineActiveList indicates if the receiver declines the use of an active list.
244     */
245        public void setDeclineActiveList(boolean declineActiveList) {
246                this.declineActiveList = declineActiveList;
247        }
248
249    /** 
250     * Returns whether the receiver allows or declines the use of a default list.
251     * 
252     * @return the decline status of the list.
253     */
254        public boolean isDeclineDefaultList() {
255                return declineDefaultList;
256        }
257
258    /** 
259     * Sets whether the receiver allows or declines the use of a default list.
260     * 
261     * @param declineDefaultList indicates if the receiver declines the use of a default list.
262     */
263        public void setDeclineDefaultList(boolean declineDefaultList) {
264                this.declineDefaultList = declineDefaultList;
265        }
266
267        /** 
268     * Returns all the list names the user has defined to group restrictions.
269     * 
270     * @return a Set with Strings containing every list names.
271     */
272        public Set<String> getPrivacyListNames() {
273                return this.itemLists.keySet();
274        }
275        
276        public String getChildElementXML() {
277        StringBuilder buf = new StringBuilder();
278        buf.append("<query xmlns=\"" + PrivacyListManager.NAMESPACE + "\">");
279
280        // Add the active tag
281        if (this.isDeclineActiveList()) {
282                buf.append("<active/>");
283        } else {
284                if (this.getActiveName() != null) {
285                buf.append("<active name=\"").append(this.getActiveName()).append("\"/>");
286            }
287        }
288        // Add the default tag
289        if (this.isDeclineDefaultList()) {
290                buf.append("<default/>");
291        } else {
292                if (this.getDefaultName() != null) {
293                        buf.append("<default name=\"").append(this.getDefaultName()).append("\"/>");
294                }
295        }
296        
297        // Add the list with their privacy items
298        for (Map.Entry<String, List<PrivacyItem>> entry : this.getItemLists().entrySet()) {
299          String listName = entry.getKey();
300          List<PrivacyItem> items = entry.getValue();
301                        // Begin the list tag
302                        if (items.isEmpty()) {
303                                buf.append("<list name=\"").append(listName).append("\"/>");
304                        } else {
305                                buf.append("<list name=\"").append(listName).append("\">");
306                        }
307                for (PrivacyItem item : items) {
308                        // Append the item xml representation
309                        buf.append(item.toXML());
310                }
311                // Close the list tag
312                if (!items.isEmpty()) {
313                                buf.append("</list>");
314                        }
315                }
316
317        // Add packet extensions, if any are defined.
318        buf.append(getExtensionsXML());
319        buf.append("</query>");
320        return buf.toString();
321    }
322    
323}