com.eightkdata.mongowp.server.api.impl.MapBasedCommandsExecutor Maven / Gradle / Ivy
/*
* This file is part of mongowp.
*
* mongowp is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mongowp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with mongowp. If not, see .
*
* Copyright (c) 2014, 8Kdata Technology
*
*/
package com.eightkdata.mongowp.server.api.impl;
import com.eightkdata.mongowp.server.api.CommandImplementation;
import com.eightkdata.mongowp.server.api.CommandResult;
import com.eightkdata.mongowp.server.api.CommandReply;
import com.eightkdata.mongowp.server.api.CommandsExecutor;
import com.eightkdata.mongowp.server.api.CommandsLibrary;
import com.eightkdata.mongowp.server.api.Command;
import com.eightkdata.mongowp.server.api.CommandRequest;
import com.eightkdata.mongowp.exceptions.CommandNotSupportedException;
import com.eightkdata.mongowp.exceptions.MongoException;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
@SuppressWarnings("unchecked")
public class MapBasedCommandsExecutor implements CommandsExecutor {
private static final Logger LOGGER
= LoggerFactory.getLogger(MapBasedCommandsExecutor.class);
/**
* A map that associates each command with its implementation.
*
* It is guaranteed by construction that the implementation uses the same
* request and reply than command it is associated with.
*/
private final ImmutableMap implementations;
private MapBasedCommandsExecutor(ImmutableMap implementations) {
this.implementations = implementations;
}
@Override
public CommandReply execute(
@Nonnull Command super Arg, ? super Result> command,
@Nonnull CommandRequest request)
throws MongoException, CommandNotSupportedException {
CommandImplementation implementation = implementations.get(command);
if (implementation == null) {
throw new CommandNotSupportedException(command.getCommandName());
}
try {
CommandResult result = implementation.apply(command, request);
if (command.isReadyToReplyResult(result.getResult())) {
return new DelegateCommandReply<>(command, result);
}
else {
return new CorrectCommandReply<>(command, result);
}
} catch (MongoException ex) {
return new FailedCommandReply<>(ex);
}
}
public static Builder fromLibraryBuilder(CommandsLibrary library) {
return new FromLibraryBuilder(library);
}
public static Builder builder() {
return new UnsafeBuilder();
}
public static interface Builder {
public Builder addImplementation(
@Nonnull Command command,
@Nonnull CommandImplementation implementation);
public Builder addImplementations(
Iterable, CommandImplementation>> entries);
public MapBasedCommandsExecutor build();
}
private static class UnsafeBuilder implements Builder {
private final Map implementations = Maps.newHashMap();
@Override
public Builder addImplementations(
Iterable, CommandImplementation>> entries) {
for (Entry, CommandImplementation> entry : entries) {
addImplementation(entry.getKey(), entry.getValue());
}
return this;
}
@Override
public Builder addImplementation(
Command command,
CommandImplementation implementation) {
if (implementations.containsKey(command)) {
throw new IllegalArgumentException(
"There is another implementation ("
+ implementations.get(command) + " associated to "
+ command);
}
implementations.put(command, implementation);
return this;
}
@Override
public MapBasedCommandsExecutor build() {
return new MapBasedCommandsExecutor(
ImmutableMap.copyOf(implementations)
);
}
}
private static class FromLibraryBuilder extends UnsafeBuilder {
private final @Nullable Set notImplementedCommands;
public FromLibraryBuilder(CommandsLibrary library) {
this.notImplementedCommands = library.getSupportedCommands();
if (this.notImplementedCommands == null) {
LOGGER.warn("An unsafe commands library has been used to "
+ "create an executor. It is impossible to check at "
+ "creation time if all commands supported by the "
+ "library have an associated implementation");
}
}
@Override
public Builder addImplementations(
Iterable, CommandImplementation>> entries) {
for (Entry, CommandImplementation> entry : entries) {
addImplementation(entry.getKey(), entry.getValue());
}
return this;
}
@Override
public Builder addImplementation(
Command command,
CommandImplementation implementation) {
if (notImplementedCommands != null && !notImplementedCommands.remove(command)) {
throw new IllegalArgumentException("Command " + command + " is "
+ "not supported by the given library");
}
return super.addImplementation(command, implementation);
}
@Override
public MapBasedCommandsExecutor build() {
if (notImplementedCommands != null) {
Preconditions.checkState(
notImplementedCommands.isEmpty(),
"The following commands have no implementation: %s",
notImplementedCommands
);
}
return super.build();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy