blob: 54c33b53c37d9772a6b2588ec665be256fc4fafa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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.apache.hugegraph.schema;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.schema.builder.SchemaBuilder;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.IndexType;
import org.apache.hugegraph.util.E;
import com.google.common.base.Objects;
public class IndexLabel extends SchemaElement {
private HugeType baseType;
private Id baseValue;
private IndexType indexType;
private List<Id> indexFields;
public IndexLabel(final HugeGraph graph, Id id, String name) {
super(graph, id, name);
this.baseType = HugeType.SYS_SCHEMA;
this.baseValue = NONE_ID;
this.indexType = IndexType.SECONDARY;
this.indexFields = new ArrayList<>();
}
protected IndexLabel(long id, String name) {
this(null, IdGenerator.of(id), name);
}
@Override
public HugeType type() {
return HugeType.INDEX_LABEL;
}
public HugeType baseType() {
return this.baseType;
}
public void baseType(HugeType baseType) {
this.baseType = baseType;
}
public Id baseValue() {
return this.baseValue;
}
public void baseValue(Id id) {
this.baseValue = id;
}
public IndexType indexType() {
return this.indexType;
}
public void indexType(IndexType indexType) {
this.indexType = indexType;
}
public HugeType queryType() {
switch (this.baseType) {
case VERTEX_LABEL:
return HugeType.VERTEX;
case EDGE_LABEL:
return HugeType.EDGE;
case SYS_SCHEMA:
return HugeType.SYS_SCHEMA;
default:
throw new AssertionError(String.format(
"Query type of index label is either '%s' or '%s', " +
"but '%s' is used",
HugeType.VERTEX_LABEL, HugeType.EDGE_LABEL,
this.baseType));
}
}
public List<Id> indexFields() {
return Collections.unmodifiableList(this.indexFields);
}
public void indexFields(Id... ids) {
this.indexFields.addAll(Arrays.asList(ids));
}
public void indexField(Id id) {
this.indexFields.add(id);
}
public Id indexField() {
E.checkState(this.indexFields.size() == 1,
"There should be only one field in %s index label, " +
"but got: %s", this.indexType.string(), this.indexFields);
return this.indexFields.get(0);
}
public SchemaLabel baseLabel() {
return getBaseLabel(this.graph, this.baseType, this.baseValue);
}
public boolean hasSameContent(IndexLabel other) {
return super.hasSameContent(other) &&
this.indexType == other.indexType &&
this.baseType == other.baseType &&
Objects.equal(this.graph.mapPkId2Name(this.indexFields),
other.graph.mapPkId2Name(other.indexFields));
}
public boolean olap() {
return VertexLabel.OLAP_VL.id().equals(this.baseValue);
}
public Object validValue(Object value) {
if (!(value instanceof Number)) {
return value;
}
Number number = (Number) value;
switch (this.indexType()) {
case RANGE_INT:
return number.intValue();
case RANGE_LONG:
return number.longValue();
case RANGE_FLOAT:
return number.floatValue();
case RANGE_DOUBLE:
return number.doubleValue();
default:
return value;
}
}
// Label index
private static final IndexLabel VL_IL = new IndexLabel(VL_IL_ID, "~vli");
private static final IndexLabel EL_IL = new IndexLabel(EL_IL_ID, "~eli");
// Schema name index
private static final IndexLabel PKN_IL = new IndexLabel(PKN_IL_ID, "~pkni");
private static final IndexLabel VLN_IL = new IndexLabel(VLN_IL_ID, "~vlni");
private static final IndexLabel ELN_IL = new IndexLabel(ELN_IL_ID, "~elni");
private static final IndexLabel ILN_IL = new IndexLabel(ILN_IL_ID, "~ilni");
public static IndexLabel label(HugeType type) {
switch (type) {
case VERTEX:
return VL_IL;
case EDGE:
case EDGE_OUT:
case EDGE_IN:
return EL_IL;
case PROPERTY_KEY:
return PKN_IL;
case VERTEX_LABEL:
return VLN_IL;
case EDGE_LABEL:
return ELN_IL;
case INDEX_LABEL:
return ILN_IL;
default:
throw new AssertionError(String.format(
"No primitive index label for '%s'", type));
}
}
public static IndexLabel label(HugeGraph graph, Id id) {
// Primitive IndexLabel first
if (id.asLong() < 0 && id.asLong() > -NEXT_PRIMITIVE_SYS_ID) {
switch ((int) id.asLong()) {
case VL_IL_ID:
return VL_IL;
case EL_IL_ID:
return EL_IL;
case PKN_IL_ID:
return PKN_IL;
case VLN_IL_ID:
return VLN_IL;
case ELN_IL_ID:
return ELN_IL;
case ILN_IL_ID:
return ILN_IL;
default:
throw new AssertionError(String.format(
"No primitive index label for '%s'", id));
}
}
return graph.indexLabel(id);
}
public static SchemaLabel getBaseLabel(HugeGraph graph,
HugeType baseType,
Object baseValue) {
E.checkNotNull(baseType, "base type", "index label");
E.checkNotNull(baseValue, "base value", "index label");
E.checkArgument(baseValue instanceof String || baseValue instanceof Id,
"The base value must be instance of String or Id, " +
"but got %s(%s)", baseValue,
baseValue.getClass().getSimpleName());
SchemaLabel label;
switch (baseType) {
case VERTEX_LABEL:
if (baseValue instanceof String) {
label = graph.vertexLabel((String) baseValue);
} else {
assert baseValue instanceof Id;
label = graph.vertexLabel((Id) baseValue);
}
break;
case EDGE_LABEL:
if (baseValue instanceof String) {
label = graph.edgeLabel((String) baseValue);
} else {
assert baseValue instanceof Id;
label = graph.edgeLabel((Id) baseValue);
}
break;
default:
throw new AssertionError(String.format(
"Unsupported base type '%s' of index label",
baseType));
}
E.checkArgumentNotNull(label, "Can't find the %s with name '%s'",
baseType.readableName(), baseValue);
return label;
}
public interface Builder extends SchemaBuilder<IndexLabel> {
TaskWithSchema createWithTask();
Id rebuild();
Builder onV(String baseValue);
Builder onE(String baseValue);
Builder by(String... fields);
Builder secondary();
Builder range();
Builder search();
Builder shard();
Builder unique();
Builder on(HugeType baseType, String baseValue);
Builder indexType(IndexType indexType);
Builder userdata(String key, Object value);
Builder userdata(Map<String, Object> userdata);
Builder rebuild(boolean rebuild);
}
}