001 package com.skype.api;
002
003 import java.io.IOException;
004 import java.util.*;
005 import com.skype.ipc.*;
006 /**
007 * Events in a conversation context are expressed as Messages. It is therefore useful to think of Message objects as events, rather than specifically text chat messages. <br><br>Message member functions all return a Boolean indicating the success (true) or failure (false) of processing the request itself (transport, runtime availability, and so forth) - not the success or failure of its associated functionality. For example, Message.Edit returns true if it was able to make a determination, and its result parameter reflects whether this Message can be edited. Similarly, Message.Edit returns false if it was unable to make a determination, and the value of its result parameter is undefined. <br><br>Message member functions that are specific to a Message TYPE return false if this Message is not of that type. For example, Message.GetVoiceMessage will return false if this Message's type is not POSTED_VOICE_MESSAGE. <br><br>The actual meaning of a Message can be determined by its P_TYPE property. The meanings of most other Message properties depend on the value of P_TYPE. For example, let's take P_BODY_XML property. <br><br>Following messages have a text entered by the user as a body. It may contain emoticons, URLs, etc. <br> - POSTED_TEXT <br> - POSTED_EMOTE <br> - SET_METADATA <br> - REQUESTED_AUTH <br><br>Following messages have a custom XML format for the body (see the specific section on these message types for details): <br> - POSTED_CONTACTS <br> - POSTED_VOICE_MESSAGE <br> - POSTED_FILES <br> - POSTED_SMS <br> - STARTED_LIVESESSION and ENDED_LIVESESSION (same format) <br><br>Following messages do not use the body property: <br> - SPAWNED_CONFERENCE <br> - ADDED_CONSUMERS <br> - ADDED_APPLICANTS <br> - RETIRED_OTHERS <br> - RETIRED <br> - SET_RANK <br> - HAS_BIRTHDAY <br> - GRANTED_AUTH <br> - BLOCKED <br><br>Messages such as POSTED_TEXT use a small subset of a HTML-like markup to control the visual representation of the text. This markup is used by POSTED_TEXT and POSTED_EMOTE, but also for the conversation topic (CONVERSATION_META_TOPIC property and the body of the SET_METADATA message) and for authorization requests. <br><br>Having chat messages in XML format means that all formatting is indicated by XML tags. This includes emoticons and URls. The big advantage is that it makes the parsing of the message by the UI much easier. The UI does not need to do emoticons or URL detection, this is already done and it only needs to look for the XML tags. <br><br>For text messages, it is possible for the UI to simply ignore (meaning strip) the XML and the message will be understandable fine, it will only have lost some formatting. <br><br>But it is obviously nicer to display at least the most commonly used tags. <br><br>To strip the XML: <br> - if they have the alt="sometext" attribute set, return sometext as the output of that tag and ignore the rest of tag and all nested sub tags <br> - if no alt="" attribute set, use tag content as output - <sometag>hereissomething</sometag> is output as hereissomething<br> - if no alt="" and no tag content, ignore the tag altogether (return nothing) <br>Skype for Windows supports displaying many XML tags, but only a sub-set is regularly used and should be supported by the UI for a good experience. These are the ones described here. <br>Animated emoticons <br>Emoticons are encoded with the "ss" tag. The element content is the plain text representation. It has a "type" attribute indicating the emoticons canonical name. Example: <br>@code <br>Hi <ss type="smile">:-)</ss> <br></CODE> <br><br>Flag emoticons <br>Flag emoticons are little flags. They are encoded with the "flag" tag. The element contents is the plain text representation and it has a "country" attribute which is a 2-letter ISO-3166 country code. The user can enter a flag using "(flag:XX)", where XX is a valid ISO country code. Example: <br>@code <br>I am in <flag country="cc">CC</flag> <br></CODE> <br><br>Links <br>If the library detects a URL, it will encode it using the html "a" tag, with the "href" attribute indicating the URL. The plain text representation is what the user originally typed. Example: <br>@code <br>I am in <a href="http://wwww.skype.com">www.skype.com</a> <br></CODE> <br><br>Alert matches <br>When a conversation is configured to display only alerts if specific words are present in the message (see "/alertson [text to match]" command), if a message matches the alert, it will be marked with the <alertmatch> tag. This allows the UI to highlight the word matching. Example: <br>@code <br>Maybe <alertmatch>Vincent</alertmatch> knows the answer <br></CODE> <br><br>Bold, italic, etc <br>Skype for Windows also supports displaying bold and italic text, using the "b" and "i" tags. <br><br>Encoding messages <br>When sending a chat message via PostText(), there is the possibility to indicate if the library should do the XML encoding, or if the message has already been encoded. Usually, the UI can let library do the encoding. This is the case when the message does not contain any specific formatting. It may contain emoticons or URls, which will be detected by the library encoder and converted into XML tags. <br>If the message has some more complex encoding, such as a quote or some bold text, it is up to the UI to encode the message. <br>
008 */
009
010
011 public class Message extends SkypeObject {
012
013
014 public interface MessageListener {
015 /** This event gets called when there are changes to Message properties defined in Message.PROPERTY */
016 public void OnPropertyChange(SkypeObject obj, PROPERTY prop, Object value);
017
018 }
019
020 public Message(int oid, Skype skype) {
021 super(oid,skype);
022 /**get default properties for this module **/
023 GetDefaultProps();
024 }
025
026 private static final int MODULE_ID = 9;
027
028 public static final int moduleID() {
029 return MODULE_ID;
030 }
031
032 /** Properties of the Message class */
033 public enum PROPERTY {
034
035 /** DB ID of corresponding conversation, type: Conversation */
036 convo_id(960),
037
038 /** GUID of the Conversation. The GUID is a "global ID" - these values are shared accross Skype client instances and accross all the participants of the conversation. <br>, type: String */
039 convo_guid(120),
040
041 /** Identity of the sender. While this is almost always the same as SKYPENAME property of the Contact, in some rare cases it can also be a phone number - for example, incoming voicemail notification Messages (message type = POSTED_VOICE_MESSAGE). <br>, type: String */
042 author(122),
043
044 /** displayname of the sender at the time of posting, type: String */
045 author_displayname(123),
046
047 /** Unlike the message id, the GUID is the same on all instances and for all participants. <br>, type: byte[] */
048 guid(792),
049
050 /** This property gets set when a conference is spawned from dialog Conversation. In that case recent message history from the original dialog is copied to the target conversation. For all the copied messages, the ORIGINALLY_MEANT_FOR property will be set to identity of the remote participant of the original dialog. <br>, type: String */
051 originally_meant_for(790),
052
053 /** UNIX timestamp (sent time, adjusted for local clock), type: int */
054 timestamp(121),
055
056 /** type: Message.TYPE */
057 type(961),
058
059 /** type: Message.SENDING_STATUS */
060 sending_status(962),
061
062 /** type: Message.CONSUMPTION_STATUS */
063 consumption_status(968),
064
065 /** Identity of the author that last edited this message. NULL if message has not been edited <br>, type: String */
066 edited_by(222),
067
068 /** UNIX timestamp of last edit, type: int */
069 edit_timestamp(223),
070
071 /** Message type-specific parameter. See Message.SET_METADATA_KEY for more information. <br>, type: int */
072 param_key(963),
073
074 /** Message type-specific parameter <br>, type: int */
075 param_value(964),
076
077 /** Message type-specific parameter <br>, type: String */
078 body_xml(127),
079
080 /** Message type-specific parameter. Depending of Message type, this property contains: <br> - STARTED_LIVESESSION - list of participants in the cal; <br> - ENDED_LIVESESSION - list of participants in the call; <br> - POSTED_SMS - list of recipients of the message; <br> - SPAWNED_CONFERENCE - the list of identities that were added; <br> - ADDED_CONSUMERS - the list of identities that were added; <br> - RETIRED_OTHERS - the skypename of the participant who was kicked; <br> - SET_RANK - the skypename of the participant whose rank was changed; <br> - REQUESTED_AUTH - Message.P_AUTHOR and Message.P_IDENTITIES are set to the users receiving and requesting the authorization, depending if the message was received or sent; <br> - GRANTED_AUTH - the skypename of the user we granted authorization; <br> - BLOCKED - the skypename of the user who was blocked; <br> - HAS_BIRTHDAY - skypename of current logged in user. <br>, type: String */
081 identities(125),
082
083 /** Message type-specific parameter. Possible values for STARTED/ENDED_LIVESESSION (only set for dialogs): <br> - no_answer <br> - manual <br> - busy <br> - connection_dropped <br> - no_skypeout_subscription; <br> - insufficient_funds <br> - internet_connection_lost <br> - skypeout_account_blocked <br> - pstn_could_not_connect_to_skype_proxy <br> - pstn_invalid_number <br> - pstn_number_forbidden <br> - pstn_call_timed_out <br> - pstn_busy <br> - pstn_call_terminated <br> - pstn_network_error <br> - number_unavailable <br> - pstn_call_rejected <br> - pstn_misc_error <br> - internal_error <br> - unable_to_connect <br> - connection_dropped <br> - recording_failed <br> - playback_error <br> - legacy_error <br> - blocked_by_privacy_settings <br> - error <br> - transfer_failed <br> - transfer_insufficient_funds <br> - blocked_by_us <br> - emergency_call_denied <br><br>This information is now available as an enum in LEAVEREASON <br>, type: String */
084 reason(966),
085
086 /** leave reason for message of the RETIRED type, type: Message.LEAVEREASON */
087 leavereason(126),
088
089 /** Number of people who received this message (including local user) <br>, type: int */
090 participant_count(982);
091
092 private static final Map<Integer,PROPERTY> lookup = new HashMap<Integer,PROPERTY>();
093
094 static {
095 for(PROPERTY s : EnumSet.allOf(PROPERTY.class))
096 lookup.put(s.getId(), s);
097 }
098
099 private final int id;
100
101 private PROPERTY(int value) {
102 this.id = value;
103 }
104
105 public int getId() { return id; }
106
107 public static PROPERTY get(int code) {
108 return lookup.get(code);
109 }
110
111 public static PROPERTY fromString(String s) {
112 for (PROPERTY p : lookup.values()) {
113 if (p.toString() == s) {
114 return p;
115 }
116 }
117 return null;
118 }
119 }
120
121 public Object GetPropertyAsEnum(int propid) {
122 return PROPERTY.get(propid);
123 }
124
125 public String GetStrProperty(PROPERTY prop) {
126 //check in propcache if so then return
127 if (mPropCache.containsKey(new Integer(prop.id))){
128 String value = (String)mPropCache.get(prop.id);
129 if (value != null && !(value.length() == 0) ){
130 return value;
131 }
132 }
133 //else get from skypekit...
134 GetPropertyRequest request = new GetPropertyRequest(9, mObjectId, prop.id);
135
136 String string = null;
137 GetPropertyResponse r = skype.GetProperty(request);
138 if (r != null){
139 string = r.GetAsString();
140 }
141
142 if (string != null)
143 {
144 mPropCache.put(new Integer(prop.id), string);
145 }
146 return string;
147 }
148
149 public int GetIntProperty(PROPERTY prop) {
150 //check in propcache if so then return
151 if (mPropCache.containsKey(new Integer(prop.id))){
152 int value = ((Integer)mPropCache.get(prop.id)).intValue();
153 if (value != 0){
154 return value;
155 }
156 }
157 //else get from skypekit...
158 GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
159
160 Integer integer = null;
161 GetPropertyResponse r = skype.GetProperty(request);
162 if (r != null){
163 integer = r.GetAsInt();
164 }
165
166 if (integer != null)
167 {
168 mPropCache.put(new Integer(prop.id), integer);
169 return integer.intValue();
170 }
171 else
172 {
173 return 0;
174 }
175 }
176
177 public boolean GetBooleanProperty(PROPERTY prop) {
178 //check in propcache if so then return
179 if (mPropCache.containsKey(new Integer(prop.id))){
180 return ((Boolean)mPropCache.get(prop.id)).booleanValue();
181 }
182 //else get from skypekit...
183 GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
184
185 Boolean boolResp = null;
186 GetPropertyResponse r = skype.GetProperty(request);
187 if (r != null){
188 boolResp = r.GetAsBoolean();
189 }
190
191 if (boolResp != null)
192 {
193 mPropCache.put(new Integer(prop.id), boolResp);
194 return boolResp.booleanValue();
195 }
196 else
197 {
198 return false;
199 }
200 }
201
202 public byte [] GetBinProperty(PROPERTY prop) {
203 //get from skypekit...
204 GetPropertyRequest request = new GetPropertyRequest(9, mObjectId, prop.id);
205
206 byte [] data = null;
207 GetPropertyResponse r = skype.GetProperty(request);
208 if (r != null) {
209 data = r.GetAsBinary();
210 }
211 return data;
212 }
213
214 /**default array of Message Properties that get fetched & cached upon class construction*/
215 private static PROPERTY [] defaultProperties = { PROPERTY.convo_id, PROPERTY.type, PROPERTY.author, PROPERTY.author_displayname, PROPERTY.identities, PROPERTY.timestamp, PROPERTY.body_xml, PROPERTY.sending_status, PROPERTY.consumption_status};
216
217 private void GetDefaultProps() {
218 MultiGetPropertyRequest request = null;
219 ArrayList<Integer> proparray = null;
220 /**Add the single oid into array*/
221 ArrayList<Integer> oidarray=new ArrayList<Integer>();
222 oidarray.add(mObjectId);
223
224 /**Add all requested propids into array*/
225 proparray=new ArrayList<Integer>();
226 for (PROPERTY defaultProp : defaultProperties) {
227 proparray.add(defaultProp.getId());
228 }
229 /**Generate the request*/
230 request = new MultiGetPropertyRequest(moduleID(), oidarray,proparray);
231
232 /** Make Multi Get call*/
233 GetPropertyResponse r=skype.MultiGetProperty(request);
234 /**Verify that it is a proper multiresponse*/
235 if(!r.isMultiresponse())
236 {
237 return;
238 }
239 /**update property cache with results*/
240 mPropCache.putAll(r.GetAsMap(mObjectId, proparray));
241 }
242
243 /**
244 The P_TYPE property determines the actual meaning of the Message object. Only Messages of POSTED_TEXT type contain actual text messages. The meaning and content of the rest of the message properties are largely dependant of the value of the Message.P_TYPE. <br> */
245 public enum TYPE {
246
247 /** Conference metadata were changed*/
248 SET_METADATA(2),
249
250 /** A conference was spawned from this dialog*/
251 SPAWNED_CONFERENCE(4),
252
253 /** Some users were added to the conference*/
254 ADDED_CONSUMERS(10),
255
256 /** Some users are applying to be added to the conference*/
257 ADDED_APPLICANTS(11),
258
259 /** User was kicked from the conference*/
260 RETIRED_OTHERS(12),
261
262 /** User left the conference*/
263 RETIRED(13),
264
265 /** Changed the rank of a user in the Conversation (multichat administration) <br>*/
266 SET_RANK(21),
267
268 /** A live session started*/
269 STARTED_LIVESESSION(30),
270
271 /** A live session ended*/
272 ENDED_LIVESESSION(39),
273
274 /** User requested authorization*/
275 REQUESTED_AUTH(50),
276
277 /** User was granted authorization. Notification message that user is now an authorized contact (of the local user). <br>*/
278 GRANTED_AUTH(51),
279
280 /** User was blocked*/
281 BLOCKED(53),
282
283 /** A text message*/
284 POSTED_TEXT(61),
285
286 /** An emote ('John Doe is laughing', cf /me chat command)*/
287 POSTED_EMOTE(60),
288
289 /** The message represents (a set of) contact card(s) posted in the conversation. One message can contain more than one contact cards. The contacts can be retrieved from the message by parsing them out from the P_BODY_XML property. For more information, see Conversation.PostContacts <br>*/
290 POSTED_CONTACTS(63),
291
292 /** The message represents an SMS object that was posted in the Conversation. See Conversation.PostSMS for more details. The Sms object itself can be retrieved from the Message with Message.GetSms The message BODY_XML contains a set of SMS properties, such as status, failurereason, targets, price and timestamp. <br>*/
293 POSTED_SMS(64),
294
295 /** Deprecated, never sent*/
296 POSTED_ALERT(65),
297
298 /** A voicemail*/
299 POSTED_VOICE_MESSAGE(67),
300
301 /** The message represents a (list of) file transfers that were posted in the Conversation with Conversation.PostFiles. Transfer objects can be retrieved from the Message with Message.GetTransfers <br>*/
302 POSTED_FILES(68),
303
304 /** Currently unused. <br>*/
305 POSTED_INVOICE(69),
306
307 /** The message represents a Contact birthday notification. <br>*/
308 HAS_BIRTHDAY(110);
309
310 private static final Map<Integer,TYPE> lookup = new HashMap<Integer,TYPE>();
311
312 static {
313 for(TYPE s : EnumSet.allOf(TYPE.class))
314 lookup.put(s.getId(), s);
315 }
316
317 private final int id;
318
319 private TYPE(int value) {
320 this.id = value;
321 }
322
323 public int getId() { return id; }
324
325 public static TYPE get(int code) {
326 return lookup.get(code);
327 }
328
329 public static TYPE fromString(String s) {
330 for (TYPE p : lookup.values()) {
331 if (p.toString() == s) {
332 return p;
333 }
334 }
335 return null;
336 }
337 }
338
339 /**
340 */
341 public enum SENDING_STATUS {
342
343 /** Message has not been delivered to at least one of the participants <br>*/
344 SENDING(1),
345
346 /** Message has been delivered to at least one other participant <br>*/
347 SENT(2),
348
349 /** Message could not be delivered (for SMS this reflects the actual SMS, not the chat message) <br>*/
350 FAILED_TO_SEND(3);
351
352 private static final Map<Integer,SENDING_STATUS> lookup = new HashMap<Integer,SENDING_STATUS>();
353
354 static {
355 for(SENDING_STATUS s : EnumSet.allOf(SENDING_STATUS.class))
356 lookup.put(s.getId(), s);
357 }
358
359 private final int id;
360
361 private SENDING_STATUS(int value) {
362 this.id = value;
363 }
364
365 public int getId() { return id; }
366
367 public static SENDING_STATUS get(int code) {
368 return lookup.get(code);
369 }
370
371 public static SENDING_STATUS fromString(String s) {
372 for (SENDING_STATUS p : lookup.values()) {
373 if (p.toString() == s) {
374 return p;
375 }
376 }
377 return null;
378 }
379 }
380
381 /**
382 Indicates if a message has been consumed (meaning read) or not */
383 public enum CONSUMPTION_STATUS {
384
385 /** Message has been read. Note that this is a read-only property. Consumption status of individual messages can not be set selectively. Message consumption status is determined at the conversation level, based conversation consumption horizon and individual message timestamps. Conversation consumption horizon can be updated with Conversation.SetConsumedHorizon method. <br>*/
386 CONSUMED(0),
387
388 /** Do not notify the user that they have this unread message <br>*/
389 UNCONSUMED_SUPPRESSED(1),
390
391 /** Notify the user that they have this unread message <br>*/
392 UNCONSUMED_NORMAL(2),
393
394 /** This message consumption state is marked as DEPRECATED <br>*/
395 UNCONSUMED_ELEVATED(3);
396
397 private static final Map<Integer,CONSUMPTION_STATUS> lookup = new HashMap<Integer,CONSUMPTION_STATUS>();
398
399 static {
400 for(CONSUMPTION_STATUS s : EnumSet.allOf(CONSUMPTION_STATUS.class))
401 lookup.put(s.getId(), s);
402 }
403
404 private final int id;
405
406 private CONSUMPTION_STATUS(int value) {
407 this.id = value;
408 }
409
410 public int getId() { return id; }
411
412 public static CONSUMPTION_STATUS get(int code) {
413 return lookup.get(code);
414 }
415
416 public static CONSUMPTION_STATUS fromString(String s) {
417 for (CONSUMPTION_STATUS p : lookup.values()) {
418 if (p.toString() == s) {
419 return p;
420 }
421 }
422 return null;
423 }
424 }
425
426 /**
427 For messages of type SET_METADATA that alert participants to changes to the associated Conversation's metadata, indicates which metadata property changed and its P_BODY_XML property contains the changed data. Your UI is expected to detect messages with PARAM_KEY set and to update its visual representation of Conversation accordingly. <br>You can use the associated Conversation's properties and methods to obtain the updated metadata rather than parse the message body XML, for example, Conversation.P_META_PICTURE and Conversation.Conversation.GetPropMetaPicture. <br> */
428 public enum SET_METADATA_KEY {
429
430 /** Notification message that conversation name has changed. <br>*/
431 SET_META_NAME(3640),
432
433 /** Notification message that conversation topic has changed. <br>*/
434 SET_META_TOPIC(3644),
435
436 /** Notification message that conversation guidelines have changed. <br>*/
437 SET_META_GUIDELINES(3652),
438
439 /** Notification message that conversation picture has changed. <br>*/
440 SET_META_PICTURE(3658);
441
442 private static final Map<Integer,SET_METADATA_KEY> lookup = new HashMap<Integer,SET_METADATA_KEY>();
443
444 static {
445 for(SET_METADATA_KEY s : EnumSet.allOf(SET_METADATA_KEY.class))
446 lookup.put(s.getId(), s);
447 }
448
449 private final int id;
450
451 private SET_METADATA_KEY(int value) {
452 this.id = value;
453 }
454
455 public int getId() { return id; }
456
457 public static SET_METADATA_KEY get(int code) {
458 return lookup.get(code);
459 }
460
461 public static SET_METADATA_KEY fromString(String s) {
462 for (SET_METADATA_KEY p : lookup.values()) {
463 if (p.toString() == s) {
464 return p;
465 }
466 }
467 return null;
468 }
469 }
470
471 /**
472 Indicates the reason a user could not join or left a Conversation. SkypeKit automatically sets "could not join"-related values. "Left voluntarily"-related values are set as a result of explicit user actions. <br> */
473 public enum LEAVEREASON {
474
475 /** User cannot chat (user is currently logged in with a client that has chat disabled - see Contact.CAPABILITY.CAPABILITY_TEXT) <br>*/
476 USER_INCAPABLE(2),
477
478 /** Attempt to add local user to a conversation by an unknown contact <br>*/
479 ADDER_MUST_BE_FRIEND(3),
480
481 /** Attempt to add local user to a conversation by an unauthorized contact <br>*/
482 ADDER_MUST_BE_AUTHORIZED(4),
483
484 /** Local user declined an "invitation" to join a chat <br>*/
485 DECLINE_ADD(5),
486
487 /** User decided to end participation in an on-going multi-chat <br>*/
488 UNSUBSCRIBE(6);
489
490 private static final Map<Integer,LEAVEREASON> lookup = new HashMap<Integer,LEAVEREASON>();
491
492 static {
493 for(LEAVEREASON s : EnumSet.allOf(LEAVEREASON.class))
494 lookup.put(s.getId(), s);
495 }
496
497 private final int id;
498
499 private LEAVEREASON(int value) {
500 this.id = value;
501 }
502
503 public int getId() { return id; }
504
505 public static LEAVEREASON get(int code) {
506 return lookup.get(code);
507 }
508
509 public static LEAVEREASON fromString(String s) {
510 for (LEAVEREASON p : lookup.values()) {
511 if (p.toString() == s) {
512 return p;
513 }
514 }
515 return null;
516 }
517 }
518
519 /**
520 *For Message types having a body, determines whether that body is editable by the user. <br>
521 * @return result
522 */
523 public boolean CanEdit() {
524
525 Request request = null;
526 try {
527 request = new XCallRequest(9,1);
528 } catch (IOException e) {
529 e.printStackTrace();
530 if (skype.errorListener != null)
531 skype.errorListener.OnSkypeKitFatalError();
532 }
533 request.addParm('O',0,mObjectId);
534
535 Response r = skype.XCall((XCallRequest)request);
536
537 if (r.isErrCall())
538 return false;
539
540 boolean result = false;
541 result = r.GetAsBoolean(1);
542 return result;
543 }
544
545 /**
546 *For Message types that include a body and are editable: <br> - alters BODY_XML of the message object <br> - sets EDITED_BY and EDIT_TIMESTAMP properties <br> - propagates the changes to remote users. <br>
547 * @param newText New value of the message BODY_XML property. <br>
548 * @param isXML Specify isXML as true if the message body is formatted as XML; omit it or specify it as false if the message body is plain text. <br>
549 */
550 public void Edit( String newText, boolean isXML) {
551
552 Request request = null;
553 try {
554 request = new XCallRequest(9,2);
555 } catch (IOException e) {
556 e.printStackTrace();
557 if (skype.errorListener != null)
558 skype.errorListener.OnSkypeKitFatalError();
559 }
560 request.addParm('O',0,mObjectId);
561 request.addParm('S',1,newText);
562 request.addParm('b',2,isXML);
563
564 skype.XCall((XCallRequest)request);
565 }
566
567 /**
568 *For messages of type POSTED_CONTACTS, parses the body XML and formats the data as a list of Contact instances. <br>
569 * @return contacts
570 */
571 public Contact [] GetContacts() {
572
573 Request request = null;
574 try {
575 request = new XCallRequest(9,3);
576 } catch (IOException e) {
577 e.printStackTrace();
578 if (skype.errorListener != null)
579 skype.errorListener.OnSkypeKitFatalError();
580 }
581 request.addParm('O',0,mObjectId);
582
583 Response r = skype.XCall((XCallRequest)request);
584
585 if (r.isErrCall())
586 return null;
587
588 Vector<Contact> contacts = new Vector<Contact>();
589 while (r.HasMore(1))
590 {
591 int oid = 0;
592 Contact contact = null;
593 oid = r.GetOid(1);
594 if (oid != AbstractDecoder.NULL_VALUE) {
595 contact = (Contact)skype.factory(Contact.moduleID(), oid, skype);
596 }
597 contacts.add(contact);
598 }
599 return contacts.toArray(new Contact[contacts.size()]);
600
601 }
602
603 /**
604 *For messages of type POSTED_FILES, parses the body XML and creates a list of Transfer instances. <br>
605 * @return transfers
606 */
607 public Transfer [] GetTransfers() {
608
609 Request request = null;
610 try {
611 request = new XCallRequest(9,4);
612 } catch (IOException e) {
613 e.printStackTrace();
614 if (skype.errorListener != null)
615 skype.errorListener.OnSkypeKitFatalError();
616 }
617 request.addParm('O',0,mObjectId);
618
619 Response r = skype.XCall((XCallRequest)request);
620
621 if (r.isErrCall())
622 return null;
623
624 Vector<Transfer> transfers = new Vector<Transfer>();
625 while (r.HasMore(1))
626 {
627 int oid = 0;
628 Transfer transfer = null;
629 oid = r.GetOid(1);
630 if (oid != AbstractDecoder.NULL_VALUE) {
631 transfer = (Transfer)skype.factory(Transfer.moduleID(), oid, skype);
632 }
633 transfers.add(transfer);
634 }
635 return transfers.toArray(new Transfer[transfers.size()]);
636
637 }
638
639 /**
640 *For messages of type POSTED_VOICE_MESSAGE, parses the body XML and creates a Voicemail instance. <br>
641 * @return voicemail
642 */
643 public Voicemail GetVoiceMessage() {
644
645 Request request = null;
646 try {
647 request = new XCallRequest(9,5);
648 } catch (IOException e) {
649 e.printStackTrace();
650 if (skype.errorListener != null)
651 skype.errorListener.OnSkypeKitFatalError();
652 }
653 request.addParm('O',0,mObjectId);
654
655 Response r = skype.XCall((XCallRequest)request);
656
657 if (r.isErrCall())
658 return null;
659
660 int oid = 0;
661 Voicemail voicemail = null;
662 oid = r.GetOid(1);
663 if (oid != AbstractDecoder.NULL_VALUE) {
664 voicemail = (Voicemail)skype.factory(Voicemail.moduleID(), oid, skype);
665 }
666 return voicemail;
667 }
668
669 /**
670 *For messages of type POSTED_SMS, parses the body XML and creates an SMS instances <br>
671 * @return sms
672 */
673 public Sms GetSMS() {
674
675 Request request = null;
676 try {
677 request = new XCallRequest(9,6);
678 } catch (IOException e) {
679 e.printStackTrace();
680 if (skype.errorListener != null)
681 skype.errorListener.OnSkypeKitFatalError();
682 }
683 request.addParm('O',0,mObjectId);
684
685 Response r = skype.XCall((XCallRequest)request);
686
687 if (r.isErrCall())
688 return null;
689
690 int oid = 0;
691 Sms sms = null;
692 oid = r.GetOid(1);
693 if (oid != AbstractDecoder.NULL_VALUE) {
694 sms = (Sms)skype.factory(Sms.moduleID(), oid, skype);
695 }
696 return sms;
697 }
698
699 /**
700 *Deletes this message from the local database. These deletions do not propagate to the other Skype instances that the user may have on other computers. Nor do they affect other participants that have the same message. This method is specifically from removing Message objects from the database - not for removing Messages from conversations. To remove a Message from a conversation, use Message.Edit method to replace the existing body text with an empty string. <br>
701 */
702 public void DeleteLocally() {
703
704 Request request = null;
705 try {
706 request = new XCallRequest(9,8);
707 } catch (IOException e) {
708 e.printStackTrace();
709 if (skype.errorListener != null)
710 skype.errorListener.OnSkypeKitFatalError();
711 }
712 request.addParm('O',0,mObjectId);
713
714 skype.XCall((XCallRequest)request);
715 }
716
717
718 }