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