/*
* Copyright 2012 NGDATA nv
*
* 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.lilyproject.tools.linkindex.cli;
import java.util.List;
import java.util.Set;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.lilyproject.cli.BaseZkCliTool;
import org.lilyproject.client.LilyClient;
import org.lilyproject.hbaseindex.IndexManager;
import org.lilyproject.linkindex.FieldedLink;
import org.lilyproject.linkindex.LinkIndex;
import org.lilyproject.repository.api.FieldType;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.RecordId;
import org.lilyproject.repository.api.RepositoryException;
import org.lilyproject.repository.api.SchemaId;
import org.lilyproject.repository.api.TypeManager;
import org.lilyproject.util.Version;
import org.lilyproject.util.hbase.HBaseTableFactoryImpl;
import org.lilyproject.util.io.Closer;
public class LinkIndexCli extends BaseZkCliTool {
private Option indexOption;
private Option recordIdOption;
private Option vtagOption;
private Option fieldOption;
private LilyClient lilyClient;
private TypeManager typeManager;
@Override
protected String getCmdName() {
return "lily-query-linkindex";
}
public static void main(String[] args) {
new LinkIndexCli().start(args);
}
@Override
protected String getVersion() {
return Version.readVersion("org.lilyproject", "lily-linkindex-cli");
}
@Override
@SuppressWarnings("static-access")
public List<Option> getOptions() {
List<Option> options = super.getOptions();
indexOption = OptionBuilder
.withArgName("name")
.hasArg()
.withDescription("Index name: either 'incoming' (default, synonym 'backward') or 'outgoing' (synonym: 'forward')")
.withLongOpt("index-name")
.create("in");
options.add(indexOption);
recordIdOption = OptionBuilder
.withArgName("record_id")
.hasArg()
.withDescription("Record ID: UUID.something or USER.something")
.withLongOpt("record")
.create("r");
options.add(recordIdOption);
vtagOption = OptionBuilder
.withArgName("vtag")
.hasArg()
.withDescription("vtag name, for example: last")
.withLongOpt("vtag")
.create("vt");
options.add(vtagOption);
fieldOption = OptionBuilder
.withArgName("field")
.hasArg()
.withDescription("field name, format: {namespace}name")
.withLongOpt("field")
.create("f");
options.add(fieldOption);
return options;
}
@Override
public int run(CommandLine cmd) throws Exception {
int result = super.run(cmd);
if (result != 0) {
return result;
}
lilyClient = new LilyClient(zkConnectionString, 60000);
LRepository repository = lilyClient.getDefaultRepository();
typeManager = repository.getTypeManager();
Configuration hbaseConf = HBaseConfiguration.create();
hbaseConf.set("hbase.zookeeper.quorum", zkConnectionString);
IndexManager indexManager = new IndexManager(hbaseConf, new HBaseTableFactoryImpl(hbaseConf));
LinkIndex linkIndex = new LinkIndex(indexManager, lilyClient);
//
// Determine the index to query
//
boolean incoming = true; // false = outgoing
if (cmd.hasOption(indexOption.getOpt())) {
String index = cmd.getOptionValue(indexOption.getOpt());
if (index.equals("incoming") || index.equals("backward")) {
incoming = true;
} else if (index.equals("outgoing") || index.equals("forward")) {
incoming = false;
} else {
System.err.println("Invalid index name: " + index);
return -1;
}
}
//
// Determine the record id
//
String recordIdParam = cmd.getOptionValue(recordIdOption.getOpt());
if (recordIdParam == null) {
System.out.println("Specify record id with -" + recordIdOption.getOpt());
return 1;
}
RecordId recordId = repository.getIdGenerator().fromString(recordIdParam);
//
// Determine the vtag
//
SchemaId vtagId = null;
if (cmd.hasOption(vtagOption.getOpt())) {
String vtagParam = cmd.getOptionValue(vtagOption.getOpt());
vtagId = typeManager.getFieldTypeByName(new QName("org.lilyproject.vtag", vtagParam)).getId();
}
//
// Determine the field
//
SchemaId fieldId = null;
if (cmd.hasOption(fieldOption.getOpt())) {
if (vtagId == null) {
System.err.println("A field can only be specified in combination with a vtag.");
return -1;
}
String fieldParam = cmd.getOptionValue(fieldOption.getOpt());
FieldType field = typeManager.getFieldTypeByName(QName.fromString(fieldParam));
fieldId = field.getId();
if (!field.getValueType().getDeepestValueType().getBaseName().equals("LINK")) {
System.err.println("The field '" + field.getName() + "' is not a link field.");
return -1;
}
}
//
// Perform the query
//
if (incoming) {
System.out.println("Querying the incoming links (backward index)");
System.out.println("Record id: " + recordId);
System.out.println("vtag id: " + vtagId + getFieldTypeNameSuffix(vtagId));
System.out.println("field id: " + fieldId + getFieldTypeNameSuffix(fieldId));
System.out.println();
if (fieldId != null) {
Set<RecordId> records = linkIndex.getReferrers(recordId, vtagId, fieldId);
printRecords(records);
} else {
Set<FieldedLink> fieldedLinks = linkIndex.getFieldedReferrers(recordId, vtagId);
printFieldedLinks(fieldedLinks);
}
} else {
System.out.println("Querying the outgoing links (forward index)");
System.out.println("Record id: " + recordId);
System.out.println("vtag id: " + vtagId + getFieldTypeNameSuffix(vtagId));
System.out.println("field id: " + fieldId + getFieldTypeNameSuffix(fieldId));
System.out.println();
if (fieldId != null) {
Set<RecordId> records = linkIndex.getForwardLinks(recordId, vtagId, fieldId);
printRecords(records);
} else {
Set<FieldedLink> fieldedLinks = linkIndex.getFieldedForwardLinks(recordId, vtagId);
printFieldedLinks(fieldedLinks);
}
}
return 0;
}
@Override
protected void cleanup() {
Closer.close(lilyClient);
super.cleanup();
}
private String getFieldTypeNameSuffix(SchemaId id) throws RepositoryException, InterruptedException {
if (id == null) {
return "";
} else {
return " -- " + typeManager.getFieldTypeById(id).getName();
}
}
private void printRecords(Set<RecordId> records) {
System.out.println("Result count: " + records.size());
System.out.println();
for (RecordId record : records) {
System.out.println(record);
}
}
private void printFieldedLinks(Set<FieldedLink> fieldedLinks) throws RepositoryException, InterruptedException {
System.out.println("Result count: " + fieldedLinks.size());
System.out.println();
for (FieldedLink link : fieldedLinks) {
QName fieldName = typeManager.getFieldTypeById(link.getFieldTypeId()).getName();
System.out.println(link.getRecordId() + " -- " + fieldName);
}
}
}