1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx.packet; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collection; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Iterator; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.LinkedList; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.CopyOnWriteArrayList; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A DiscoverInfo IQ packet, which is used by XMPP clients to request and receive information 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to/from other XMPP entities.<p> 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The received information may contain one or more identities of the requested XMPP entity, and 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a list of supported features by the requested XMPP entity. 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class DiscoverInfo extends IQ { 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final String NAMESPACE = "http://jabber.org/protocol/disco#info"; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<Feature> features = new CopyOnWriteArrayList<Feature>(); 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<Identity> identities = new CopyOnWriteArrayList<Identity>(); 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String node; 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public DiscoverInfo() { 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(); 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copy constructor 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param d 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public DiscoverInfo(DiscoverInfo d) { 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(d); 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set node 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setNode(d.getNode()); 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Copy features 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (d.features) { 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Feature f : d.features) { 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addFeature(f); 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Copy identities 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (d.identities) { 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Identity i : d.identities) { 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addIdentity(i); 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a new feature to the discovered information. 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param feature the discovered feature 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addFeature(String feature) { 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addFeature(new Feature(feature)); 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a collection of features to the packet. Does noting if featuresToAdd is null. 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param featuresToAdd 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addFeatures(Collection<String> featuresToAdd) { 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (featuresToAdd == null) return; 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (String feature : featuresToAdd) { 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addFeature(feature); 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void addFeature(Feature feature) { 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (features) { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen features.add(feature); 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the discovered features of an XMPP entity. 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return an Iterator on the discovered features of an XMPP entity 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Iterator<Feature> getFeatures() { 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (features) { 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Collections.unmodifiableList(features).iterator(); 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a new identity of the requested entity to the discovered information. 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param identity the discovered entity's identity 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addIdentity(Identity identity) { 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (identities) { 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen identities.add(identity); 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds identities to the DiscoverInfo stanza 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param identitiesToAdd 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addIdentities(Collection<Identity> identitiesToAdd) { 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (identitiesToAdd == null) return; 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (identities) { 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen identities.addAll(identitiesToAdd); 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the discovered identities of an XMPP entity. 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return an Iterator on the discoveted identities 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Iterator<Identity> getIdentities() { 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (identities) { 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Collections.unmodifiableList(identities).iterator(); 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the node attribute that supplements the 'jid' attribute. A node is merely 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * something that is associated with a JID and for which the JID can provide information.<p> 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Node attributes SHOULD be used only when trying to provide or query information which 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is not directly addressable. 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the node attribute that supplements the 'jid' attribute 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getNode() { 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return node; 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the node attribute that supplements the 'jid' attribute. A node is merely 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * something that is associated with a JID and for which the JID can provide information.<p> 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Node attributes SHOULD be used only when trying to provide or query information which 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is not directly addressable. 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param node the node attribute that supplements the 'jid' attribute 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setNode(String node) { 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.node = node; 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns true if the specified feature is part of the discovered information. 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param feature the feature to check 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the requestes feature has been discovered 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean containsFeature(String feature) { 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<Feature> it = getFeatures(); it.hasNext();) { 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (feature.equals(it.next().getVar())) 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getChildElementXML() { 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuilder buf = new StringBuilder(); 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("<query xmlns=\"" + NAMESPACE + "\""); 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (getNode() != null) { 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(" node=\""); 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(StringUtils.escapeForXML(getNode())); 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("\""); 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(">"); 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (identities) { 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Identity identity : identities) { 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(identity.toXML()); 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (features) { 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Feature feature : features) { 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(feature.toXML()); 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add packet extensions, if any are defined. 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(getExtensionsXML()); 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("</query>"); 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return buf.toString(); 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Test if a DiscoverInfo response contains duplicate identities. 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if duplicate identities where found, otherwise false 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean containsDuplicateIdentities() { 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<Identity> checkedIdentities = new LinkedList<Identity>(); 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Identity i : identities) { 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Identity i2 : checkedIdentities) { 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (i.equals(i2)) 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkedIdentities.add(i); 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Test if a DiscoverInfo response contains duplicate features. 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if duplicate identities where found, otherwise false 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean containsDuplicateFeatures() { 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<Feature> checkedFeatures = new LinkedList<Feature>(); 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Feature f : features) { 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Feature f2 : checkedFeatures) { 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (f.equals(f2)) 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkedFeatures.add(f); 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Represents the identity of a given XMPP entity. An entity may have many identities but all 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the identities SHOULD have the same name.<p> 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a> 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in order to get the official registry of values for the <i>category</i> and <i>type</i> 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * attributes. 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static class Identity implements Comparable<Identity> { 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String category; 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String name; 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String type; 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String lang; // 'xml:lang; 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new identity for an XMPP entity. 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param category the entity's category. 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name the entity's name. 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @deprecated As per the spec, the type field is mandatory and the 3 argument constructor should be used instead. 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Identity(String category, String name) { 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.category = category; 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.name = name; 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new identity for an XMPP entity. 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 'category' and 'type' are required by 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <a href="http://xmpp.org/extensions/xep-0030.html#schemas">XEP-30 XML Schemas</a> 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param category the entity's category (required as per XEP-30). 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name the entity's name. 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type the entity's type (required as per XEP-30). 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Identity(String category, String name, String type) { 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ((category == null) || (type == null)) 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("category and type cannot be null"); 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.category = category; 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.name = name; 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.type = type; 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the entity's category. To get the official registry of values for the 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 'category' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a> 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the entity's category. 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getCategory() { 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return category; 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the identity's name. 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the identity's name. 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getName() { 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return name; 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the entity's type. To get the official registry of values for the 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 'type' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a> 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the entity's type. 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getType() { 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return type; 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the entity's type. To get the official registry of values for the 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 'type' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a> 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type the identity's type. 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @deprecated As per the spec, this field is mandatory and the 3 argument constructor should be used instead. 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setType(String type) { 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.type = type; 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the natural language (xml:lang) for this identity (optional) 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param lang the xml:lang of this Identity 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setLanguage(String lang) { 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.lang = lang; 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the identities natural language if one is set 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the value of xml:lang of this Identity 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getLanguage() { 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return lang; 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String toXML() { 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuilder buf = new StringBuilder(); 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("<identity"); 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if this packet has 'lang' set and maybe append it to the resulting string 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (lang != null) 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(" xml:lang=\"").append(StringUtils.escapeForXML(lang)).append("\""); 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Category must always be set 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(" category=\"").append(StringUtils.escapeForXML(category)).append("\""); 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Name must always be set 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(" name=\"").append(StringUtils.escapeForXML(name)).append("\""); 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if this packet has 'type' set and maybe append it to the resulting string 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type != null) { 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append(" type=\"").append(StringUtils.escapeForXML(type)).append("\""); 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("/>"); 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return buf.toString(); 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Check equality for Identity for category, type, lang and name 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in that order as defined by 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <a href="http://xmpp.org/extensions/xep-0115.html#ver-proc">XEP-0015 5.4 Processing Method (Step 3.3)</a> 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean equals(Object obj) { 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == null) 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == this) 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj.getClass() != getClass()) 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo.Identity other = (DiscoverInfo.Identity) obj; 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!this.category.equals(other.category)) 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String otherLang = other.lang == null ? "" : other.lang; 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String thisLang = lang == null ? "" : lang; 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!otherLang.equals(thisLang)) 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // This safeguard can be removed once the deprecated constructor is removed. 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String otherType = other.type == null ? "" : other.type; 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String thisType = type == null ? "" : type; 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!otherType.equals(thisType)) 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String otherName = other.name == null ? "" : other.name; 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String thisName = name == null ? "" : other.name; 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!thisName.equals(otherName)) 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int result = 1; 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 37 * result + category.hashCode(); 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 37 * result + (lang == null ? 0 : lang.hashCode()); 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 37 * result + (type == null ? 0 : type.hashCode()); 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 37 * result + (name == null ? 0 : name.hashCode()); 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return result; 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Compares this identity with another one. The comparison order is: 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Category, Type, Lang. If all three are identical the other Identity is considered equal. 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Name is not used for comparision, as defined by XEP-0115 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param obj 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int compareTo(DiscoverInfo.Identity other) { 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String otherLang = other.lang == null ? "" : other.lang; 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String thisLang = lang == null ? "" : lang; 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // This can be removed once the deprecated constructor is removed. 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String otherType = other.type == null ? "" : other.type; 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String thisType = type == null ? "" : type; 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (category.equals(other.category)) { 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (thisType.equals(otherType)) { 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (thisLang.equals(otherLang)) { 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Don't compare on name, XEP-30 says that name SHOULD 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // be equals for all identities of an entity 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return 0; 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return thisLang.compareTo(otherLang); 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return thisType.compareTo(otherType); 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return category.compareTo(other.category); 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Represents the features offered by the item. This information helps requestors determine 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * what actions are possible with regard to this item (registration, search, join, etc.) 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * as well as specific feature types of interest, if any (e.g., for the purpose of feature 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * negotiation). 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static class Feature { 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String variable; 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new feature offered by an XMPP entity or item. 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param variable the feature's variable. 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Feature(String variable) { 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (variable == null) 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("variable cannot be null"); 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.variable = variable; 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the feature's variable. 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the feature's variable. 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getVar() { 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return variable; 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String toXML() { 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuilder buf = new StringBuilder(); 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buf.append("<feature var=\"").append(StringUtils.escapeForXML(variable)).append("\"/>"); 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return buf.toString(); 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean equals(Object obj) { 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == null) 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == this) 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj.getClass() != getClass()) 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo.Feature other = (DiscoverInfo.Feature) obj; 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return variable.equals(other.variable); 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return 37 * variable.hashCode(); 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 508