// viewPathToGraphPath translates the path in a view into a "path" // utilized in graph queries. func viewPathToGraphPath(v *view.View, key string, graphDB *cayley.Handle) (*path.Path, error) { // outputPath is the final tranlated graph path. var outputPath *path.Path // Loop over the paths in the view translating the metadata. for idx, pth := range v.Paths { // We create an alias prefix for tags, so we can track which // path a tag is in. alias := strconv.Itoa(idx+1) + "_" // Sort the view Path value. sort.Sort(pth.Segments) // graphPath will contain the entire strict graph path. var graphPath *path.Path // subPaths will contain each sub path of the full graph path, // as a separate graph path. var subPaths []path.Path // Loop over the path segments translating the path. level := 1 for _, segment := range pth.Segments { // Check that the level is the level we expect (i.e., that the levels // are in order) if level != segment.Level { err := fmt.Errorf("Invalid view path level, expected %d but seeing %d", level, segment.Level) return graphPath, err } // Initialize the path, if we are on level 1. if level == 1 { // Add the first level relationship. switch segment.Direction { case inString: graphPath = cayley.StartPath(graphDB, quad.String(key)).In(quad.String(segment.Predicate)) case outString: graphPath = cayley.StartPath(graphDB, quad.String(key)).Out(quad.String(segment.Predicate)) } // Add the tag, if present. if segment.Tag != "" { graphPath = graphPath.Clone().Tag(alias + segment.Tag) } // Track this as a subpath. subPaths = append(subPaths, *graphPath.Clone()) level++ continue } // Add the relationship. switch segment.Direction { case inString: graphPath = graphPath.Clone().In(quad.String(segment.Predicate)) case outString: graphPath = graphPath.Clone().Out(quad.String(segment.Predicate)) } // Add the tag, if present. if segment.Tag != "" { graphPath = graphPath.Clone().Tag(alias + segment.Tag) } // Add this as a subpath. subPaths = append(subPaths, *graphPath.Clone()) level++ } // If we are forcing a strict path, return only the resulting or // tagged items along the full path. if pth.StrictPath { if outputPath == nil { outputPath = graphPath continue } outputPath = outputPath.Clone().Or(graphPath) continue } // Otherwise add all the subpaths to the output path. for _, subPath := range subPaths { if outputPath == nil { addedPath := &subPath outputPath = addedPath.Clone() continue } outputPath = outputPath.Clone().Or(&subPath) } } return outputPath, nil }