1/* 2 Copyright (c) 2012 Kier Davis 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 associated documentation files (the "Software"), to deal in the Software without restriction, 6 including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 furnished to do so, subject to the following conditions: 9 10 The above copyright notice and this permission notice shall be included in all copies or substantial 11 portions of the Software. 12 13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 16 OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18*/ 19 20package gojsonld 21 22import ( 23 "fmt" 24 "math/rand" 25 "strings" 26) 27 28// A Term is the value of a subject, predicate or object i.e. a IRI reference, blank node or 29// literal. 30type Term interface { 31 // Method String should return the NTriples representation of this term. 32 String() string 33 // Returns the value without formatting 34 RawValue() string 35 // Method Equal should return whether this term is equal to another. 36 Equal(Term) bool 37} 38 39// A Resource is an URI / IRI reference. 40type Resource struct { 41 URI string 42} 43 44// Function NewResource returns a new resource object. 45func NewResource(uri string) (term Term) { 46 return Term(&Resource{URI: uri}) 47} 48 49// Method String returns the NTriples representation of this resource. 50func (term Resource) String() (str string) { 51 return fmt.Sprintf("<%s>", term.URI) 52} 53 54// Method Equal returns whether this resource is equal to another. 55func (term Resource) Equal(other Term) bool { 56 if spec, ok := other.(*Resource); ok { 57 return term.URI == spec.URI 58 } 59 60 return false 61} 62 63func (term Resource) RawValue() string { 64 return term.URI 65} 66 67// A Literal is a textual value, with an associated language or datatype. 68type Literal struct { 69 Value string 70 Language string 71 Datatype Term 72} 73 74// Function NewLiteral returns a new literal with the given value. 75func NewLiteral(value string) (term Term) { 76 return Term(&Literal{Value: value}) 77} 78 79// Function NewLiteralWithLanguage returns a new literal with the given value and language. 80func NewLiteralWithLanguage(value string, language string) (term Term) { 81 return Term(&Literal{Value: value, Language: language}) 82} 83 84// Function NewLiteralWithDatatype returns a new literal with the given value and datatype. 85func NewLiteralWithDatatype(value string, datatype Term) (term Term) { 86 return Term(&Literal{Value: value, Datatype: datatype}) 87} 88 89// Function NewLiteralWithLanguageAndDatatype returns a new literal with the given value, language 90// and datatype. Technically a literal cannot have both a language and a datatype, but this function 91// is provided to allow creation of literal in a context where this check has already been made, 92// such as in a parser. 93func NewLiteralWithLanguageAndDatatype(value string, language string, datatype Term) (term Term) { 94 return Term(&Literal{Value: value, Language: language, Datatype: datatype}) 95} 96 97// Method String returns the NTriples representation of this literal. 98func (term Literal) String() (str string) { 99 str = term.Value 100 str = strings.Replace(str, "\\", "\\\\", -1) 101 str = strings.Replace(str, "\"", "\\\"", -1) 102 str = strings.Replace(str, "\n", "\\n", -1) 103 str = strings.Replace(str, "\r", "\\r", -1) 104 str = strings.Replace(str, "\t", "\\t", -1) 105 106 str = fmt.Sprintf("\"%s\"", str) 107 108 if term.Language != "" { 109 str += "@" + term.Language 110 } else if term.Datatype != nil { 111 str += "^^" + term.Datatype.String() 112 } 113 114 return str 115} 116 117// Method Equal returns whether this literal is equivalent to another. 118func (term Literal) Equal(other Term) bool { 119 spec, ok := other.(*Literal) 120 if !ok { 121 return false 122 } 123 124 if term.Value != spec.Value { 125 return false 126 } 127 128 if term.Language != spec.Language { 129 return false 130 } 131 132 if (term.Datatype == nil && spec.Datatype != nil) || (term.Datatype != nil && spec.Datatype == nil) { 133 return false 134 } 135 136 if term.Datatype != nil && spec.Datatype != nil && !term.Datatype.Equal(spec.Datatype) { 137 return false 138 } 139 140 return true 141} 142 143func (term Literal) RawValue() string { 144 return term.Value 145} 146 147// A BlankNode is an RDF blank node i.e. an unqualified URI/IRI. 148type BlankNode struct { 149 ID string 150} 151 152// Function NewBlankNode returns a new blank node with the given ID. 153func NewBlankNode(id string) (term Term) { 154 return Term(&BlankNode{ID: id}) 155} 156 157// Function NewAnonNode returns a new blank node with a pseudo-randomly generated ID. 158func NewAnonNode() (term Term) { 159 return Term(&BlankNode{ID: fmt.Sprintf("anon%016x", rand.Int63())}) 160} 161 162// Method String returns the NTriples representation of the blank node. 163func (term BlankNode) String() (str string) { 164 return "_:" + term.ID 165} 166 167// Method Equal returns whether this blank node is equivalent to another. 168func (term BlankNode) Equal(other Term) bool { 169 if spec, ok := other.(*BlankNode); ok { 170 return term.ID == spec.ID 171 } 172 173 return false 174} 175 176func (term BlankNode) RawValue() string { 177 return term.ID 178} 179 180func isTermBlankNode(term Term) bool { 181 _, isBlankNode := term.(*BlankNode) 182 return isBlankNode 183} 184 185func isTermResource(term Term) bool { 186 _, isResource := term.(*Resource) 187 return isResource 188} 189 190func isTermLiteral(term Term) bool { 191 _, isLiteral := term.(*Literal) 192 return isLiteral 193} 194