summaryrefslogtreecommitdiffstats
blob: 11ba1b4518d6bff443671a2fa3e1a10c30fb3dd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * Copyright (c) 2010-2015, Isode Limited, London, England.
 * All rights reserved.
 */

package com.isode.stroke.elements;

import com.isode.stroke.jid.JID;

import java.util.Date;
import java.util.Vector;

/**
 * Base class for all types of XMPP stanza.
 */
public abstract class Stanza implements Element {
    private String id_ = "";
    private JID from_ = new JID();
    private JID to_ = new JID();
    private Vector<Payload> payloads_ = new Vector<Payload>();

    /**
     * Create a stanza object 
     */
    public Stanza() {        
    }
    
    /**
     * Create a stanza object copy from another
     * @param other object to be copied, not null
     */
    public Stanza(Stanza other) {
        this.id_ = other.id_;
        if(other.from_ != null) {
            this.from_ = JID.fromString(other.from_.toString());
        }
        if(other.to_!= null) {
            this.to_ = JID.fromString(other.to_.toString());
        }
        payloads_ = new Vector<Payload>(other.payloads_);
    }

    /**
     * Get the payload of the given type from the stanza
     * @param <T> payload type
     * @param type payload type object instance, not null
     * @return payload of given type, can be null
     */
    @SuppressWarnings("unchecked")
	public <T extends Payload> T getPayload(T type) {
        for (Payload payload : payloads_) {
            if (payload.getClass().isAssignableFrom(type.getClass())) {
                return (T)payload;
            }
        }
        return null;
    }

    /**
     * Get the payloads of the given type from the stanza
     * @param <T> payload type
     * @param type payload type object instance, not null
     * @return list of payloads of given type, not null but can be empty
     */
    @SuppressWarnings("unchecked")
	public <T extends Payload> Vector<T> getPayloads(T type) {
        Vector<T> results = new Vector<T>();
        for (Payload payload : payloads_) {
            if (payload.getClass().isAssignableFrom(type.getClass())) {
                results.add((T)payload);
            }
        }
        return results;
    }

    /**
     * Get the list of payloads from this stanza
     * @return list of payloads, not null but can be empty
     */
    public Vector<Payload> getPayloads() {
        return payloads_;
    }

    /**
     * Add a payload to the stanza
     * @param payload payload to be added, not null
     */
    public void addPayload(Payload payload) {
        payloads_.add(payload);
    }

    /**
     * Update payload to the staza object. It will replace the payload of
     * given type  if it exists or add it the list if it does not exist
     * @param payload payload to be updated, not null
     */
    public void updatePayload(Payload payload) {
        for (int i = 0; i < payloads_.size(); i++) {
            if (payloads_.get(i).getClass() == payload.getClass()) {
                payloads_.set(i, payload);
                return;
            }
        }
        payloads_.add(payload);
    }

    /**
     * Get the jabber ID of the sender
     * @return jabber id, can be null
     */
    public JID getFrom() {
        return from_;
    }

    /**
     * Set the jabber ID of the sender
     * @param from jabber id, can be null
     */
    public void setFrom(JID from) {
        from_ = from;
    }

    /**
     * Get the jabber ID of the recipient user of the stanza
     * @return jabber id, can be null
     */
    public JID getTo() {
        return to_;
    }

    /**
     * Set the jabber ID of the recipient user of the stanza
     * @param to jabber id, can be null
     */
    public void setTo(JID to) {
        to_ = to;
    }

    /**
     * Get the identification string of the stanza
     * @return ID string, can be null if its not an IQ stanza
     */
    public String getID() {
        return id_;
    }

    /**
     * Set the identification string of the stanza
     * @param id ID string, not null for IQ stanza but can be null for
     *          Message or Presence stanza
     */
    public void setID(String id) {
        id_ = id;
    }
    
    /**
     * Returns debug-friendly String description of this Stanza, which will
     * include the subclass's name (e.g. "Presence").
     * @return a debug-friendly String.  
     */
    @Override
    public String toString() {
        String className = this.getClass().getSimpleName();

        // Include actual stanza type based on class name of the object
        return className + 
        " stanza from \"" + from_ + "\" to \"" + to_ + "\"" +
        " id=\"" + id_ + "\"";
    }

    public Date getTimestamp() {
    	Delay delay = getPayload(new Delay());
    	return delay != null ? delay.getStamp() : null;
    }
    
    public Date getTimestampFrom(final JID jid) {
        Vector<Delay> delays = getPayloads(new Delay());
        for (int i = 0; i < delays.size(); ++i) {
            Delay delay = delays.get(i);
            final JID from = delay.getFrom();
            if (from != null && from.equals(jid)) {
                return delay.getStamp();
            }
        }
        return getTimestamp();
    }

}