wgoodall01/wikipath

View on GitHub
wp/indexpath.go

Summary

Maintainability
A
0 mins
Test Coverage
package wikipath

// Direction is either forward or reverse. This represents
// a direction for the bidirectional search.
type Direction bool

// FORWARD goes forward
const FORWARD Direction = true

// REVERSE goes in reverse
const REVERSE Direction = false

// IndexPath represents a link path through the Index.
type IndexPath struct {
    Item      *IndexItem // Item in the path
    Prev      *IndexPath // The previous item, `nil` if the starting item.
    Direction Direction  // The direction the path is from.
}

// NewIndexPath creates an IndexPath from a starting node and a Direction.
func NewIndexPath(it *IndexItem, direction Direction) *IndexPath {
    return &IndexPath{
        Item:      it,
        Prev:      nil,
        Direction: direction,
    }
}

// NewIndexPathByJoin joins a forward and a reverse path together into one. The
// heads of each path must point to the same item.
// Returns nil if it doesn't work out.
func NewIndexPathByJoin(i1 *IndexPath, i2 *IndexPath) *IndexPath {
    var all *IndexPath
    var rest *IndexPath

    if i1.Direction == FORWARD && i2.Direction == REVERSE {
        all = i1
        rest = i2
    } else if i1.Direction == REVERSE && i2.Direction == FORWARD {
        all = i2
        rest = i1
    } else {
        // They have to be one forwards, one reverse.
        return nil
    }

    if rest.Item != all.Item {
        // They don't join up evenly. Die.
        return nil
    }

    // Advance rest by 1, skip
    rest = rest.Prev

    for rest != nil {
        all = all.Append(rest.Item)
        rest = rest.Prev
    }

    return all
}

// Append returns a new IndexPath by appending `it` to `path`.
func (path *IndexPath) Append(it *IndexItem) *IndexPath {
    return &IndexPath{
        Item:      it,
        Prev:      path,
        Direction: path.Direction,
    }
}

// ToSlice returns the IndexPath as a []*IndexItem.
func (path *IndexPath) ToSlice() []*IndexItem {
    len := path.Len()
    pathArr := make([]*IndexItem, len)
    for i := len - 1; i >= 0; i-- {
        pathArr[i] = path.Item
        path = path.Prev
    }
    return pathArr
}

// ToStringSlice returns the IndexPath as a []string.
func (path *IndexPath) ToStringSlice() []string {
    items := path.ToSlice()
    strings := make([]string, len(items))
    for i, it := range items {
        strings[i] = it.Title
    }
    return strings
}

func (path *IndexPath) Len() int {
    n := 1
    itm := path
    for itm.Prev != nil {
        itm = itm.Prev
        n++
    }
    return n
}

// String converts the IndexPath to a string.
func (path *IndexPath) String() string {
    items := path.ToSlice()
    str := ""
    for i, it := range items {
        if i != 0 {
            str += " > "
        }
        str += it.Title
    }
    return str
}