blob: 98072d231b6f1bf94e2b62234a0a082dff6ff01c [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.auth;
import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.hugegraph.HugeGraphParams;
import org.apache.hugegraph.auth.HugeTarget.P;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.schema.IndexLabel;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.Cardinality;
import org.apache.hugegraph.type.define.DataType;
import org.apache.hugegraph.util.E;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph.Hidden;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
public abstract class SchemaDefine {
protected final HugeGraphParams graph;
protected final String label;
public SchemaDefine(HugeGraphParams graph, String label) {
this.graph = graph;
this.label = label;
}
public abstract void initSchemaIfNeeded();
protected SchemaManager schema() {
return this.graph.graph().schema();
}
protected boolean existVertexLabel(String label) {
return this.graph.graph().existsVertexLabel(label);
}
protected boolean existEdgeLabel(String label) {
return this.graph.graph().existsEdgeLabel(label);
}
protected String createPropertyKey(String name) {
return this.createPropertyKey(name, DataType.TEXT);
}
protected String createPropertyKey(String name, DataType dataType) {
return this.createPropertyKey(name, dataType, Cardinality.SINGLE);
}
protected String createPropertyKey(String name, DataType dataType,
Cardinality cardinality) {
SchemaManager schema = this.schema();
PropertyKey propertyKey = schema.propertyKey(name)
.dataType(dataType)
.cardinality(cardinality)
.build();
this.graph.schemaTransaction().addPropertyKey(propertyKey);
return name;
}
protected String[] initProperties(List<String> props) {
String label = this.label;
props.add(createPropertyKey(hideField(label, AuthElement.CREATE),
DataType.DATE));
props.add(createPropertyKey(hideField(label, AuthElement.UPDATE),
DataType.DATE));
props.add(createPropertyKey(hideField(label, AuthElement.CREATOR)));
return props.toArray(new String[0]);
}
protected IndexLabel createRangeIndex(VertexLabel label, String field) {
SchemaManager schema = this.schema();
String name = Hidden.hide(label + "-index-by-" + field);
IndexLabel indexLabel = schema.indexLabel(name).range()
.on(HugeType.VERTEX_LABEL, this.label)
.by(field)
.build();
this.graph.schemaTransaction().addIndexLabel(label, indexLabel);
return indexLabel;
}
protected static String hideField(String label, String key) {
return label + "_" + key;
}
protected static String unhideField(String label, String key) {
return Hidden.unHide(label) + "_" + key;
}
public abstract static class AuthElement implements Serializable {
private static final long serialVersionUID = 8746691160192814973L;
protected static final String CREATE = "create";
protected static final String UPDATE = "update";
protected static final String CREATOR = "creator";
protected Id id;
protected Date create;
protected Date update;
protected String creator;
public AuthElement() {
this.create = new Date();
this.update = this.create;
}
public Id id() {
return this.id;
}
public void id(Id id) {
this.id = id;
}
public String idString() {
return Hidden.unHide(this.label()) + "(" + this.id + ")";
}
public Date create() {
return this.create;
}
public void create(Date create) {
this.create = create;
}
public Date update() {
return this.update;
}
public void update(Date update) {
this.update = update;
}
public void onUpdate() {
this.update = new Date();
}
public String creator() {
return this.creator;
}
public void creator(String creator) {
this.creator = creator;
}
protected Map<String, Object> asMap(Map<String, Object> map) {
E.checkState(this.create != null,
"Property %s time can't be null", CREATE);
E.checkState(this.update != null,
"Property %s time can't be null", UPDATE);
E.checkState(this.creator != null,
"Property %s can't be null", CREATOR);
if (this.id != null) {
// The id is null when creating
map.put(Hidden.unHide(P.ID), this.id);
}
map.put(unhideField(this.label(), CREATE), this.create);
map.put(unhideField(this.label(), UPDATE), this.update);
map.put(unhideField(this.label(), CREATOR), this.creator);
return map;
}
protected boolean property(String key, Object value) {
E.checkNotNull(key, "property key");
if (key.equals(hideField(this.label(), CREATE))) {
this.create = (Date) value;
return true;
}
if (key.equals(hideField(this.label(), UPDATE))) {
this.update = (Date) value;
return true;
}
if (key.equals(hideField(this.label(), CREATOR))) {
this.creator = (String) value;
return true;
}
return false;
}
protected Object[] asArray(List<Object> list) {
E.checkState(this.create != null,
"Property %s time can't be null", CREATE);
E.checkState(this.update != null,
"Property %s time can't be null", UPDATE);
E.checkState(this.creator != null,
"Property %s can't be null", CREATOR);
list.add(hideField(this.label(), CREATE));
list.add(this.create);
list.add(hideField(this.label(), UPDATE));
list.add(this.update);
list.add(hideField(this.label(), CREATOR));
list.add(this.creator);
return list.toArray();
}
public abstract ResourceType type();
public abstract String label();
public abstract Map<String, Object> asMap();
protected abstract Object[] asArray();
}
// NOTE: travis-ci fails if class Entity implements Nameable
public abstract static class Entity extends AuthElement
implements org.apache.hugegraph.type.Nameable {
private static final long serialVersionUID = 4113319546914811762L;
public static <T extends Entity> T fromVertex(Vertex vertex, T entity) {
E.checkArgument(vertex.label().equals(entity.label()),
"Illegal vertex label '%s' for entity '%s'",
vertex.label(), entity.label());
entity.id((Id) vertex.id());
for (Iterator<VertexProperty<Object>> iter = vertex.properties();
iter.hasNext(); ) {
VertexProperty<Object> prop = iter.next();
entity.property(prop.key(), prop.value());
}
return entity;
}
@Override
public String idString() {
String label = Hidden.unHide(this.label());
String name = this.name();
StringBuilder sb = new StringBuilder(label.length() +
name.length() + 2);
sb.append(label).append("(").append(name).append(")");
return sb.toString();
}
}
public abstract static class Relationship extends AuthElement {
private static final long serialVersionUID = -1406157381685832493L;
public abstract String sourceLabel();
public abstract String targetLabel();
public abstract Id source();
public abstract Id target();
public static <T extends Relationship> T fromEdge(Edge edge,
T relationship) {
E.checkArgument(edge.label().equals(relationship.label()),
"Illegal edge label '%s' for relationship '%s'",
edge.label(), relationship.label());
relationship.id((Id) edge.id());
for (Iterator<Property<Object>> iter = edge.properties();
iter.hasNext(); ) {
Property<Object> prop = iter.next();
relationship.property(prop.key(), prop.value());
}
return relationship;
}
@Override
public String idString() {
String label = Hidden.unHide(this.label());
StringBuilder sb = new StringBuilder(label.length() +
this.source().length() +
this.target().length() + 4);
sb.append(label).append("(").append(this.source())
.append("->").append(this.target()).append(")");
return sb.toString();
}
}
}