Federate.java
/*******************************************************************************
* Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.console.command;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import org.eclipse.rdf4j.common.exception.RDF4JException;
import org.eclipse.rdf4j.console.ConsoleIO;
import org.eclipse.rdf4j.console.ConsoleState;
import org.eclipse.rdf4j.federated.repository.FedXRepositoryConfig;
import org.eclipse.rdf4j.federated.repository.FedXRepositoryConfigBuilder;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.repository.config.RepositoryConfig;
import org.eclipse.rdf4j.repository.config.RepositoryConfigException;
import org.eclipse.rdf4j.repository.manager.RepositoryManager;
/**
* Implements the 'federate' command for the RDF4J Console.
*
* @author Dale Visser
*/
public class Federate extends ConsoleCommand {
@Override
public String getName() {
return "federate";
}
@Override
public String getHelpShort() {
return "Federate existing repositories";
}
@Override
public String getHelpLong() {
return PrintHelp.USAGE
+ "federate <fedID> <repoID_1> <repoID_2> [<repoID_n>]*\n"
+ " <fedId> The id to assign the federated repository.\n"
+ " <repoID1> <repoID2> The id's of at least 2 repositories to federate.\n"
+ " [<repoID_n>]* The id's of 0 or mare additional repositories to federate.\n\n"
+ "You will be prompted to enter a description for the federated repository as well.";
}
/**
* Constructor
*
* @param consoleIO
* @param state
*/
public Federate(ConsoleIO consoleIO, ConsoleState state) {
super(consoleIO, state);
}
/**
* Executes a 'federate' command for the RDF4J Console.
*
* @param parameters the expectations for the tokens in this array are fully documented in {@link PrintHelp} .
*/
@Override
public void execute(String... parameters) {
if (parameters.length < 4) {
writeln(getHelpLong());
} else {
LinkedList<String> plist = new LinkedList<>(Arrays.asList(parameters));
plist.remove(); // "federate"
if (distinctValues(plist)) {
String fedID = plist.pop();
federate(fedID, plist);
} else {
writeError("Duplicate repository id's specified.");
}
}
}
/**
* Check if all values are distinct
*
* @param plist
* @return true if all values are distinct
*/
private boolean distinctValues(Deque<String> plist) {
return plist.size() == new HashSet<>(plist).size();
}
/**
* Add one or more repositories to a repository federation
*
* @param fedID
* @param memberIDs list of member
*/
private void federate(String fedID, Deque<String> memberIDs) {
if (LOGGER.isDebugEnabled()) {
logCallDetails(fedID, memberIDs);
}
RepositoryManager manager = state.getManager();
try {
if (manager.hasRepositoryConfig(fedID)) {
writeError(fedID + " already exists.");
} else if (validateMembers(manager, memberIDs)) {
String description = consoleIO.readln("Federation Description (optional): ");
FedXRepositoryConfig federationConfig = FedXRepositoryConfigBuilder.create()
.withResolvableEndpoint(memberIDs)
.build();
RepositoryConfig config = new RepositoryConfig(fedID, federationConfig);
config.setTitle(description);
manager.addRepositoryConfig(config);
writeln("Federation created.");
}
} catch (RepositoryConfigException | RepositoryException rce) {
writeError("Federation failed", rce);
} catch (RDF4JException rce) {
writeError("I/O exception on federation", rce);
}
}
/**
* Validate members of a federation
*
* @param manager repository manager
* @param memberIDs IDs of the federated repositories
* @return true when all members are present
*/
private boolean validateMembers(RepositoryManager manager, Deque<String> memberIDs) {
boolean result = true;
try {
for (String memberID : memberIDs) {
if (!manager.hasRepositoryConfig(memberID)) {
result = false;
writeError(memberID + " does not exist.");
}
}
} catch (RepositoryException | RepositoryConfigException re) {
writeError(re.getMessage());
}
return result;
}
/**
* Log basic details about calls to federated repositories
*
* @param fedID
* @param memberIDs
*/
private void logCallDetails(String fedID, Deque<String> memberIDs) {
StringBuilder builder = new StringBuilder();
builder.append("Federate called with federation ID = " + fedID + ", and member ID's = ");
for (String member : memberIDs) {
builder.append("[").append(member).append("]");
}
LOGGER.debug(builder.toString());
}
/**
* Get the value of an optional string parameter or the default
*
* @param parameters set of parameters
* @param name parameter name
* @param defaultValue default string value
* @return value or default
*/
private String getOptionalParamValue(Deque<String> parameters, String name, String defaultValue) {
String result = defaultValue;
for (String parameter : parameters) {
if (parameter.length() >= name.length() && parameter.substring(0, name.length()).equalsIgnoreCase(name)) {
String[] parsed = parameter.split("=");
if (parsed.length == 2 && parsed[0].equalsIgnoreCase(name)) {
result = parsed[1].toLowerCase();
parameters.remove(parameter);
break;
}
}
}
return result;
}
}