aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/util/call/MetaContactPhoneUtil.java
blob: bd219a2ee3d8092844c3e6102d9b34a65c4c5457 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
/*
 * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package net.java.sip.communicator.util.call;

import java.util.*;

import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.OperationSetServerStoredContactInfo.DetailsResponseListener;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.MobilePhoneDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.VideoDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkPhoneDetail;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.account.*;

/**
 * Utility class used to check if there is a telephony service, video calls and
 * desktop sharing enabled for a protocol specific <tt>MetaContact</tt>.
 *
 * @author Damian Minkov
 * @author Yana Stamcheva
 */
public class MetaContactPhoneUtil
{
    /**
     * The metacontcat we are working on.
     */
    private MetaContact metaContact;

    /**
     * The phones that have been discovered for metacontact child contacts.
     */
    private Hashtable<Contact,List<String>> phones =
        new Hashtable<Contact, List<String>>();

    /**
     * The video phones that have been discovered
     * for metacontact child contacts.
     */
    private Hashtable<Contact,List<String>> videoPhones =
        new Hashtable<Contact, List<String>>();

    /**
     * True if there is any phone found for the metacontact.
     */
    private boolean hasPhones = false;

    /**
     * True if there is any video phone found for the metacontact.
     */
    private boolean hasVideoDetail = false;

    /**
     * Is routing for video enabled for any of the contacts of the metacontact.
     */
    private boolean routingForVideoEnabled = false;

    /**
     * Is routing for desktop enabled for any of the contacts of the metacontact.
     */
    private boolean routingForDesktopEnabled = false;

    /**
     * Obtains the util for <tt>metaContact</tt>
     * @param metaContact the metaconctact.
     * @return ContactPhoneUtil for the <tt>metaContact</tt>.
     */
    public static MetaContactPhoneUtil getPhoneUtil(MetaContact metaContact)
    {
        return new MetaContactPhoneUtil(metaContact);
    }

    /**
     * Creates utility instance for <tt>metaContact</tt>.
     * @param metaContact the metacontact checked in the utility.
     */
    protected MetaContactPhoneUtil(MetaContact metaContact)
    {
        this.metaContact = metaContact;
    }

    /**
     * Returns the metaContact we work on.
     * @return the metaContact we work on.
     */
    public MetaContact getMetaContact()
    {
        return metaContact;
    }

    /**
     * Returns localized addition phones list for contact, if any.
     * Return null if we have stopped searching and a listener is available
     * and will be used to inform for results.
     * @param contact the contact
     * @return localized addition phones list for contact, if any.
     */
    public List<String> getPhones(Contact contact)
    {
        return getPhones(contact, null, true);
    }

    /**
     * Returns list of video phones for <tt>contact</tt>, localized.
     * Return null if we have stopped searching and a listener is available
     * and will be used to inform for results.
     * @param contact the contact to check for video phones.
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @return list of video phones for <tt>contact</tt>, localized.
     */
    public List<String> getVideoPhones( Contact contact,
                                        DetailsResponseListener listener)
    {
        if(!this.metaContact.containsContact(contact))
        {
            return new ArrayList<String>();
        }

        if(videoPhones.containsKey(contact))
        {
            return videoPhones.get(contact);
        }

        List<String> phonesList = ContactPhoneUtil.getContactAdditionalPhones(
                contact, listener, true, true);

        if(phonesList == null)
            return null;
        else if (phonesList.size() > 0)
            hasVideoDetail = true;

        videoPhones.put(contact, phonesList);

        // to check for routingForVideoEnabled prop
        isVideoCallEnabled(contact);
        // to check for routingForDesktopEnabled prop
        isDesktopSharingEnabled(contact);

        return phonesList;
    }

    /**
     * List of phones for contact, localized if <tt>localized</tt> is
     * <tt>true</tt>, and not otherwise.
     * Return null if we have stopped searching and a listener is available
     * and will be used to inform for results.
     * @param contact the contact to check for video phones.
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @param localized whether to localize the phones, put a description text.
     * @return list of phones for contact.
     */
    public List<String> getPhones(  Contact contact,
                                    DetailsResponseListener listener,
                                    boolean localized)
    {
        if(!this.metaContact.containsContact(contact))
        {
            return new ArrayList<String>();
        }

        if(phones.containsKey(contact))
        {
            return phones.get(contact);
        }

        List<String> phonesList
            = ContactPhoneUtil.getContactAdditionalPhones(
                contact, listener, false, localized);

        if(phonesList == null)
            return null;
        else if (phonesList.size() > 0)
            hasPhones = true;

        phones.put(contact, phonesList);

        return phonesList;
    }

    /**
     * Is video called is enabled for metaContact. If any of the child
     * contacts has video enabled.
     *
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @return is video called is enabled for metaContact.
     */
    public boolean isVideoCallEnabled(DetailsResponseListener listener)
    {
        // make sure children are checked
        if(!checkMetaContactVideoPhones(listener))
            return false;

        return metaContact.getDefaultContact(
                    OperationSetVideoTelephony.class) != null
               || routingForVideoEnabled
               || hasVideoDetail;
    }

    /**
     * Is video called is enabled for metaContact. If any of the child
     * contacts has video enabled.
     *
     * @return is video called is enabled for metaContact.
     */
    public boolean isVideoCallEnabled()
    {
        return isVideoCallEnabled((DetailsResponseListener) null);
    }

    /**
     * Is video call enabled for contact.
     * @param contact to check for video capabilities.
     * @return is video call enabled for contact.
     */
    public boolean isVideoCallEnabled(Contact contact)
    {
        if(!this.metaContact.containsContact(contact))
            return false;

        // make sure we have checked everything for the contact
        // before continue
        if(!checkContactPhones(contact))
            return false;

        routingForVideoEnabled =
            ConfigurationUtils
                .isRouteVideoAndDesktopUsingPhoneNumberEnabled()
            && phones.containsKey(contact)
            && phones.get(contact).size() > 0
            && AccountUtils.getOpSetRegisteredProviders(
                OperationSetVideoTelephony.class,
                null,
                null).size() > 0;

        return contact.getProtocolProvider().getOperationSet(
            OperationSetVideoTelephony.class) != null
                && hasContactCapabilities(contact,
                        OperationSetVideoTelephony.class)
                || routingForVideoEnabled;
    }

    /**
     * Is desktop sharing enabled for metaContact. If any of the child
     * contacts has desktop sharing enabled.
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @return is desktop share is enabled for metaContact.
     */
    public boolean isDesktopSharingEnabled(DetailsResponseListener listener)
    {
        // make sure children are checked
        if(!checkMetaContactVideoPhones(listener))
            return false;

        return metaContact.getDefaultContact(
            OperationSetDesktopSharingServer.class) != null
            || routingForDesktopEnabled
            || hasVideoDetail;
    }

    /**
     * Is desktop sharing enabled for metaContact. If any of the child
     * contacts has desktop sharing enabled.
     * @return is desktop share is enabled for metaContact.
     */
    public boolean isDesktopSharingEnabled()
    {
        return isDesktopSharingEnabled((DetailsResponseListener) null);
    }

    /**
     * Is desktop sharing enabled for contact.
     * @param contact to check for desktop sharing capabilities.
     * @return is desktop sharing enabled for contact.
     */
    public boolean isDesktopSharingEnabled(Contact contact)
    {
        if(!this.metaContact.containsContact(contact))
            return false;

        // make sure we have checked everything for the contact
        // before continue
        if(!checkContactPhones(contact))
            return false;

        routingForDesktopEnabled =
            ConfigurationUtils
                .isRouteVideoAndDesktopUsingPhoneNumberEnabled()
            && phones.containsKey(contact)
            && phones.get(contact).size() > 0
            && AccountUtils.getOpSetRegisteredProviders(
                    OperationSetDesktopSharingServer.class,
                    null,
                    null).size() > 0;
        return contact.getProtocolProvider().getOperationSet(
            OperationSetDesktopSharingServer.class) != null
               && hasContactCapabilities(contact,
                        OperationSetDesktopSharingServer.class)
               || routingForDesktopEnabled;
    }

    /**
     * Is call enabled for metaContact. If any of the child
     * contacts has call enabled.
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @return is call enabled for metaContact.
     */
    public boolean isCallEnabled(DetailsResponseListener listener)
    {
        return isCallEnabled(listener, true);
    }

    /**
     * Is call enabled for metaContact. If any of the child
     * contacts has call enabled.
     * @param listener the <tt>DetailsResponseListener</tt> to listen for result
     * details
     * @param checkForTelephonyOpSet whether we should check for registered
     * telephony operation sets that can be used to dial out, can be used
     * in plugins dialing out using methods outside the provider.
     * @return is call enabled for metaContact.
     */
    public boolean isCallEnabled(DetailsResponseListener listener,
                                 boolean checkForTelephonyOpSet)
    {
        // make sure children are checked
        if(!checkMetaContactPhones(listener))
            return false;

         boolean hasPhoneCheck = hasPhones;

         if(checkForTelephonyOpSet)
             hasPhoneCheck =
                 hasPhones && AccountUtils.getRegisteredProviders(
                     OperationSetBasicTelephony.class).size() > 0;

        return metaContact.getDefaultContact(
                    OperationSetBasicTelephony.class) != null
               || hasPhoneCheck;
    }

    /**
     * Is call enabled for metaContact. If any of the child
     * contacts has call enabled.
     * @return is call enabled for metaContact.
     */
    public boolean isCallEnabled()
    {
        return isCallEnabled(null, true);
    }

    /**
     * Is call enabled for metaContact. If any of the child
     * contacts has call enabled.
     * @param checkForTelephonyOpSet whether we should check for registered
     * telephony operation sets that can be used to dial out, can be used
     * in plugins dialing out using methods outside the provider.
     * @return is call enabled for metaContact.
     */
    public boolean isCallEnabled(boolean checkForTelephonyOpSet)
    {
        return isCallEnabled(null,
            checkForTelephonyOpSet);
    }

    /**
     * Is call enabled for contact.
     * @param contact to check for call capabilities.
     * @return is call enabled for contact.
     */
    public boolean isCallEnabled(Contact contact)
    {
        if(!checkContactPhones(contact))
            return false;

        return contact.getProtocolProvider().getOperationSet(
                        OperationSetBasicTelephony.class) != null
               && hasContactCapabilities(contact,
                        OperationSetBasicTelephony.class);
    }

    /**
     * Checking all contacts for the metacontact.
     * Return <tt>false</tt> if there are listeners added for a contact
     * and we need to stop executions cause listener will be used to be informed
     * for result.
     *
     * @return whether to continue or listeners present and will be informed
     * for result.
     */
    private boolean checkMetaContactPhones()
    {
        return checkMetaContactPhones(null);
    }

    /**
     * Checking all contacts for the metacontact.
     * Return <tt>false</tt> if there are listeners added for a contact
     * and we need to stop executions cause listener will be used to be informed
     * for result.
     *
     * @param l the <tt>DetailsResponseListener</tt> to listen for further
     * details
     * @return whether to continue or listeners present and will be informed
     * for result.
     */
    private boolean checkMetaContactPhones(DetailsResponseListener l)
    {
        Iterator<Contact> contactIterator = metaContact.getContacts();
        while(contactIterator.hasNext())
        {
            Contact contact = contactIterator.next();
            if(phones.containsKey(contact))
                continue;

            List<String> phones = getPhones(contact, l, false);
            if(phones == null)
                return false;
        }

        return true;
    }

    /**
     * Checking all contacts for the metacontact.
     * Return <tt>false</tt> if there are listeners added for a contact
     * and we need to stop executions cause listener will be used to be informed
     * for result.
     *
     * @param l the <tt>DetailsResponseListener</tt> to listen for further
     * details
     * @return whether to continue or listeners present and will be informed
     * for result.
     */
    private boolean checkMetaContactVideoPhones(DetailsResponseListener l)
    {
        Iterator<Contact> contactIterator = metaContact.getContacts();
        while(contactIterator.hasNext())
        {
            Contact contact = contactIterator.next();
            if(videoPhones.containsKey(contact))
                continue;

            List<String> phones = getVideoPhones(contact, l);
            if(phones == null)
                return false;
        }

        return true;
    }

    /**
     * Checking contact for phones.
     * Return <tt>false</tt> if there are listeners added for the contact
     * and we need to stop executions cause listener will be used to be informed
     * for result.
     *
     * @return whether to continue or listeners present and will be informed
     * for result.
     */
    private boolean checkContactPhones(Contact contact)
    {
        if(!phones.containsKey(contact))
        {
            List<String> phones = getPhones(contact);
            if(phones == null)
                return false;

            // to check for routingForVideoEnabled prop
            isVideoCallEnabled(contact);
            // to check for routingForDesktopEnabled prop
            isDesktopSharingEnabled(contact);
        }

        return true;
    }

    /**
     * Returns <tt>true</tt> if <tt>Contact</tt> supports the specified
     * <tt>OperationSet</tt>, <tt>false</tt> otherwise.
     *
     * @param contact contact to check
     * @param opSet <tt>OperationSet</tt> to search for
     * @return Returns <tt>true</tt> if <tt>Contact</tt> supports the specified
     * <tt>OperationSet</tt>, <tt>false</tt> otherwise.
     */
    private boolean hasContactCapabilities(
            Contact contact, Class<? extends OperationSet> opSet)
    {
        OperationSetContactCapabilities capOpSet =
            contact.getProtocolProvider().
                getOperationSet(OperationSetContactCapabilities.class);

        if (capOpSet == null)
        {
            // assume contact has OpSet capabilities
            return true;
        }
        else
        {
            if(capOpSet.getOperationSet(contact, opSet) != null)
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns localized phone number.
     *
     * @param d the detail.
     * @return the localized phone number.
     */
    protected String getLocalizedPhoneNumber(GenericDetail d)
    {
        if(d instanceof WorkPhoneDetail)
        {
            return UtilActivator.getResources().
                getI18NString(
                    "service.gui.WORK_PHONE");
        }
        else if(d instanceof MobilePhoneDetail)
        {
            return UtilActivator.getResources().
                getI18NString(
                    "service.gui.MOBILE_PHONE");
        }
        else if(d instanceof VideoDetail)
        {
            return UtilActivator.getResources().
                getI18NString(
                    "service.gui.VIDEO_PHONE");
        }
        else
        {
            return UtilActivator.getResources().
                getI18NString(
                    "service.gui.HOME");
        }
    }
}