Esempio n. 1
0
// 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
}