/*
* Copyright 2014-2016 CyberVision, Inc.
*
* 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 org.kaaproject.kaa.server.operations.service.akka.messages.core.endpoint;
import akka.actor.ActorRef;
import org.kaaproject.kaa.common.TransportType;
import org.kaaproject.kaa.server.sync.ClientSync;
import org.kaaproject.kaa.server.sync.ConfigurationClientSync;
import org.kaaproject.kaa.server.sync.EventClientSync;
import org.kaaproject.kaa.server.sync.NotificationClientSync;
import org.kaaproject.kaa.server.sync.ServerSync;
import org.kaaproject.kaa.server.sync.UserClientSync;
import org.kaaproject.kaa.server.transport.channel.ChannelAware;
import org.kaaproject.kaa.server.transport.channel.ChannelContext;
import org.kaaproject.kaa.server.transport.channel.ChannelType;
import org.kaaproject.kaa.server.transport.message.Message;
import org.kaaproject.kaa.server.transport.session.SessionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.UUID;
/**
* The Class SyncRequestMessage.
*/
public class SyncRequestMessage extends EndpointAwareMessage implements ChannelAware {
private static final Logger LOG = LoggerFactory.getLogger(SyncRequestMessage.class);
/**
* The command.
*/
private final Message command;
/**
* The request.
*/
private final ClientSync request;
/**
* The session.
*/
private final SessionInfo session;
/**
* Instantiates a new sync request message.
*
* @param session the session
* @param request the request
* @param requestMessage the request message
* @param originator the originator
*/
public SyncRequestMessage(SessionInfo session,
ClientSync request,
Message requestMessage,
ActorRef originator) {
super(session.getApplicationToken(), session.getKey(), originator);
this.command = requestMessage;
this.request = request;
this.session = session;
}
/**
* Gets the request.
*
* @return the request
*/
public ClientSync getRequest() {
return request;
}
@Override
public UUID getChannelUuid() {
return session.getUuid();
}
@Override
public ChannelType getChannelType() {
return session.getChannelType();
}
@Override
public ChannelContext getChannelContext() {
return session.getCtx();
}
public SessionInfo getSession() {
return session;
}
public Message getCommand() {
return command;
}
/**
* Updates a request.
*/
public void updateRequest(ServerSync response) {
UUID channelUuid = getChannelUuid();
LOG.debug("[{}] Cleanup profile request", channelUuid);
request.setProfileSync(null);
if (request.getUserSync() != null) {
LOG.debug("[{}] Cleanup user request", channelUuid);
request.setUserSync(new UserClientSync());
}
if (request.getEventSync() != null) {
LOG.debug("[{}] Cleanup event request", channelUuid);
request.setEventSync(new EventClientSync());
}
if (request.getLogSync() != null) {
LOG.debug("[{}] Cleanup log request", channelUuid);
request.getLogSync().setLogEntries(null);
}
if (request.getNotificationSync() != null) {
LOG.debug("[{}] Cleanup/update notification request", channelUuid);
request.getNotificationSync().setSubscriptionCommands(null);
request.getNotificationSync().setAcceptedUnicastNotifications(null);
}
}
/**
* Merge original sync request with new one.
*
* @param syncRequest sync request to be merged
* @return client sync
*/
public ClientSync merge(SyncRequestMessage syncRequest) {
UUID channelUuid = getChannelUuid();
ClientSync other = syncRequest.getRequest();
LOG.trace("[{}] Merging original request {} with new request {}",
channelUuid, request, other);
request.setRequestId(other.getRequestId());
request.getClientSyncMetaData()
.setProfileHash(other.getClientSyncMetaData().getProfileHash());
LOG.debug("[{}] Updated request id and profile hash", channelUuid);
ClientSync diff = new ClientSync();
diff.setRequestId(other.getRequestId());
diff.setClientSyncMetaData(other.getClientSyncMetaData());
diff.setUseConfigurationRawSchema(other.isUseConfigurationRawSchema());
if (request.getClientSyncMetaData().getApplicationToken() != null) {
LOG.debug("Setting application token, as it was null: {}",
request.getClientSyncMetaData().getApplicationToken());
diff.getClientSyncMetaData()
.setApplicationToken(request.getClientSyncMetaData().getApplicationToken());
} else {
LOG.trace("[{}] Application token is null for request", request);
}
boolean hasProfileSync = other.getProfileSync() != null;
if (hasProfileSync) {
diff.setProfileSync(other.getProfileSync());
request.setProfileSync(other.getProfileSync());
LOG.debug("[{}] Updated profile request", channelUuid);
}
if (other.getConfigurationSync() != null) {
ConfigurationClientSync mergedConfigurationClientSync = hasProfileSync
|| other.isForceConfigurationSync()
? other.getConfigurationSync()
: diff(request.getConfigurationSync(), other.getConfigurationSync());
diff.setConfigurationSync(mergedConfigurationClientSync);
request.setConfigurationSync(other.getConfigurationSync());
LOG.debug("[{}] Updated configuration request", channelUuid);
} else {
if (hasProfileSync) {
diff.setConfigurationSync(request.getConfigurationSync());
}
}
if (other.getNotificationSync() != null) {
NotificationClientSync mergedNotificationClientSync = hasProfileSync
|| other.isForceNotificationSync()
? other.getNotificationSync()
: diff(request.getNotificationSync(), other.getNotificationSync());
diff.setNotificationSync(mergedNotificationClientSync);
request.setNotificationSync(other.getNotificationSync());
LOG.debug("[{}] Updated notification request", channelUuid);
} else {
if (hasProfileSync) {
diff.setNotificationSync(request.getNotificationSync());
}
}
if (other.getUserSync() != null) {
diff.setUserSync(other.getUserSync());
request.setUserSync(other.getUserSync());
LOG.debug("[{}] Updated user request", channelUuid);
}
if (other.getEventSync() != null) {
diff.setEventSync(other.getEventSync());
request.setEventSync(other.getEventSync());
LOG.debug("[{}] Updated event request", channelUuid);
}
if (other.getLogSync() != null) {
diff.setLogSync(other.getLogSync());
request.setLogSync(other.getLogSync());
LOG.debug("[{}] Updated log request", channelUuid);
}
return diff;
}
private ConfigurationClientSync diff(ConfigurationClientSync oldRequest,
ConfigurationClientSync newRequest) {
if (oldRequest == null) {
return newRequest;
} else {
if (!Arrays.equals(oldRequest.getConfigurationHash().array(),
newRequest.getConfigurationHash().array())) {
return newRequest;
} else {
return null;
}
}
}
/**
* Calculate different between requests.
*
* @param oldRequest old request
* @param newRequest new request
* @return difference
*/
private NotificationClientSync diff(NotificationClientSync oldRequest,
NotificationClientSync newRequest) {
if (oldRequest == null) {
return newRequest;
} else {
if ((newRequest.getAcceptedUnicastNotifications() != null
&& newRequest.getAcceptedUnicastNotifications().size() > 0)
|| (newRequest.getSubscriptionCommands() != null
&& newRequest.getSubscriptionCommands().size() > 0)
|| (newRequest.getTopicListHash() != oldRequest.getTopicListHash())) {
return newRequest;
} else {
return null;
}
}
}
/**
* Returns whether a transport a type is valid.
* @param type transport type
* @return true if type is valid otherwise false
*/
public boolean isValid(TransportType type) {
switch (type) {
case EVENT:
return request.getEventSync() != null;
case NOTIFICATION:
return request.getNotificationSync() != null;
case CONFIGURATION:
return request.getConfigurationSync() != null;
case USER:
return request.getUserSync() != null;
case PROFILE:
return request.getProfileSync() != null;
case LOGGING:
return request.getLogSync() != null;
default:
return false;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("SyncRequestMessage [command=");
builder.append(command);
builder.append(", request=");
builder.append(request);
builder.append(", session=");
builder.append(session);
builder.append("]");
return builder.toString();
}
}