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