diff --git a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java index 48b0633e2..8d87c46a4 100644 --- a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java +++ b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java @@ -1150,11 +1150,32 @@ private ConferenceInfoDocument.EndpointStatusType getEndpointStatus( return null; } - //to and from need to be "full" + /** + * @param from A document with state full from which to generate a + * "diff". + * @param to A document with state full to which to generate a + * "diff" + * @return a ConferenceInfoDocument, such that when it is applied + * to from using the procedure defined in section 4.6 of RFC4575, + * the result is to. May return null if from and + * to are not found to be different (that is, in case no document + * needs to be sent) + */ protected ConferenceInfoDocument getConferenceInfoDiff( ConferenceInfoDocument from, ConferenceInfoDocument to) + throws IllegalArgumentException { + if (from.getState() != ConferenceInfoDocument.State.FULL) + throw new IllegalArgumentException("The 'from' document needs to" + + "have state=full"); + if (to.getState() != ConferenceInfoDocument.State.FULL) + throw new IllegalArgumentException("The 'to' document needs to" + + "have state=full"); + + if (conferenceInfoDocumentsMatch(from, to)) + return null; + return to; } @@ -1162,13 +1183,162 @@ private int updateConferenceInfoDocument( MediaAwareCallPeerT callPeer, ConferenceInfoDocument diff) { - logger.warn("Received a conference-info partial notification, which we" + - " can't handle. Sending peer: " + callPeer); + logger.warn("Received a conference-info partial notification, which we" + + " can't handle. Sending peer: " + callPeer); return -1; // TODO: generate a new full conf info by applying 'diff' to // callPeer.getConferenceState // return setConferenceInfoDocument(callPeer, newFullConfInfo); } + /** + * @param a A document with state full which to compare to + * b + * @param b A document with state full which to compare to + * a + * @return false if the two documents are found to be different, + * true otherwise (that is, it can return true for non-identical + * documents). + */ + private boolean conferenceInfoDocumentsMatch( + ConferenceInfoDocument a, + ConferenceInfoDocument b) + { + if (a.getState() != ConferenceInfoDocument.State.FULL) + throw new IllegalArgumentException("The 'a' document needs to" + + "have state=full"); + if (b.getState() != ConferenceInfoDocument.State.FULL) + throw new IllegalArgumentException("The 'b' document needs to" + + "have state=full"); + + if (stringsMatch(a.getEntity(), b.getEntity())) + return false; + else if (a.getUserCount() != b.getUserCount()) + return false; + else if (a.getUsers().size() != b.getUsers().size()) + return false; + + for(ConferenceInfoDocument.User aUser : a.getUsers()) + { + if (!usersMatch(aUser, b.getUser(aUser.getEntity()))) + return false; + } + return true; + } + + /** + * Checks whether two ConferenceInfoDocument.User instances + * match according to the needs of our implementation. Can return + * true for users which are not identical. + * + * @param a A ConferenceInfoDocument.User to compare + * @param b A ConferenceInfoDocument.User to compare + * @return false if a and b are found to be + * different in a way that is significant for our needs, true + * otherwise. + */ + private boolean usersMatch( + ConferenceInfoDocument.User a, + ConferenceInfoDocument.User b) + { + if (a == null && b == null) + return true; + else if (a == null || b == null) + return false; + else if (!stringsMatch(a.getEntity(), b.getEntity())) + return false; + else if (!stringsMatch(a.getDisplayText(), b.getDisplayText())) + return false; + else if (a.getEndpoints().size() != b.getEndpoints().size()) + return false; + + for (ConferenceInfoDocument.Endpoint aEndpoint : a.getEndpoints()) + { + if (!endpointsMatch(aEndpoint, b.getEndpoint(aEndpoint.getEntity()))) + return false; + } + + return true; + } + + /** + * Checks whether two ConferenceInfoDocument.Endpoint instances + * match according to the needs of our implementation. Can return + * true for endpoints which are not identical. + * + * @param a A ConferenceInfoDocument.Endpoint to compare + * @param b A ConferenceInfoDocument.Endpoint to compare + * @return false if a and b are found to be + * different in a way that is significant for our needs, true + * otherwise. + */ + private boolean endpointsMatch( + ConferenceInfoDocument.Endpoint a, + ConferenceInfoDocument.Endpoint b) + { + if (a == null && b == null) + return true; + else if (a == null || b == null) + return false; + else if (!stringsMatch(a.getEntity(), b.getEntity())) + return false; + else if (a.getStatus() != b.getStatus()) + return false; + else if (a.getMedias().size() != b.getMedias().size()) + return false; + + for (ConferenceInfoDocument.Media aMedia : a.getMedias()) + { + if (!mediasMatch(aMedia, b.getMedia(aMedia.getId()))) + return false; + } + return true; + } + + /** + * Checks whether two ConferenceInfoDocument.Media instances + * match according to the needs of our implementation. Can return + * true for endpoints which are not identical. + * + * @param a A ConferenceInfoDocument.Media to compare + * @param b A ConferenceInfoDocument.Media to compare + * @return false if a and b are found to be + * different in a way that is significant for our needs, true + * otherwise. + */ + private boolean mediasMatch( + ConferenceInfoDocument.Media a, + ConferenceInfoDocument.Media b) + { + if (a == null && b == null) + return true; + else if (a == null || b == null) + return false; + else if (!stringsMatch(a.getId(), b.getId())) + return false; + else if (!stringsMatch(a.getSrcId(), b.getSrcId())) + return false; + else if (!stringsMatch(a.getType(), b.getType())) + return false; + else if (!stringsMatch(a.getStatus(), b.getStatus())) + return false; + + return true; + } + + /** + * @param a A String to compare to b + * @param b A String to compare to a + * @return true if and only if a and b are both + * null, or they are equal as Strings + */ + private boolean stringsMatch(String a, String b) + { + if (a == null && b == null) + return true; + else if (a == null || b == null) + return false; + return a.equals(b); + } }