001    package com.skype.api;
002    
003    import java.io.IOException;
004    import java.util.*;
005    import com.skype.ipc.*;
006    /**
007     * Collects and manages Contacts related by type, status, or some other arbitrary criteria. SkypeKit recognizes two distinct ContactGroup flavors - "hardwired" and "custom". SkypeKit both defines the criteria for and dynamically manages all "hardwired" ContactGroups. Individual users explicitly create and manage all "custom" ContactGroups.  <br><br>"Hardwired" groups are primarily organizational tools, for example, they enable you to display a list of all Contacts awaiting authorization by you. "Custom" groups are also organizational tools, for example, they enable you to display a list of all Contacts in a particular geographical area or belonging to a particular professional association, social clubs, and so forth. Primarily, though, "custom" groups are functional tools that enable you to establish conference calls, group chats, and so forth. <br><br>"Hardwired" ContactGroups are defined for and available to all users. SkypeKit determines membership in a particular "hardwired" group dynamically whenever a user invokes Skype.GetHardwiredContactGroup for that group. Subsequent changes to a Contact's status might result in its being added to (for example, the Contact is now authorized) or removed from (for example, the Contact is now removed or blocked) one or more "hardwired" groups. <br><br>SkypeKit fires OnChange events for all affected ContractGroup instances. Essentially all ContactGroup methods related to explicitly adding and removing members and conversations from the group return false, and CanAdd and CanRemove additionally return a false result. <br><br>"Custom" ContactGroups can be defined by a particular Skype user through the UI. Your UI should implement Creation, deletion and filtering contact list by custom contact groups, as well as adding and removing contacts in those groups. <br><br>A Contact can belong to multiple non-mutually exclusive "hardwired" groups at the same time, for example, an authorized contact is typically in your "buddy" group, but a Contact cannot belong to CONTACTS_AUTHORIZED_BY_ME if they are awaiting authorization. Similarly, a Contact can belong to multiple "custom" groups and mutual exclusivity is typically not an issue. <br>
008     */
009    
010    
011    public class ContactGroup extends SkypeObject {
012    
013    
014            public interface ContactGroupListener {
015                    /** This event gets called when there are changes to ContactGroup properties defined in ContactGroup.PROPERTY  */
016                    public void OnPropertyChange(SkypeObject obj, PROPERTY prop, Object value);
017                    
018                    /**conversation added or removed from this group*/
019                    public void OnChangeConversation(SkypeObject obj, Conversation conversation);
020                    
021                    /**A contact has been added or removed to this ContactGroup. <br>NB! On rare occasions, the ContectRef argument to this callback can be NULL. You should always check whether the reference is valid, before accessing methods or properties. <br>*/
022                    public void OnChange(SkypeObject obj, Contact contact);
023                    
024            }
025            
026            public ContactGroup(int oid, Skype skype) {
027                    super(oid,skype);
028                    /**get default properties for this module **/
029                    GetDefaultProps();
030            }
031            
032            private static final int MODULE_ID = 10;
033            
034            public static final int moduleID() {
035                    return MODULE_ID;
036            }
037            
038            /** Properties of the ContactGroup class */
039            public enum PROPERTY {
040            
041                    /** ContactGroup.TYPE, type: TYPE */
042                    type(155),
043                    
044                    /** unique 32-bit ID for custom groups, type: int */
045                    custom_group_id(154),
046                    
047                    /** change via ContactGroup.GiveDisplayname(), type: String */
048                    given_displayname(151),
049                    
050                    /** Number of contacts in the group. NB! The value of this property does not get updated until 5 seconds after account login. During these initial 5 seconds, the value of this property remains 0. The reason for this 5 second delay is to reduce the flurry of property update traffic that occurs during the CBL synchronization phase, following successful login. Note that if you absolutely need to have this value immediately after login, you can still get it by retrieving the contact list with ContactGroup.GetContacts method and examining its size.  <br>, type: int */
051                    nrofcontacts(152),
052                    
053                    /** number of contacts online in the group, type: int */
054                    nrofcontacts_online(153);
055                    
056                    private static final Map<Integer,PROPERTY> lookup = new HashMap<Integer,PROPERTY>();
057                    
058                    static {
059                            for(PROPERTY s : EnumSet.allOf(PROPERTY.class))
060                                    lookup.put(s.getId(), s);
061                    }
062                    
063                    private final int id;
064                    
065                    private PROPERTY(int value) {
066                            this.id = value;
067                    }
068                    
069                    public int getId() { return id; }
070                    
071                    public static PROPERTY get(int code) {
072                            return lookup.get(code);
073                    }
074                    
075                    public static PROPERTY fromString(String s) {
076                            for (PROPERTY p : lookup.values()) {
077                                    if (p.toString() == s) {
078                                            return p;
079                                    }
080                            }
081                            return null;
082                    }
083            }
084            
085            public Object GetPropertyAsEnum(int propid) {
086                    return PROPERTY.get(propid);
087            }
088            
089            public String GetStrProperty(PROPERTY prop) {
090                    //check in propcache if so then return
091                    if (mPropCache.containsKey(new Integer(prop.id))){
092                            String value =  (String)mPropCache.get(prop.id);
093                            if (value != null && !(value.length() == 0) ){
094                                    return value;
095                            }
096                    }
097                    //else get from skypekit...
098                    GetPropertyRequest request = new GetPropertyRequest(10, mObjectId, prop.id);
099                    
100                    String string = null;
101                    GetPropertyResponse r = skype.GetProperty(request);
102                    if (r != null){
103                            string = r.GetAsString();
104                    }
105                    
106                    if (string != null)
107                    {
108                            mPropCache.put(new Integer(prop.id), string);
109                    }
110                    return string;
111            }
112            
113            public int GetIntProperty(PROPERTY prop) {
114                    //check in propcache if so then return
115                    if (mPropCache.containsKey(new Integer(prop.id))){
116                            int value = ((Integer)mPropCache.get(prop.id)).intValue();
117                            if (value != 0){
118                                    return value;
119                            }
120                    }
121                    //else get from skypekit...
122                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
123                    
124                    Integer integer = null;
125                    GetPropertyResponse r = skype.GetProperty(request);
126                    if (r != null){
127                            integer  = r.GetAsInt();
128                    }
129                    
130                    if (integer != null)
131                    {
132                            mPropCache.put(new Integer(prop.id), integer);
133                            return integer.intValue();
134                    }
135                    else
136                    {
137                            return 0;
138                    }
139            }
140            
141            public boolean GetBooleanProperty(PROPERTY prop) {
142                    //check in propcache if so then return
143                    if (mPropCache.containsKey(new Integer(prop.id))){
144                            return ((Boolean)mPropCache.get(prop.id)).booleanValue();
145                    }
146                    //else get from skypekit...
147                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
148                    
149                    Boolean boolResp = null;
150                    GetPropertyResponse r = skype.GetProperty(request);
151                    if (r != null){
152                            boolResp  = r.GetAsBoolean();
153                    }
154                    
155                    if (boolResp != null)
156                    {
157                            mPropCache.put(new Integer(prop.id), boolResp);
158                            return boolResp.booleanValue();
159                    }
160                    else
161                    {
162                            return false;
163                    }
164            }
165            
166            public byte [] GetBinProperty(PROPERTY prop) {
167                    //get from skypekit...
168                    GetPropertyRequest request = new GetPropertyRequest(10, mObjectId, prop.id);
169                    
170                    byte [] data = null;
171                    GetPropertyResponse r = skype.GetProperty(request);
172                    if (r != null) {
173                            data = r.GetAsBinary();
174                    }
175                    return data;
176            }
177            
178            /**default array of ContactGroup Properties that get fetched & cached upon class construction*/
179            private static PROPERTY [] defaultProperties = { PROPERTY.type, PROPERTY.custom_group_id, PROPERTY.given_displayname, PROPERTY.nrofcontacts, PROPERTY.nrofcontacts_online};
180            
181            private void GetDefaultProps() {
182                    MultiGetPropertyRequest request = null;
183                    ArrayList<Integer> proparray = null;
184                            /**Add the single oid into array*/
185                            ArrayList<Integer> oidarray=new ArrayList<Integer>();
186                            oidarray.add(mObjectId);
187                            
188                            /**Add all requested propids into array*/
189                            proparray=new ArrayList<Integer>();
190                            for (PROPERTY defaultProp : defaultProperties) {
191                                    proparray.add(defaultProp.getId());
192                            }
193                            /**Generate the request*/
194                            request = new MultiGetPropertyRequest(moduleID(), oidarray,proparray);
195                            
196                            /** Make Multi Get call*/
197                            GetPropertyResponse r=skype.MultiGetProperty(request);
198                            /**Verify that it is a proper multiresponse*/
199                            if(!r.isMultiresponse())
200                            {
201                                    return;
202                            }
203                            /**update property cache with results*/
204                            mPropCache.putAll(r.GetAsMap(mObjectId, proparray));
205                    }
206                    
207                    /**
208                    The list of all possible ContactGroup types. A value of this type can be passed to Skype class GetHardwiredContactGroup to retrieve the relevant ContactGroup object. <br> */
209                    public enum TYPE {
210                    
211                            /** The superset of all "hardwired" contact groups. <br>*/
212                            ALL_KNOWN_CONTACTS(1),
213                            
214                            /** The set of all authorized contacts, that is, contacts that were last the target of Contact.SetBuddyStatus(false) plus all SkypeOut contacts. <br>*/
215                            ALL_BUDDIES(2),
216                            
217                            /** The set of all authorized Skype contacts (Contact:_SKYPENAME is non-null).  <br>Note that this excludes Skype contacts that have either never been the target of Contact.SetBuddyStatus(true) or were last the target of Contactact.SetBuddyStatus(false). <br>*/
218                            SKYPE_BUDDIES(3),
219                            
220                            /** The set of all SkypeOut contacts (Contact:_PSTNNUMBER is non-null). PSTN contacts can be added to the contact list by retrieving a new contact object with Skype.GetContact, passing in the phone number as string, and then either using Contact.SetBuddyStatus(true) or adding the contact to the SKYPEOUT_BUDDIES group with ContactGroup.AddContact. <br>*/
221                            SKYPEOUT_BUDDIES(4),
222                            
223                            /** The subset of ALL_BUDDIES that are currently online, including those currently marked as DO_NOT_DISTURBED and AWAY. <br>*/
224                            ONLINE_BUDDIES(5),
225                            
226                            /** The set of all contacts whose Contact:_TYPE reflects UNRECOGNIZED OR have not authorized the local user yet. <br>*/
227                            UNKNOWN_OR_PENDINGAUTH_BUDDIES(6),
228                            
229                            /** This filter returns top 10 most recently contacted contacts, based on Contact.P_LASTUSED_TIMESTAMP property values. This is not configurable. Note that the P_LASTUSED_TIMESTAMP property does not propagate between different Skype instances - thus this filter only works in context of the local database. Recent contacts that were in touch with the user on some other Skype installation will not show up in this filter. <br>*/
230                            RECENTLY_CONTACTED_CONTACTS(7),
231                            
232                            /** Contacts to whose authorization request the user has not responded yet. The UI should enable the user to accept, decline the authorization request and in case of decline, optionally block further incoming communication from the contact. See: Contact.SetBuddyStatus, Contact.SetBlocked and Contact.IgnoreAuthRequest for more information. <br>*/
233                            CONTACTS_WAITING_MY_AUTHORIZATION(8),
234                            
235                            /** All contacts authorized by the user. <br>*/
236                            CONTACTS_AUTHORIZED_BY_ME(9),
237                            
238                            /** Group of contacts the user has blocked from further incoming communications. If the UI enables contact blocking, it should also provide interface for the user to unblock the blocked contacts. Note that a contact can simultaneously be in both CONTACTS_BLOCKED_BY_ME and CONTACTS_AUTHORIZED_BY_ME groups. <br>*/
239                            CONTACTS_BLOCKED_BY_ME(10),
240                            
241                            /** The set of all "buddies" that are not also a member of a custom group. <br>*/
242                            UNGROUPED_BUDDIES(11),
243                            
244                            /** A custom group defined by user. <br>*/
245                            CUSTOM_GROUP(12),
246                            
247                            /** The shared contact group functionality is no longer supported. This contact group type can be ignored. <br>*/
248                            PROPOSED_SHARED_GROUP(13),
249                            
250                            /** The shared contact group functionality is no longer supported. This contact group type can be ignored. <br>*/
251                            SHARED_GROUP(14),
252                            
253                            /** The set of all contacts that were originally imported from an external address book. <br>*/
254                            EXTERNAL_CONTACTS(15);
255                            
256                            private static final Map<Integer,TYPE> lookup = new HashMap<Integer,TYPE>();
257                            
258                            static {
259                                    for(TYPE s : EnumSet.allOf(TYPE.class))
260                                            lookup.put(s.getId(), s);
261                            }
262                            
263                            private final int id;
264                            
265                            private TYPE(int value) {
266                                    this.id = value;
267                            }
268                            
269                            public int getId() { return id; }
270                            
271                            public static TYPE get(int code) {
272                                    return lookup.get(code);
273                            }
274                            
275                            public static TYPE fromString(String s) {
276                                    for (TYPE p : lookup.values()) {
277                                            if (p.toString() == s) {
278                                                    return p;
279                                            }
280                                    }
281                                    return null;
282                            }
283                    }
284                    
285                    /**
286                     *Setter for ContactGroup class GIVEN_DISPLAYNAME property. <br>
287                     * @param name
288                     */
289                    public void GiveDisplayName( String name) {
290                    
291                            Request request = null;
292                            try {
293                                    request = new XCallRequest(10,1);
294                            } catch (IOException e) {
295                                    e.printStackTrace();
296                                    if (skype.errorListener != null)
297                                            skype.errorListener.OnSkypeKitFatalError();
298                            }
299                            request.addParm('O',0,mObjectId);
300                            request.addParm('S',1,name);
301                            
302                            skype.XCall((XCallRequest)request);
303                    }
304                    
305                    /**
306                     *Removes the contact group. This is synced across instances logged in with the same account - which can take several minutes for the sync to happen. <br>
307                     * @return result
308                     */
309                    public boolean Delete() {
310                    
311                            Request request = null;
312                            try {
313                                    request = new XCallRequest(10,2);
314                            } catch (IOException e) {
315                                    e.printStackTrace();
316                                    if (skype.errorListener != null)
317                                            skype.errorListener.OnSkypeKitFatalError();
318                            }
319                            request.addParm('O',0,mObjectId);
320                            
321                            Response r = skype.XCall((XCallRequest)request);
322                            
323                            if (r.isErrCall())
324                                    return false;
325                                    
326                            boolean result = false;
327                            result = r.GetAsBoolean(1);
328                            return result;
329                    }
330                    
331                    /**
332                     *Returns list of conversations in the ContactGroup. <br>
333                     * @return conversations
334                     */
335                    public Conversation [] GetConversations() {
336                    
337                            Request request = null;
338                            try {
339                                    request = new XCallRequest(10,3);
340                            } catch (IOException e) {
341                                    e.printStackTrace();
342                                    if (skype.errorListener != null)
343                                            skype.errorListener.OnSkypeKitFatalError();
344                            }
345                            request.addParm('O',0,mObjectId);
346                            
347                            Response r = skype.XCall((XCallRequest)request);
348                            
349                            if (r.isErrCall())
350                                    return null;
351                                    
352                            Vector<Conversation> conversations = new Vector<Conversation>();
353                            while (r.HasMore(1))
354                            {
355                                    int oid = 0;
356                                    Conversation conversation = null;
357                                    oid = r.GetOid(1);
358                                    if (oid != AbstractDecoder.NULL_VALUE) { 
359                                            conversation = (Conversation)skype.factory(Conversation.moduleID(), oid, skype);
360                                    }
361                                    conversations.add(conversation);
362                            }
363                            return conversations.toArray(new Conversation[conversations.size()]);
364                            
365                    }
366                    
367                    /**
368                     *Checks if the current user can add given conversation to the ContactGroup. Returns false for most of the hardwired contact groups for example. <br>
369                     * @param conversation Conversation to be checked. <br>
370                     * @return result Returns true if Conversation can be added to this ContactGroup. <br>
371                     */
372                    public boolean CanAddConversation( Conversation conversation) {
373                    
374                            Request request = null;
375                            try {
376                                    request = new XCallRequest(10,4);
377                            } catch (IOException e) {
378                                    e.printStackTrace();
379                                    if (skype.errorListener != null)
380                                            skype.errorListener.OnSkypeKitFatalError();
381                            }
382                            request.addParm('O',0,mObjectId);
383                            request.addParm('O',1,conversation.getOid());
384                            
385                            Response r = skype.XCall((XCallRequest)request);
386                            
387                            if (r.isErrCall())
388                                    return false;
389                                    
390                            boolean result = false;
391                            result = r.GetAsBoolean(1);
392                            return result;
393                    }
394                    
395                    /**
396                     *Adds given conversation to the ContactGroup. <br>
397                     * @param conversation
398                     */
399                    public void AddConversation( Conversation conversation) {
400                    
401                            Request request = null;
402                            try {
403                                    request = new XCallRequest(10,5);
404                            } catch (IOException e) {
405                                    e.printStackTrace();
406                                    if (skype.errorListener != null)
407                                            skype.errorListener.OnSkypeKitFatalError();
408                            }
409                            request.addParm('O',0,mObjectId);
410                            request.addParm('O',1,conversation.getOid());
411                            
412                            skype.XCall((XCallRequest)request);
413                    }
414                    
415                    /**
416                     *Checks if the current user can remove given conversation from the ContactGroup. Again, returns false for most hardwired contact groups. <br>
417                     * @return result true if RemoveConversation(contact) works on this group
418                     */
419                    public boolean CanRemoveConversation() {
420                    
421                            Request request = null;
422                            try {
423                                    request = new XCallRequest(10,6);
424                            } catch (IOException e) {
425                                    e.printStackTrace();
426                                    if (skype.errorListener != null)
427                                            skype.errorListener.OnSkypeKitFatalError();
428                            }
429                            request.addParm('O',0,mObjectId);
430                            
431                            Response r = skype.XCall((XCallRequest)request);
432                            
433                            if (r.isErrCall())
434                                    return false;
435                                    
436                            boolean result = false;
437                            result = r.GetAsBoolean(1);
438                            return result;
439                    }
440                    
441                    /**
442                     *Removes given conversation from the ContactGroup. <br>
443                     * @param conversation
444                     */
445                    public void RemoveConversation( Conversation conversation) {
446                    
447                            Request request = null;
448                            try {
449                                    request = new XCallRequest(10,7);
450                            } catch (IOException e) {
451                                    e.printStackTrace();
452                                    if (skype.errorListener != null)
453                                            skype.errorListener.OnSkypeKitFatalError();
454                            }
455                            request.addParm('O',0,mObjectId);
456                            request.addParm('O',1,conversation.getOid());
457                            
458                            skype.XCall((XCallRequest)request);
459                    }
460                    
461                    /**
462                     *Retrieves contact list. <br>
463                     * @return contacts
464                     */
465                    public Contact [] GetContacts() {
466                    
467                            Request request = null;
468                            try {
469                                    request = new XCallRequest(10,8);
470                            } catch (IOException e) {
471                                    e.printStackTrace();
472                                    if (skype.errorListener != null)
473                                            skype.errorListener.OnSkypeKitFatalError();
474                            }
475                            request.addParm('O',0,mObjectId);
476                            
477                            Response r = skype.XCall((XCallRequest)request);
478                            
479                            if (r.isErrCall())
480                                    return null;
481                                    
482                            Vector<Contact> contacts = new Vector<Contact>();
483                            while (r.HasMore(1))
484                            {
485                                    int oid = 0;
486                                    Contact contact = null;
487                                    oid = r.GetOid(1);
488                                    if (oid != AbstractDecoder.NULL_VALUE) { 
489                                            contact = (Contact)skype.factory(Contact.moduleID(), oid, skype);
490                                    }
491                                    contacts.add(contact);
492                            }
493                            return contacts.toArray(new Contact[contacts.size()]);
494                            
495                    }
496                    
497                    /**
498                     *Checks if the current user can add given contact to the ContactGroup.  <br>
499                     * @param contact Contact to be checked. <br>
500                     * @return result returns true if AddContact(contact) works on this group. <br>
501                     */
502                    public boolean CanAddContact( Contact contact) {
503                    
504                            Request request = null;
505                            try {
506                                    request = new XCallRequest(10,9);
507                            } catch (IOException e) {
508                                    e.printStackTrace();
509                                    if (skype.errorListener != null)
510                                            skype.errorListener.OnSkypeKitFatalError();
511                            }
512                            request.addParm('O',0,mObjectId);
513                            request.addParm('O',1,contact.getOid());
514                            
515                            Response r = skype.XCall((XCallRequest)request);
516                            
517                            if (r.isErrCall())
518                                    return false;
519                                    
520                            boolean result = false;
521                            result = r.GetAsBoolean(1);
522                            return result;
523                    }
524                    
525                    /**
526                     *Adds contact to a contact group. This only works for non-hardwired contact groups. <br>
527                     * @param contact
528                     */
529                    public void AddContact( Contact contact) {
530                    
531                            Request request = null;
532                            try {
533                                    request = new XCallRequest(10,10);
534                            } catch (IOException e) {
535                                    e.printStackTrace();
536                                    if (skype.errorListener != null)
537                                            skype.errorListener.OnSkypeKitFatalError();
538                            }
539                            request.addParm('O',0,mObjectId);
540                            request.addParm('O',1,contact.getOid());
541                            
542                            skype.XCall((XCallRequest)request);
543                    }
544                    
545                    /**
546                     *Checks if the current user can remove given contact from the ContactGroup. <br>
547                     * @return result true if RemoveContact(contact) works on this group
548                     */
549                    public boolean CanRemoveContact() {
550                    
551                            Request request = null;
552                            try {
553                                    request = new XCallRequest(10,11);
554                            } catch (IOException e) {
555                                    e.printStackTrace();
556                                    if (skype.errorListener != null)
557                                            skype.errorListener.OnSkypeKitFatalError();
558                            }
559                            request.addParm('O',0,mObjectId);
560                            
561                            Response r = skype.XCall((XCallRequest)request);
562                            
563                            if (r.isErrCall())
564                                    return false;
565                                    
566                            boolean result = false;
567                            result = r.GetAsBoolean(1);
568                            return result;
569                    }
570                    
571                    /**
572                     *Removes contact from the ContactGroup. <br>
573                     * @param contact
574                     */
575                    public void RemoveContact( Contact contact) {
576                    
577                            Request request = null;
578                            try {
579                                    request = new XCallRequest(10,12);
580                            } catch (IOException e) {
581                                    e.printStackTrace();
582                                    if (skype.errorListener != null)
583                                            skype.errorListener.OnSkypeKitFatalError();
584                            }
585                            request.addParm('O',0,mObjectId);
586                            request.addParm('O',1,contact.getOid());
587                            
588                            skype.XCall((XCallRequest)request);
589                    }
590                    
591            
592            }