1/**
2 * $Revision$
3 * $Date$
4 *
5 * Copyright 2006-2007 Jive Software.
6 *
7 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20package org.jivesoftware.smack.packet;
21
22import java.util.*;
23
24/**
25 * A Privacy IQ Packet, is used by the {@link org.jivesoftware.smack.PrivacyListManager}
26 * and {@link org.jivesoftware.smack.provider.PrivacyProvider} to allow and block
27 * communications from other users. It contains the appropriate structure to suit
28 * user-defined privacy lists. Different configured Privacy packages are used in the
29 * server & manager communication in order to:
30 * <ul>
31 * <li>Retrieving one's privacy lists.
32 * <li>Adding, removing, and editing one's privacy lists.
33 * <li>Setting, changing, or declining active lists.
34 * <li>Setting, changing, or declining the default list (i.e., the list that is active by default).
35 * </ul>
36 * Privacy Items can handle different kind of blocking communications based on JID, group,
37 * subscription type or globally {@link PrivacyItem}
38 *
39 * @author Francisco Vives
40 */
41public class Privacy extends IQ {
42	/** declineActiveList is true when the user declines the use of the active list **/
43	private boolean declineActiveList=false;
44	/** activeName is the name associated with the active list set for the session **/
45	private String activeName;
46	/** declineDefaultList is true when the user declines the use of the default list **/
47	private boolean declineDefaultList=false;
48	/** defaultName is the name of the default list that applies to the user as a whole **/
49	private String defaultName;
50	/** itemLists holds the set of privacy items classified in lists. It is a map where the
51	 * key is the name of the list and the value a collection with privacy items. **/
52	private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
53
54    /**
55     * Set or update a privacy list with privacy items.
56     *
57     * @param listName the name of the new privacy list.
58     * @param listItem the {@link PrivacyItem} that rules the list.
59     * @return the privacy List.
60     */
61    public List<PrivacyItem> setPrivacyList(String listName, List<PrivacyItem> listItem) {
62        // Add new list to the itemLists
63        this.getItemLists().put(listName, listItem);
64        return listItem;
65    }
66
67    /**
68     * Set the active list based on the default list.
69     *
70     * @return the active List.
71     */
72    public List<PrivacyItem> setActivePrivacyList() {
73        this.setActiveName(this.getDefaultName());
74        return this.getItemLists().get(this.getActiveName());
75    }
76
77    /**
78     * Deletes an existing privacy list. If the privacy list being deleted was the default list
79     * then the user will end up with no default list. Therefore, the user will have to set a new
80     * default list.
81     *
82     * @param listName the name of the list being deleted.
83     */
84    public void deletePrivacyList(String listName) {
85        // Remove the list from the cache
86    	this.getItemLists().remove(listName);
87
88        // Check if deleted list was the default list
89        if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
90        	this.setDefaultName(null);
91        }
92    }
93
94    /**
95     * Returns the active privacy list or <tt>null</tt> if none was found.
96     *
97     * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
98     */
99    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=\"jabber:iq:privacy\">");
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}