1package gojsonld 2 3import ( 4 "reflect" 5 "sort" 6 "strings" 7) 8 9const MAX_CONTEXT_URLS = 10 10 11var ( 12 allKeywords = map[string]bool{ 13 "@base": true, 14 "@context": true, 15 "@container": true, 16 "@default": true, 17 "@embed": true, 18 "@explicit": true, 19 "@graph": true, 20 "@id": true, 21 "@index": true, 22 "@language": true, 23 "@list": true, 24 "@omitDefault": true, 25 "@reverse": true, 26 "@preserve": true, 27 "@set": true, 28 "@type": true, 29 "@value": true, 30 "@vocab": true, 31 } 32) 33 34func isKeyword(key interface{}) bool { 35 switch s := key.(type) { 36 case string: 37 return allKeywords[s] 38 } 39 return false 40} 41 42func isScalar(value interface{}) bool { 43 _, isString := value.(string) 44 _, isFloat64 := value.(float64) 45 _, isFloat32 := value.(float32) 46 _, isInt64 := value.(int64) 47 _, isInt32 := value.(int32) 48 _, isBoolean := value.(bool) 49 if isString || isFloat32 || isFloat64 || isInt32 || 50 isInt64 || isBoolean { 51 return true 52 } 53 return false 54} 55 56func isValueObject(value interface{}) bool { 57 valueMap, isMap := value.(map[string]interface{}) 58 _, containsValue := valueMap["@value"] 59 if isMap && containsValue { 60 return true 61 } 62 return false 63} 64 65func isValidValueObject(value interface{}) bool { 66 valueMap, isMap := value.(map[string]interface{}) 67 if !isMap { 68 return false 69 } 70 if len(valueMap) > 4 { 71 return false 72 } 73 for key := range valueMap { 74 if key != "@value" && key != "@language" && 75 key != "@type" && key != "@index" { 76 return false 77 } 78 } 79 _, hasLanguage := valueMap["@language"] 80 _, hasType := valueMap["@type"] 81 if hasLanguage && hasType { 82 return false 83 } 84 return true 85} 86 87func isListObject(value interface{}) bool { 88 valueMap, isMap := value.(map[string]interface{}) 89 _, containsList := valueMap["@list"] 90 if isMap && containsList { 91 return true 92 } 93 return false 94} 95 96func isNil(value interface{}) bool { 97 switch value.(type) { 98 case string, int64, int32, float64, float32, bool: 99 return false 100 } 101 102 if value == nil || reflect.ValueOf(value).IsNil() { 103 return true 104 } else { 105 return false 106 } 107} 108 109func deepCompareMatters(v1, v2 interface{}, listOrderMatters bool) bool { 110 return reflect.DeepEqual(v1, v2) 111} 112 113func deepCompare(v1, v2 interface{}) bool { 114 return deepCompareMatters(v1, v2, false) 115} 116 117func deepContains(values []interface{}, value interface{}) bool { 118 for _, item := range values { 119 if deepCompare(item, value) { 120 return true 121 } 122 } 123 return false 124} 125 126func deepCopy(value interface{}) interface{} { 127 switch v := value.(type) { 128 case string, int64, int32, float64, float32: 129 valueCopy := v 130 return valueCopy 131 case []interface{}: 132 tmpArray := make([]interface{}, 0) 133 for _, item := range v { 134 tmpArray = append(tmpArray, deepCopy(item)) 135 } 136 return tmpArray 137 case map[string]interface{}: 138 tmpMap := make(map[string]interface{}, 0) 139 for key, item := range v { 140 tmpMap[key] = deepCopy(item) 141 } 142 return tmpMap 143 } 144 return nil 145} 146 147func mergeValue(obj map[string]interface{}, key string, value interface{}) { 148 if obj == nil { 149 return 150 } 151 152 values, ex := obj[key].([]interface{}) 153 if !ex { 154 values = make([]interface{}, 0) 155 } 156 157 if key == "@list" || isListObject(value) || 158 !deepContains(values, value) { 159 values = append(values, value) 160 obj[key] = values 161 return 162 } 163} 164 165type InverseSlice []string 166 167func (is InverseSlice) Swap(i, j int) { 168 is[i], is[j] = is[j], is[i] 169} 170 171func (is InverseSlice) Len() int { 172 return len(is) 173} 174 175func compareShortestLeast(s1, s2 string) bool { 176 if len(s1) != len(s2) { 177 return len(s1) < len(s2) 178 } else { 179 return s1 < s2 180 } 181} 182 183func (is InverseSlice) Less(i, j int) bool { 184 s1, s2 := is[i], is[j] 185 return compareShortestLeast(s1, s2) 186} 187 188func specialSortInverse(keys []string) { 189 sort.Sort(InverseSlice(keys)) 190} 191 192func sortedKeys(inputMap map[string]interface{}) []string { 193 keys := make([]string, 0) 194 for key := range inputMap { 195 keys = append(keys, key) 196 } 197 sort.Strings(keys) 198 return keys 199} 200 201func isAbsoluteIri(value string) bool { 202 // TODO: this is a bit simplistic! 203 return strings.Contains(value, ":") 204} 205 206func isIRI(value interface{}) bool { 207 //TODO improve function 208 valueString, isString := value.(string) 209 if !isString { 210 return false 211 } 212 if strings.HasPrefix(valueString, "_") { 213 return false 214 } 215 if !strings.Contains(valueString, ":") { 216 return false 217 } 218 return true 219} 220 221func isRelativeIri(value string) bool { 222 if !(isKeyword(value) || isAbsoluteIri(value)) { 223 return true 224 } 225 return false 226} 227 228func isNodeObject(value interface{}) bool { 229 valueMap, isMap := value.(map[string]interface{}) 230 if !isMap { 231 return false 232 } 233 _, hasValue := valueMap["@value"] 234 _, hasList := valueMap["@list"] 235 _, hasSet := valueMap["@set"] 236 if !(hasValue || hasList || hasSet) { 237 return true 238 } 239 return false 240} 241 242func isBlankNodeIdentifier(value string) bool { 243 if strings.HasPrefix(value, "_:") { 244 return true 245 } 246 return false 247} 248 249func convertFloatValue(value string) string { 250 minusIndex := strings.Index(value, "-") 251 plusIndex := strings.Index(value, "+") 252 var index int 253 if minusIndex > plusIndex { 254 index = minusIndex 255 } else { 256 index = plusIndex 257 } 258 base := value[:(index - 1)] 259 dotIndex := strings.Index(base, ".") 260 if dotIndex < 0 { 261 base += ".0" 262 } 263 exponent := value[(index + 1):] 264 exponent = strings.TrimLeft(exponent, "0") 265 if exponent == "" { 266 exponent = "0" 267 } 268 if plusIndex > -1 { 269 return base + "E" + exponent 270 } else { 271 return base + "E-" + exponent 272 } 273} 274