sort.go 2.46 KB
Newer Older
zauberstuhl's avatar
zauberstuhl committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
package federation
//
// GangGo Diaspora Federation Library
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import (
  "github.com/Zauberstuhl/go-xml"
  "strings"
  "sort"
)

type XmlOrder struct {
  XMLName xml.Name
  Order []string `xml:"-"`
  Lines []XmlOrderLine `xml:",any"`
}

type XmlOrderLine struct {
  XMLName xml.Name
  Value string `xml:",chardata"`
}

func (order XmlOrder) Len() int { return len(order.Lines) }

func (order XmlOrder) Swap(i, j int) {
  order.Lines[i], order.Lines[j] = order.Lines[j], order.Lines[i]
}

func (order XmlOrder) Less(i, j int) bool {
  for _, o := range order.Order {
    if order.Lines[i].XMLName.Local == o {
      return true
    }
    if order.Lines[j].XMLName.Local == o {
      return false
    }
  }
  // if element order is not
  // avialable ignore it
  return false
}

func (o *XmlOrderLine) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
  o.XMLName = start.Name
  return d.DecodeElement(&(o.Value), &start)
}

func FetchEntityOrder(entity []byte) (string, error) {
  var order []string
  var xmlOrder XmlOrder
  err := xml.Unmarshal(entity, &xmlOrder)
  if err != nil {
    return "", err
  }
  for _, line := range xmlOrder.Lines {
    switch line.XMLName.Local {
    case "author_signature":
    case "parent_author_signature":
    default:
      order = append(order, line.XMLName.Local)
    }
  }
  return strings.Join(order, " "), nil
}

func SortByEntityOrder(order string, entity []byte) (sorted []byte, err error) {
  // if we do not require sorting skip it
  if order == "" {
    return entity, err
  }

  var xmlOrder XmlOrder
  xmlOrder.Order = strings.Split(order, " ")
  err = xml.Unmarshal(entity, &xmlOrder)
  if err != nil {
    return sorted, err
  }

  sort.Sort(xmlOrder)

  sorted, err = xml.MarshalIndent(xmlOrder, "", "  ")
  if err != nil {
    return sorted, err
  }
  return
}