001 package com.skype.api;
002
003 import com.skype.ipc.SidRoot;
004 import com.skype.ipc.SidObject;
005 import com.skype.ipc.EnumConverting;
006 import com.skype.ipc.PropertyEnumConverting;
007 import com.skype.ipc.Decoding;
008 import com.skype.ipc.Encoding;
009 import com.skype.ipc.Encoding;
010 import java.io.IOException;
011 import com.skype.ipc.PropertyEnumConverting;
012 import com.skype.ipc.SidGetResponding;
013
014 /**
015 * Wrapper class that includes SMS-specific properties and methods, such as P_BODY and GetTargetPrice. Instantiate SMS instances using Skype.CreateOutgoingSms; post SMS messages to a Conversation using Conversation.PostSMS.
016 *
017 * Each SMS can have multiple targets (normalized phone numbers). Note that in a Conversation context, every SMS instance has a corresponding Message instance. Once you've posted an SMS, you can retrieve its corresponding Message instance using Sms.GetPropChatmsgId. That Message instance's P_BODY_XML property contains the SMS message data, such as price, target phone number(s), failure codes, and so forth, which you can parsed out and display in the UI. To put it another way, the object chain goes like this:
018 *
019 * @code
020 * Conversation->Message->SMS
021 * </CODE>
022 *
023 * Note that SkypeKit SDK supports outgoing SMS messages only. SkypeKit clients, even when logged in with accounts that have SkypeIn numbers, cannot receive SMS messages.
024 */
025 public final class Sms extends SidObject {
026 public enum Type implements EnumConverting {
027 /** a normal outgoing SMS message */
028 OUTGOING (2),
029 /** a message requesting a SMS confirmation code be sent to the number provided */
030 CONFIRMATION_CODE_REQUEST(3),
031 /** a message returning the SMS confirmation code received as a result of a CONFIRMATION_CODE_REQUEST to authorize it */
032 CONFIRMATION_CODE_SUBMIT (4);
033 private final int key;
034 Type(int key) {
035 this.key = key;
036 };
037 public int getId() { return key; }
038 public EnumConverting getDefault() { return OUTGOING; }
039 public EnumConverting convert(int from) { return Type.get(from); }
040 public EnumConverting[] getArray(final int size) { return new Type[size]; }
041 public static Type get(int from) {
042 switch (from) {
043 case 2: return OUTGOING;
044 case 3: return CONFIRMATION_CODE_REQUEST;
045 case 4: return CONFIRMATION_CODE_SUBMIT;
046 }
047 return OUTGOING;
048 }
049 public static final int OUTGOING_VALUE = 2;
050 public static final int CONFIRMATION_CODE_REQUEST_VALUE = 3;
051 public static final int CONFIRMATION_CODE_SUBMIT_VALUE = 4;
052 }
053 public enum Status implements EnumConverting {
054 COMPOSING (3),
055 SENDING_TO_SERVER (4),
056 SENT_TO_SERVER (5),
057 DELIVERED (6),
058 SOME_TARGETS_FAILED(7),
059 FAILED (8);
060 private final int key;
061 Status(int key) {
062 this.key = key;
063 };
064 public int getId() { return key; }
065 public EnumConverting getDefault() { return COMPOSING; }
066 public EnumConverting convert(int from) { return Status.get(from); }
067 public EnumConverting[] getArray(final int size) { return new Status[size]; }
068 public static Status get(int from) {
069 switch (from) {
070 case 3: return COMPOSING;
071 case 4: return SENDING_TO_SERVER;
072 case 5: return SENT_TO_SERVER;
073 case 6: return DELIVERED;
074 case 7: return SOME_TARGETS_FAILED;
075 case 8: return FAILED;
076 }
077 return COMPOSING;
078 }
079 public static final int COMPOSING_VALUE = 3;
080 public static final int SENDING_TO_SERVER_VALUE = 4;
081 public static final int SENT_TO_SERVER_VALUE = 5;
082 public static final int DELIVERED_VALUE = 6;
083 public static final int SOME_TARGETS_FAILED_VALUE = 7;
084 public static final int FAILED_VALUE = 8;
085 }
086 public enum FailureReason implements EnumConverting {
087 MISC_ERROR (1),
088 SERVER_CONNECT_FAILED (2),
089 NO_SMS_CAPABILITY (3),
090 INSUFFICIENT_FUNDS (4),
091 INVALID_CONFIRMATION_CODE(5),
092 USER_BLOCKED (6),
093 IP_BLOCKED (7),
094 NODE_BLOCKED (8),
095 NO_SENDERID_CAPABILITY (9);
096 private final int key;
097 FailureReason(int key) {
098 this.key = key;
099 };
100 public int getId() { return key; }
101 public EnumConverting getDefault() { return MISC_ERROR; }
102 public EnumConverting convert(int from) { return FailureReason.get(from); }
103 public EnumConverting[] getArray(final int size) { return new FailureReason[size]; }
104 public static FailureReason get(int from) {
105 switch (from) {
106 case 1: return MISC_ERROR;
107 case 2: return SERVER_CONNECT_FAILED;
108 case 3: return NO_SMS_CAPABILITY;
109 case 4: return INSUFFICIENT_FUNDS;
110 case 5: return INVALID_CONFIRMATION_CODE;
111 case 6: return USER_BLOCKED;
112 case 7: return IP_BLOCKED;
113 case 8: return NODE_BLOCKED;
114 case 9: return NO_SENDERID_CAPABILITY;
115 }
116 return MISC_ERROR;
117 }
118 public static final int MISC_ERROR_VALUE = 1;
119 public static final int SERVER_CONNECT_FAILED_VALUE = 2;
120 public static final int NO_SMS_CAPABILITY_VALUE = 3;
121 public static final int INSUFFICIENT_FUNDS_VALUE = 4;
122 public static final int INVALID_CONFIRMATION_CODE_VALUE = 5;
123 public static final int USER_BLOCKED_VALUE = 6;
124 public static final int IP_BLOCKED_VALUE = 7;
125 public static final int NODE_BLOCKED_VALUE = 8;
126 public static final int NO_SENDERID_CAPABILITY_VALUE = 9;
127 }
128 public enum TargetStatus implements EnumConverting {
129 TARGET_ANALYZING (1),
130 TARGET_UNDEFINED (2),
131 TARGET_ACCEPTABLE (3),
132 TARGET_NOT_ROUTABLE (4),
133 TARGET_DELIVERY_PENDING (5),
134 TARGET_DELIVERY_SUCCESSFUL(6),
135 TARGET_DELIVERY_FAILED (7);
136 private final int key;
137 TargetStatus(int key) {
138 this.key = key;
139 };
140 public int getId() { return key; }
141 public EnumConverting getDefault() { return TARGET_ANALYZING; }
142 public EnumConverting convert(int from) { return TargetStatus.get(from); }
143 public EnumConverting[] getArray(final int size) { return new TargetStatus[size]; }
144 public static TargetStatus get(int from) {
145 switch (from) {
146 case 1: return TARGET_ANALYZING;
147 case 2: return TARGET_UNDEFINED;
148 case 3: return TARGET_ACCEPTABLE;
149 case 4: return TARGET_NOT_ROUTABLE;
150 case 5: return TARGET_DELIVERY_PENDING;
151 case 6: return TARGET_DELIVERY_SUCCESSFUL;
152 case 7: return TARGET_DELIVERY_FAILED;
153 }
154 return TARGET_ANALYZING;
155 }
156 public static final int TARGET_ANALYZING_VALUE = 1;
157 public static final int TARGET_UNDEFINED_VALUE = 2;
158 public static final int TARGET_ACCEPTABLE_VALUE = 3;
159 public static final int TARGET_NOT_ROUTABLE_VALUE = 4;
160 public static final int TARGET_DELIVERY_PENDING_VALUE = 5;
161 public static final int TARGET_DELIVERY_SUCCESSFUL_VALUE = 6;
162 public static final int TARGET_DELIVERY_FAILED_VALUE = 7;
163 }
164 public enum SetBodyResult implements EnumConverting {
165 /** body not set. message status wrong or invalid, or body not valid utf8 string */
166 BODY_INVALID (0),
167 /** body too long. set, but truncated. charsUntilNextChunk contains maxChunks value */
168 BODY_TRUNCATED (1),
169 /** body was set OK */
170 BODY_OK (2),
171 /** last unicode char was ignored, as some of the text would be deleted due to conversion */
172 BODY_LASTCHAR_IGNORED(3);
173 private final int key;
174 SetBodyResult(int key) {
175 this.key = key;
176 };
177 public int getId() { return key; }
178 public EnumConverting getDefault() { return BODY_INVALID; }
179 public EnumConverting convert(int from) { return SetBodyResult.get(from); }
180 public EnumConverting[] getArray(final int size) { return new SetBodyResult[size]; }
181 public static SetBodyResult get(int from) {
182 switch (from) {
183 case 0: return BODY_INVALID;
184 case 1: return BODY_TRUNCATED;
185 case 2: return BODY_OK;
186 case 3: return BODY_LASTCHAR_IGNORED;
187 }
188 return BODY_INVALID;
189 }
190 public static final int BODY_INVALID_VALUE = 0;
191 public static final int BODY_TRUNCATED_VALUE = 1;
192 public static final int BODY_OK_VALUE = 2;
193 public static final int BODY_LASTCHAR_IGNORED_VALUE = 3;
194 }
195 public enum ConfirmType implements EnumConverting {
196 /** Confirm mobile number as SMS sender number */
197 ID_SMS (1),
198 /** Confirm mobile number as CLI for SkypeOut calls */
199 ID_MOBILE (2),
200 /** unused currently */
201 ID_SKYPEIN(3);
202 private final int key;
203 ConfirmType(int key) {
204 this.key = key;
205 };
206 public int getId() { return key; }
207 public EnumConverting getDefault() { return ID_SMS; }
208 public EnumConverting convert(int from) { return ConfirmType.get(from); }
209 public EnumConverting[] getArray(final int size) { return new ConfirmType[size]; } public static ConfirmType get(int from) {
210 switch (from) {
211 case 1: return ID_SMS;
212 case 2: return ID_MOBILE;
213 case 3: return ID_SKYPEIN;
214 }
215 return ID_SMS;
216 }
217 public static final int ID_SMS_VALUE = 1;
218 public static final int ID_MOBILE_VALUE = 2;
219 public static final int ID_SKYPEIN_VALUE = 3;
220 }
221 private final static byte[] P_TYPE_req = {(byte) 90,(byte) 71,(byte) 190,(byte) 1,(byte) 93,(byte) 12};
222 private final static byte[] P_STATUS_req = {(byte) 90,(byte) 71,(byte) 191,(byte) 1,(byte) 93,(byte) 12};
223 private final static byte[] P_FAILURE_REASON_req = {(byte) 90,(byte) 71,(byte) 192,(byte) 1,(byte) 93,(byte) 12};
224 private final static byte[] P_IS_FAILED_UNSEEN_req = {(byte) 90,(byte) 71,(byte) 48,(byte) 93,(byte) 12};
225 private final static byte[] P_TIMESTAMP_req = {(byte) 90,(byte) 71,(byte) 198,(byte) 1,(byte) 93,(byte) 12};
226 private final static byte[] P_PRICE_req = {(byte) 90,(byte) 71,(byte) 193,(byte) 1,(byte) 93,(byte) 12};
227 private final static byte[] P_PRICE_PRECISION_req = {(byte) 90,(byte) 71,(byte) 49,(byte) 93,(byte) 12};
228 private final static byte[] P_PRICE_CURRENCY_req = {(byte) 90,(byte) 71,(byte) 194,(byte) 1,(byte) 93,(byte) 12};
229 private final static byte[] P_REPLY_TO_NUMBER_req = {(byte) 90,(byte) 71,(byte) 199,(byte) 1,(byte) 93,(byte) 12};
230 private final static byte[] P_TARGET_NUMBERS_req = {(byte) 90,(byte) 71,(byte) 195,(byte) 1,(byte) 93,(byte) 12};
231 private final static byte[] P_TARGET_STATUSES_req = {(byte) 90,(byte) 71,(byte) 196,(byte) 1,(byte) 93,(byte) 12};
232 private final static byte[] P_BODY_req = {(byte) 90,(byte) 71,(byte) 197,(byte) 1,(byte) 93,(byte) 12};
233 private final static byte[] P_CHAT_MSG_req = {(byte) 90,(byte) 71,(byte) 200,(byte) 6,(byte) 93,(byte) 12};
234 /** Properties of the Sms class */
235 public enum Property implements PropertyEnumConverting {
236 P_UNKNOWN (0,0,null,0,null),
237 P_TYPE (190, 1, P_TYPE_req, 0, Type.get(0)),
238 P_STATUS (191, 2, P_STATUS_req, 0, Status.get(0)),
239 P_FAILURE_REASON (192, 3, P_FAILURE_REASON_req, 0, FailureReason.get(0)),
240 P_IS_FAILED_UNSEEN(48, 4, P_IS_FAILED_UNSEEN_req, 0, null),
241 P_TIMESTAMP (198, 5, P_TIMESTAMP_req, 0, null),
242 P_PRICE (193, 6, P_PRICE_req, 0, null),
243 P_PRICE_PRECISION (49, 7, P_PRICE_PRECISION_req, 0, null),
244 P_PRICE_CURRENCY (194, 8, P_PRICE_CURRENCY_req, 0, null),
245 P_REPLY_TO_NUMBER (199, 9, P_REPLY_TO_NUMBER_req, 0, null),
246 P_TARGET_NUMBERS (195, 10, P_TARGET_NUMBERS_req, 0, null),
247 P_TARGET_STATUSES (196, 11, P_TARGET_STATUSES_req, 0, null),
248 P_BODY (197, 12, P_BODY_req, 0, null),
249 P_CHAT_MSG (840, 13, P_CHAT_MSG_req, 9, null);
250 private final int key;
251 private final int idx;
252 private final byte[] req;
253 private final int mod;
254 private final EnumConverting enumConverter;
255 Property(int key, int idx, byte[] req, int mod, EnumConverting converter) {
256 this.key = key;
257 this.idx = idx;
258 this.req = req;
259 this.mod = mod;
260 this.enumConverter = converter;
261 };
262 public boolean isCached() { return idx > 0; }
263 public int getIdx() { return idx; }
264 public int getId() { return key; }
265 public byte[] getRequest() { return req; }
266 public EnumConverting getDefault() { return P_UNKNOWN; }
267 public int getModuleId() { return mod; }
268 public EnumConverting getEnumConverter() { return enumConverter; }
269 public EnumConverting convert(final int from) { return Property.get(from); }
270 public EnumConverting[] getArray(final int size) { return new Property[size]; }
271 public static Property get(final int from) {
272 switch (from) {
273 case 190: return P_TYPE;
274 case 191: return P_STATUS;
275 case 192: return P_FAILURE_REASON;
276 case 48: return P_IS_FAILED_UNSEEN;
277 case 198: return P_TIMESTAMP;
278 case 193: return P_PRICE;
279 case 49: return P_PRICE_PRECISION;
280 case 194: return P_PRICE_CURRENCY;
281 case 199: return P_REPLY_TO_NUMBER;
282 case 195: return P_TARGET_NUMBERS;
283 case 196: return P_TARGET_STATUSES;
284 case 197: return P_BODY;
285 case 840: return P_CHAT_MSG;
286 }
287 return P_UNKNOWN;
288 }
289 public static final int P_TYPE_VALUE = 190;
290 public static final int P_STATUS_VALUE = 191;
291 public static final int P_FAILURE_REASON_VALUE = 192;
292 public static final int P_IS_FAILED_UNSEEN_VALUE = 48;
293 public static final int P_TIMESTAMP_VALUE = 198;
294 public static final int P_PRICE_VALUE = 193;
295 public static final int P_PRICE_PRECISION_VALUE = 49;
296 public static final int P_PRICE_CURRENCY_VALUE = 194;
297 public static final int P_REPLY_TO_NUMBER_VALUE = 199;
298 public static final int P_TARGET_NUMBERS_VALUE = 195;
299 public static final int P_TARGET_STATUSES_VALUE = 196;
300 public static final int P_BODY_VALUE = 197;
301 public static final int P_CHAT_MSG_VALUE = 840;
302 }
303 private final static byte[] getTargetStatus_req = {(byte) 90,(byte) 82,(byte) 12,(byte) 4};
304 /** Retrieves the send status of this SMS to a particular recipient (P_TARGET_STATUSES) either prior to or after invoking Conversation.PostSMS. * @param target The normalized phone number of the target recipient.
305 * @return status The send status of the target recipient, for example, TARGET_ANALYZING, TARGET_DELIVERY_PENDING, TARGET_DELIVERY_SUCCESSFUL, TARGET_DELIVERY_FAILED, and so forth. TARGET_UNDEFINED implies that the specified target is not a recipient of this SMS.
306 */
307 public TargetStatus getTargetStatus(String target) {
308 try {
309 return (TargetStatus) sidDoRequest(getTargetStatus_req)
310 .addStringParm(1, target)
311 .endRequest().getEnumParm(1, TargetStatus.get(0), true);
312 } catch(IOException e) {
313 mSidRoot.sidOnFatalError(e);
314 return TargetStatus.get(0)
315 ;}
316 }
317 private final static byte[] getTargetPrice_req = {(byte) 90,(byte) 82,(byte) 12,(byte) 13};
318 /**
319 * Retrieves the amount of Skype credit necessary to send the SMS to a particular recipient. Defaults to -1 on instantiation and set only when that recipient's status reflects TARGET_ACCEPTABLE. Use Sms.GetPropPrice to retrieve the total cost of this SMS.
320 *
321 * Note that the target price is an integer value. Calculate the actual price (in units specified by P_PRICE_CURRENCY) using P_PRICE_PRECISION as:
322 * @code
323 * actualTargetPrice = targetPrice / 10^pricePrecision;
324 * </CODE>
325 * @param target The normalized phone number of the target recipient.
326 * @return price The price of sending this SMS message to the target recipient.
327 */
328 public int getTargetPrice(String target) {
329 try {
330 return sidDoRequest(getTargetPrice_req)
331 .addStringParm(1, target)
332 .endRequest().getUintParm(1, true);
333 } catch(IOException e) {
334 mSidRoot.sidOnFatalError(e);
335 return 0
336 ;}
337 }
338 private final static byte[] setTargets_req = {(byte) 90,(byte) 82,(byte) 12,(byte) 6};
339 /** Sets the recipient(s) of this SMS. Note that each invocation replaces the target list and re-calculates all prices - they are not additive! * @param numbers Normalized phone number(s) of the intended recipient(s).
340 * @return success Set to true if the target list appears to contain valid, normalized telephone numbers. Note that this check is not very reliable. Actual target validity checking occurs asynchronously in the background, and manifests itself as a series of Sms.P_TARGET_STATUSES property change events.
341 */
342 public boolean setTargets(String[] numbers) {
343 try {
344 return sidDoRequest(setTargets_req)
345 .addStringListParm(1, numbers)
346 .endRequest().getBoolParm(1, true);
347 } catch(IOException e) {
348 mSidRoot.sidOnFatalError(e);
349 return false
350 ;}
351 }
352 private final static byte[] setBody_req = {(byte) 90,(byte) 82,(byte) 12,(byte) 7};
353 public class SetBodyResponse {
354 public SetBodyResult result;
355 public String[] chunks;
356 public int charsUntilNextChunk;
357 };
358
359 /** -The- method for setting the body text of this SMS. While Conversation.PostSMS does have a body argument, that argument is currently unused. * @param text Message body text.
360 * @return SetBodyResponse
361 * <br> - result Whether the Message body was successfully set and if not, why not.
362 * <br> - chunks The Message body as a list of individual chunks. * <br> - charsUntilNextChunk Number of available characters until creation of the next chunk becomes necessary.
363 */
364 public SetBodyResponse setBody(String text) {
365 try {
366 Decoding decoder = sidDoRequest(setBody_req)
367 .addStringParm(1, text)
368 .endRequest();
369 SetBodyResponse result = new SetBodyResponse();
370 result.result = (SetBodyResult) decoder.getEnumParm(1, SetBodyResult.get(0), false);
371 result.chunks = decoder.getStringListParm(2, false);
372 result.charsUntilNextChunk = decoder.getUintParm(3, true);
373 return result;
374 } catch(IOException e) {
375 mSidRoot.sidOnFatalError(e);
376 return null
377 ;}
378 }
379 private final static byte[] getBodyChunks_req = {(byte) 90,(byte) 82,(byte) 12,(byte) 8};
380 public class GetBodyChunksResponse {
381 public String[] textChunks;
382 public int charsUntilNextChunk;
383 };
384
385 /** Retrieves string list of SMS text chunks in first argument, while the second argument contains the number of available characters until creation of the next chunk becomes necessary. * @return GetBodyChunksResponse
386 * <br> - textChunks List of text chunk strings
387 * <br> - charsUntilNextChunk Number of available characters until creation of the next chunk becomes necessary.
388 */
389 public GetBodyChunksResponse getBodyChunks() {
390 try {
391 Decoding decoder = sidDoRequest(getBodyChunks_req)
392 .endRequest();
393 GetBodyChunksResponse result = new GetBodyChunksResponse();
394 result.textChunks = decoder.getStringListParm(1, false);
395 result.charsUntilNextChunk = decoder.getUintParm(2, true);
396 return result;
397 } catch(IOException e) {
398 mSidRoot.sidOnFatalError(e);
399 return null
400 ;}
401 }
402 /***
403 * generic multiget of a list of Property
404 * @param requested the list of requested properties of Sms
405 * @return SidGetResponding
406 */
407 public SidGetResponding sidMultiGet(Property[] requested) {
408 return super.sidMultiGet(requested);
409 }
410 /***
411 * generic multiget of list of Property for a list of Sms
412 * @param requested the list of requested properties
413 * @return SidGetResponding[] can be casted to (Sms[]) if all properties are cached
414 */
415 static public SidGetResponding[] sidMultiGet(Property[] requested, Sms[] objects) {
416 return SidObject.sidMultiGet(requested, objects);
417 }
418 public Type getType() {
419 synchronized(this) {
420 if ((mSidCached & 0x1) != 0)
421 return mType;
422 }
423 return (Type) sidRequestEnumProperty(Property.P_TYPE);
424 }
425 public Status getStatus() {
426 synchronized(this) {
427 if ((mSidCached & 0x2) != 0)
428 return mStatus;
429 }
430 return (Status) sidRequestEnumProperty(Property.P_STATUS);
431 }
432 /** Set asynchronously and meaningful only after invoking Conversation.PostSMS and detecting Sms.STATUS of SOME_TARGETS_FAILED or FAILED. */
433 public FailureReason getFailureReason() {
434 synchronized(this) {
435 if ((mSidCached & 0x4) != 0)
436 return mFailureReason;
437 }
438 return (FailureReason) sidRequestEnumProperty(Property.P_FAILURE_REASON);
439 }
440 /** set to 1 when status goes to FAILED. use MarkSeen() to clear */
441 public boolean getIsFailedUnseen() {
442 synchronized(this) {
443 if ((mSidCached & 0x8) != 0)
444 return mIsFailedUnseen;
445 }
446 return sidRequestBoolProperty(Property.P_IS_FAILED_UNSEEN);
447 }
448 /** unix timestamp of message submission */
449 public int getTimestamp() {
450 synchronized(this) {
451 if ((mSidCached & 0x10) != 0)
452 return mTimestamp;
453 }
454 return sidRequestUintProperty(Property.P_TIMESTAMP);
455 }
456 /**
457 * The total price of sending this SMS message (sum of the individual prices to send to each recipient). Defaults to -1 on instantiation and incremented by the price for each recipient once that recipient's status reflects TARGET_ACCEPTABLE. Use Sms.GetTargetPrice to retrieve individual target prices.
458 *
459 * A value of MAX_UINT indicates that SkypeKit is actively querying and/or updating the value. Note that P_PRICE is an integer value. Calculate the actual price (in units specified by P_PRICE_CURRENCY) using P_PRICE_PRECISION as:
460 *
461 * @code
462 * actualPrice = price / 10^pricePrecision;
463 * </CODE>
464 */
465 public int getPrice() {
466 synchronized(this) {
467 if ((mSidCached & 0x20) != 0)
468 return mPrice;
469 }
470 return sidRequestUintProperty(Property.P_PRICE);
471 }
472 /** The decimal precision of the SMS price values, both individual and total. For example, a value of 2 indicates that you should divide the price (represented as an integer) by 100 (10^2) to obtain the actual price. */
473 public int getPricePrecision() {
474 synchronized(this) {
475 if ((mSidCached & 0x40) != 0)
476 return mPricePrecision;
477 }
478 return sidRequestUintProperty(Property.P_PRICE_PRECISION);
479 }
480 /** should be same as account currency at the time of composing/sending */
481 public String getPriceCurrency() {
482 synchronized(this) {
483 if ((mSidCached & 0x80) != 0)
484 return mPriceCurrency;
485 }
486 return sidRequestStringProperty(Property.P_PRICE_CURRENCY);
487 }
488 /** number that should receive the replies */
489 public String getReplyToNumber() {
490 synchronized(this) {
491 if ((mSidCached & 0x100) != 0)
492 return mReplyToNumber;
493 }
494 return sidRequestStringProperty(Property.P_REPLY_TO_NUMBER);
495 }
496 /** space-separated normalised pstn numbers */
497 public String getTargetNumbers() {
498 synchronized(this) {
499 if ((mSidCached & 0x200) != 0)
500 return mTargetNumbers;
501 }
502 return sidRequestStringProperty(Property.P_TARGET_NUMBERS);
503 }
504 /** binary blob. track with OnPropertyChange(), access with GetTargetStatus(target) */
505 public byte[] getTargetStatuses() {
506 synchronized(this) {
507 if ((mSidCached & 0x400) != 0)
508 return mTargetStatuses;
509 }
510 return sidRequestBinaryProperty(Property.P_TARGET_STATUSES);
511 }
512 /** actual payload */
513 public String getBody() {
514 synchronized(this) {
515 if ((mSidCached & 0x800) != 0)
516 return mBody;
517 }
518 return sidRequestStringProperty(Property.P_BODY);
519 }
520 /** reference to Message */
521 public Message getChatMsg() {
522 synchronized(this) {
523 if ((mSidCached & 0x1000) != 0)
524 return mChatMsg;
525 }
526 return (Message) sidRequestObjectProperty(Property.P_CHAT_MSG);
527 }
528 public String sidGetStringProperty(final PropertyEnumConverting prop) {
529 switch(prop.getId()) {
530 case 194:
531 return mPriceCurrency;
532 case 199:
533 return mReplyToNumber;
534 case 195:
535 return mTargetNumbers;
536 case 197:
537 return mBody;
538 }
539 return "";
540 }
541 public SidObject sidGetObjectProperty(final PropertyEnumConverting prop) {
542 assert(prop.getId() == 840);
543 return mChatMsg;
544 }
545 public boolean sidGetBoolProperty(final PropertyEnumConverting prop) {
546 assert(prop.getId() == 48);
547 return mIsFailedUnseen;
548 }
549 public int sidGetIntProperty(final PropertyEnumConverting prop) {
550 switch(prop.getId()) {
551 case 198:
552 return mTimestamp;
553 case 193:
554 return mPrice;
555 case 49:
556 return mPricePrecision;
557 }
558 return 0;
559 }
560 public EnumConverting sidGetEnumProperty(final PropertyEnumConverting prop) {
561 switch(prop.getId()) {
562 case 190:
563 return mType;
564 case 191:
565 return mStatus;
566 case 192:
567 return mFailureReason;
568 }
569 return null;
570 }
571 public byte[] sidGetBinaryProperty(final PropertyEnumConverting prop) {
572 assert(prop.getId() == 196);
573 return mTargetStatuses;
574 }
575 public String getPropertyAsString(final int prop) {
576 switch (prop) {
577 case 190: return getType().toString();
578 case 191: return getStatus().toString();
579 case 192: return getFailureReason().toString();
580 case 48: return Boolean.toString(getIsFailedUnseen());
581 case 198: return Integer.toString(getTimestamp());
582 case 193: return Integer.toString(getPrice());
583 case 49: return Integer.toString(getPricePrecision());
584 case 194: return getPriceCurrency();
585 case 199: return getReplyToNumber();
586 case 195: return getTargetNumbers();
587 case 196: return "<binary>";
588 case 197: return getBody();
589 case 840: return Integer.toString(getChatMsg().getOid());
590 }
591 return "<unkown>";
592 }
593 public String getPropertyAsString(final Property prop) {
594 return getPropertyAsString(prop.getId());
595 }
596 protected void sidOnChangedProperty(final int propertyId, final int value, final String svalue) {
597 final Property property = Property.get(propertyId);
598 if (property == Property.P_UNKNOWN) return;
599 final int idx = property.getIdx();
600 if (idx != 0) {
601 int bit = 1<<((idx-1)%32);
602 synchronized (this) {
603 mSidCached|=bit; switch (propertyId) {
604 case 190: mType = Type.get(value); break;
605 case 191: mStatus = Status.get(value); break;
606 case 192: mFailureReason = FailureReason.get(value); break;
607 case 48: mIsFailedUnseen = value != 0; break;
608 case 198: mTimestamp = value; break;
609 case 193: mPrice = value; break;
610 case 49: mPricePrecision = value; break;
611 case 194:
612 if (svalue != null) mPriceCurrency = svalue;
613 else mSidCached &=~bit;
614 break;
615 case 199:
616 if (svalue != null) mReplyToNumber = svalue;
617 else mSidCached &=~bit;
618 break;
619 case 195:
620 if (svalue != null) mTargetNumbers = svalue;
621 else mSidCached &=~bit;
622 break;
623 case 197:
624 if (svalue != null) mBody = svalue;
625 else mSidCached &=~bit;
626 break;
627 default: mSidCached|=bit; break;
628 }
629 }
630 }
631 SmsListener listener = ((Skype) mSidRoot).getSmsListener();
632 if (listener != null)
633 listener.onPropertyChange(this, property, value, svalue);
634 }
635 public void sidSetProperty(final PropertyEnumConverting prop, final String newValue) {
636 final int propId = prop.getId();
637 switch(propId) {
638 case 194:
639 mSidCached |= 0x80;
640 mPriceCurrency= newValue;
641 break;
642 case 199:
643 mSidCached |= 0x100;
644 mReplyToNumber= newValue;
645 break;
646 case 195:
647 mSidCached |= 0x200;
648 mTargetNumbers= newValue;
649 break;
650 case 197:
651 mSidCached |= 0x800;
652 mBody= newValue;
653 break;
654 }
655 }
656 public void sidSetProperty(final PropertyEnumConverting prop, final SidObject newValue) {
657 final int propId = prop.getId();
658 assert(propId == 840);
659 mSidCached |= 0x1000;
660 mChatMsg= (Message) newValue;
661 }
662 public void sidSetProperty(final PropertyEnumConverting prop, final int newValue) {
663 final int propId = prop.getId();
664 switch(propId) {
665 case 190:
666 mSidCached |= 0x1;
667 mType= Type.get(newValue);
668 break;
669 case 191:
670 mSidCached |= 0x2;
671 mStatus= Status.get(newValue);
672 break;
673 case 192:
674 mSidCached |= 0x4;
675 mFailureReason= FailureReason.get(newValue);
676 break;
677 case 48:
678 mSidCached |= 0x8;
679 mIsFailedUnseen= newValue != 0;
680 break;
681 case 198:
682 mSidCached |= 0x10;
683 mTimestamp= newValue;
684 break;
685 case 193:
686 mSidCached |= 0x20;
687 mPrice= newValue;
688 break;
689 case 49:
690 mSidCached |= 0x40;
691 mPricePrecision= newValue;
692 break;
693 }
694 }
695 public void sidSetProperty(final PropertyEnumConverting prop, final byte[] newValue) {
696 final int propId = prop.getId();
697 assert(propId == 196);
698 mSidCached |= 0x400;
699 mTargetStatuses= newValue;
700 }
701 public Type mType;
702 public Status mStatus;
703 public FailureReason mFailureReason;
704 public boolean mIsFailedUnseen;
705 public int mTimestamp;
706 public int mPrice;
707 public int mPricePrecision;
708 public String mPriceCurrency;
709 public String mReplyToNumber;
710 public String mTargetNumbers;
711 public byte[] mTargetStatuses;
712 public String mBody;
713 public Message mChatMsg;
714 public int moduleId() {
715 return 12;
716 }
717
718 public Sms(final int oid, final SidRoot root) {
719 super(oid, root, 13);
720 }
721 }