/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.datatransfer.*;
import java.awt.im.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import org.jitsi.service.resources.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* A <tt>TransferHandler</tt> that handles dropping of <tt>UIContact</tt>s or
* <tt>String</tt> addresses on a <tt>CallConference</tt>. Dropping such data on
* the <tt>CallDialog</tt> will turn a one-to-one <tt>Call</tt> into a telephony
* conference.
*
* @author Yana Stamcheva
*/
public class CallTransferHandler
extends ExtendedTransferHandler
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* The data flavor used when transferring <tt>UIContact</tt>s.
*/
protected static final DataFlavor uiContactDataFlavor
= new DataFlavor(UIContact.class, "UIContact");
/**
* The logger.
*/
private static final Logger logger
= Logger.getLogger(CallTransferHandler.class);
/**
* The <tt>CallConference</tt> into which the dropped callees are to be
* invited.
*/
private final CallConference callConference;
/**
* Initializes a new <tt>CallTransferHandler</tt> instance which is to
* invite dropped callees to a telephony conference specified by a specific
* <tt>Call</tt> which participates in it.
*
* @param call the <tt>Call</tt> which specifies the telephony conference to
* which dropped callees are to be invited
*/
public CallTransferHandler(Call call)
{
this(call.getConference());
}
/**
* Initializes a new <tt>CallTransferHandler</tt> instance which is to
* invite dropped callees to a specific <tt>CallConference</tt>.
*
* @param callConference the <tt>CallConference</tt> to which dropped
* callees are to be invited
*/
public CallTransferHandler(CallConference callConference)
{
this.callConference = callConference;
}
/**
* Indicates whether a component will accept an import of the given
* set of data flavors prior to actually attempting to import it. We return
* <tt>true</tt> to indicate that the transfer with at least one of the
* given flavors would work and <tt>false</tt> to reject the transfer.
* <p>
* @param comp component
* @param flavor the data formats available
* @return true if the data can be inserted into the component, false
* otherwise
* @throws NullPointerException if <code>support</code> is {@code null}
*/
@Override
public boolean canImport(JComponent comp, DataFlavor[] flavor)
{
for (DataFlavor f : flavor)
{
if (f.equals(DataFlavor.stringFlavor)
|| f.equals(uiContactDataFlavor))
{
return (comp instanceof JPanel);
}
}
return false;
}
/**
* Handles transfers to the chat panel from the clip board or a
* DND drop operation. The <tt>Transferable</tt> parameter contains the
* data that needs to be imported.
* <p>
* @param comp the component to receive the transfer;
* @param t the data to import
* @return true if the data was inserted into the component and false
* otherwise
*/
@Override
public boolean importData(JComponent comp, Transferable t)
{
String callee = null;
ProtocolProviderService provider = null;
if (t.isDataFlavorSupported(uiContactDataFlavor))
{
Object o = null;
try
{
o = t.getTransferData(uiContactDataFlavor);
}
catch (UnsupportedFlavorException e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to drop meta contact.", e);
}
catch (IOException e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to drop meta contact.", e);
}
if (o instanceof ContactNode)
{
UIContact uiContact = ((ContactNode) o).getContactDescriptor();
Iterator<UIContactDetail> contactDetails
= uiContact
.getContactDetailsForOperationSet(
OperationSetBasicTelephony.class)
.iterator();
while (contactDetails.hasNext())
{
UIContactDetail detail = contactDetails.next();
ProtocolProviderService detailProvider
= detail.getPreferredProtocolProvider(
OperationSetBasicTelephony.class);
if (detailProvider != null)
{
/*
* Currently for videobridge conferences we only support
* adding contacts via the account with the videobridge
*/
if (callConference.isJitsiVideobridge())
{
for (Call call : callConference.getCalls())
{
if (detailProvider == call.getProtocolProvider())
{
callee = detail.getAddress();
provider = detailProvider;
break;
}
}
}
else
{
callee = detail.getAddress();
provider = detailProvider;
break;
}
}
}
if (callee == null)
{
/*
* It turns out that the error message to be reported would
* like to display information about the account which could
* not add the dropped callee to the telephony conference.
* Unfortunately, a telephony conference may have multiple
* accounts involved. Anyway, choose the first account
* involved in the telephony conference.
*/
ProtocolProviderService callProvider
= callConference.getCalls().get(0)
.getProtocolProvider();
ResourceManagementService resources
= GuiActivator.getResources();
AccountID accountID = callProvider.getAccountID();
new ErrorDialog(null,
resources.getI18NString("service.gui.ERROR"),
resources.getI18NString(
"service.gui.CALL_NOT_SUPPORTING_PARTICIPANT",
new String[]
{
accountID.getService(),
accountID.getUserID(),
uiContact.getDisplayName()
}))
.showDialog();
}
}
}
else if (t.isDataFlavorSupported(DataFlavor.stringFlavor))
{
InputContext inputContext = comp.getInputContext();
if (inputContext != null)
inputContext.endComposition();
try
{
BufferedReader reader
= new BufferedReader(
DataFlavor.stringFlavor.getReaderForText(t));
try
{
String line;
StringBuilder calleeBuilder = new StringBuilder();
while ((line = reader.readLine()) != null)
calleeBuilder.append(line);
callee = calleeBuilder.toString();
/*
* The value of the local variable provider will be null
* because we have a String only and hence we have no
* associated ProtocolProviderService.
* CallManager.inviteToConferenceCall will accept it.
*/
}
finally
{
reader.close();
}
}
catch (UnsupportedFlavorException e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to drop string.", e);
}
catch (IOException e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to drop string.", e);
}
}
if (callee == null)
return false;
else
{
Map<ProtocolProviderService, List<String>> callees
= new HashMap<ProtocolProviderService, List<String>>();
callees.put(provider, Arrays.asList(callee));
CallManager.inviteToConferenceCall(callees, callConference);
return true;
}
}
}