1 /*
2  * Copyright (C) 2005-2008 Jive Software. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.jivesoftware.openfire.disco;
18 
19 import org.dom4j.DocumentHelper;
20 import org.dom4j.Element;
21 import org.xmpp.packet.JID;
22 import org.xmpp.resultsetmanagement.Result;
23 
24 /**
25  * An item is associated with an XMPP Entity, usually thought of a children of
26  * the parent entity and normally are addressable as a JID.<p>
27  *
28  * An item associated with an entity may not be addressable as a JID. In order
29  * to handle such items, Service Discovery uses an optional 'node' attribute
30  * that supplements the 'jid' attribute.
31  *
32  * @author Gaston Dombiak
33  */
34 public class DiscoItem implements Result {
35 
36     private final JID jid;
37     private final String name;
38     private final String node;
39     private final String action;
40     private final Element element;
41 
42     private volatile String uid = null;
43 
DiscoItem(Element element)44     public DiscoItem(Element element) {
45         this.element = element;
46         jid = new JID(element.attributeValue("jid"));
47         action = element.attributeValue("action");
48         name = element.attributeValue("name");
49         node = element.attributeValue("node");
50     }
51 
52     /**
53      * Creates a new DiscoItem instance.
54      *
55      * @param jid
56      *            specifies the Jabber ID of the item "owner" or location
57      *            (required).
58      * @param name
59      *            specifies a natural-language name for the item (can be null).
60      * @param node
61      *            specifies the particular node associated with the JID of the
62      *            item "owner" or location (can be null).
63      * @param action
64      *            specifies the action to be taken for the item.
65      * @throws IllegalArgumentException
66      *             If a required parameter was null, or if the supplied 'action'
67      *             parameter has another value than 'null', "update" or
68      *             "remove".
69      */
DiscoItem(JID jid, String name, String node, String action)70     public DiscoItem(JID jid, String name, String node, String action) {
71         if (jid == null) {
72             throw new IllegalArgumentException("Argument 'jid' cannot be null.");
73         }
74 
75         if (action != null && !action.equals("update")
76                 && !action.equals("remove")) {
77             throw new IllegalArgumentException(
78                     "Argument 'jid' cannot have any other value than null, \"update\" or \"remove\".");
79         }
80 
81         this.jid = jid;
82         this.name = name;
83         this.node = node;
84         this.action = action;
85 
86         element = DocumentHelper.createElement("item");
87         element.addAttribute("jid", jid.toString());
88         if (action != null) {
89             element.addAttribute("action", action);
90         }
91         if (name != null) {
92             element.addAttribute("name", name);
93         }
94         if (node != null) {
95             element.addAttribute("node", node);
96         }
97     }
98 
99     /**
100      * <p>
101      * Returns the entity's ID.
102      * </p>
103      *
104      * @return the entity's ID.
105      */
getJID()106     public JID getJID() {
107         return jid;
108     }
109 
110     /**
111      * <p>
112      * Returns the node attribute that supplements the 'jid' attribute. A node
113      * is merely something that is associated with a JID and for which the JID
114      * can provide information.
115      * </p>
116      * <p>
117      * Node attributes SHOULD be used only when trying to provide or query
118      * information which is not directly addressable.
119      * </p>
120      *
121      * @return the node attribute that supplements the 'jid' attribute
122      */
getNode()123     public String getNode() {
124         return node;
125     }
126 
127     /**
128      * <p>
129      * Returns the entity's name. The entity's name specifies in
130      * natural-language the name for the item.
131      * </p>
132      *
133      * @return the entity's name.
134      */
getName()135     public String getName() {
136         return name;
137     }
138 
139     /**
140      * <p>
141      * Returns the action (i.e. update or remove) that indicates what must be
142      * done with this item or null if none. An "update" action requests the
143      * server to create or update the item. Whilst a "remove" action requests to
144      * remove the item.
145      * </p>
146      *
147      * @return the action (i.e. update or remove) that indicates what must be
148      *         done with this item or null if none.
149      */
getAction()150     public String getAction() {
151         return action;
152     }
153 
154     /**
155      * Returns a dom4j element that represents this DiscoItem object.
156      *
157      * @return element representing this object.
158      */
getElement()159     public Element getElement() {
160         return element;
161     }
162 
163     /*
164      * (non-Javadoc)
165      *
166      * @see org.jivesoftware.util.resultsetmanager.Result#getUID()
167      */
168     @Override
getUID()169     public String getUID() {
170         if (uid == null) {
171             synchronized(this) {
172                 if (uid == null) {
173                     final StringBuilder sb = new StringBuilder(jid.toString());
174                     if (name != null) {
175                         sb.append(name);
176                     }
177                     if (node != null) {
178                         sb.append(node);
179                     }
180                     if (action != null) {
181                         sb.append(action);
182                     }
183                     uid = sb.toString();
184                 }
185             }
186         }
187         return uid;
188     }
189 
190     @Override
hashCode()191     public int hashCode() {
192         return getUID().hashCode();
193     }
194 
195     @Override
equals(Object obj)196     public boolean equals(Object obj) {
197         return obj instanceof DiscoItem && getUID().equals(((DiscoItem)obj).getUID());
198     }
199 
200     @Override
toString()201     public String toString() {
202         return element.asXML();
203     }
204 
205 }
206