    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            }