// Copyright 2014 The Cayley Authors. Any rights reserved. // // 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 graph // Defines the struct which makes the TripleStore possible -- the triple. // // At its heart, it consists of three fields -- Subject, Predicate, and Object. // Three IDs that relate to each other. That's all there is to it. The triples // are the links in the graph, and the existence of node IDs is defined by the // fact that some triple in the graph mentions them. // // This means that a complete representation of the graph is equivalent to a // list of triples. The rest is just indexing for speed. // // Adding fields to the triple is not to be taken lightly. You'll see I mention // provenance, but don't as yet use it in any backing store. In general, there // can be features that can be turned on or off for any store, but I haven't // decided how to allow/disallow them yet. Another such example would be to add // a forward and reverse index field -- forward being "order the list of // objects pointed at by this subject with this predicate" such as first and // second children, top billing, what have you. // // There will never be that much in this file except for the definition, but // the consequences are not to be taken lightly. But do suggest cool features! import "fmt" // Our triple struct, used throughout. type Triple struct { Subject string `json:"subject"` Predicate string `json:"predicate"` Object string `json:"object"` Provenance string `json:"provenance,omitempty"` } func NewTriple() *Triple { return &Triple{} } func MakeTriple(sub string, pred string, obj string, provenance string) *Triple { return &Triple{sub, pred, obj, provenance} } // Direction specifies an edge's type. type Direction byte // List of the valid directions of a triple. const ( Any Direction = iota Subject Predicate Object Provenance ) func (d Direction) String() string { switch d { case Any: return "a" case Subject: return "s" case Predicate: return "p" case Provenance: return "c" case Object: return "o" default: return fmt.Sprint("illegal direction:", byte(d)) } } // Per-field accessor for triples func (t *Triple) Get(d Direction) string { switch d { case Subject: return t.Subject case Predicate: return t.Predicate case Provenance: return t.Provenance case Object: return t.Object default: panic(d.String()) } } func (t *Triple) Equals(o *Triple) bool { return *t == *o } // Pretty-prints a triple. func (t *Triple) ToString() string { return fmt.Sprintf("%s -- %s -> %s\n", t.Subject, t.Predicate, t.Object) } func (t *Triple) IsValid() bool { if t.Subject == "" { return false } if t.Predicate == "" { return false } if t.Object == "" { return false } return true } // Prints a triple in N-Triple format. func (t *Triple) ToNTriple() string { if t.Provenance == "" { //TODO(barakmich): Proper escaping. return fmt.Sprintf("%s %s %s .", t.Subject, t.Predicate, t.Object) } else { return fmt.Sprintf("%s %s %s %s .", t.Subject, t.Predicate, t.Object, t.Provenance) } }