model/vehicle_journey.go
package model
import (
"encoding/json"
"fmt"
"sync"
"bitbucket.org/enroute-mobi/ara/uuid"
)
const (
VEHICLE_DIRECTION_INBOUND = "inbound"
VEHICLE_DIRECTION_OUTBOUND = "outbound"
)
type VehicleJourneyId ModelId
type VehicleJourney struct {
References References
model Model
Attributes Attributes
CodeConsumer
LineId LineId `json:",omitempty"`
Name string `json:",omitempty"`
id VehicleJourneyId
DestinationName string `json:",omitempty"`
Occupancy string `json:",omitempty"`
DirectionType string `json:",omitempty"`
Origin string `json:",omitempty"`
OriginName string `json:",omitempty"`
Monitored bool
HasCompleteStopSequence bool
}
func NewVehicleJourney(model Model) *VehicleJourney {
vehicleJourney := &VehicleJourney{
model: model,
Attributes: NewAttributes(),
References: NewReferences(),
}
vehicleJourney.codes = make(Codes)
return vehicleJourney
}
func (vehicleJourney *VehicleJourney) modelId() ModelId {
return ModelId(vehicleJourney.id)
}
func (vehicleJourney *VehicleJourney) copy() *VehicleJourney {
vj := *vehicleJourney
vj.Attributes = vehicleJourney.Attributes.Copy()
vj.References = vehicleJourney.References.Copy()
return &vj
}
func (vehicleJourney *VehicleJourney) Id() VehicleJourneyId {
return vehicleJourney.id
}
func (vehicleJourney *VehicleJourney) Line() *Line {
if vehicleJourney.model == nil {
return nil
}
line, ok := vehicleJourney.model.Lines().Find(vehicleJourney.LineId)
if !ok {
return nil
}
return line
}
func (vehicleJourney *VehicleJourney) MarshalJSON() ([]byte, error) {
type Alias VehicleJourney
aux := struct {
Codes Codes `json:",omitempty"`
Attributes Attributes `json:",omitempty"`
References map[string]Reference `json:",omitempty"`
*Alias
Id VehicleJourneyId
StopVisits []StopVisitId `json:",omitempty"`
}{
Id: vehicleJourney.id,
Alias: (*Alias)(vehicleJourney),
}
if !vehicleJourney.Codes().Empty() {
aux.Codes = vehicleJourney.Codes()
}
if !vehicleJourney.Attributes.IsEmpty() {
aux.Attributes = vehicleJourney.Attributes
}
if !vehicleJourney.References.IsEmpty() {
aux.References = vehicleJourney.References.GetReferences()
}
stopVisitIds := []StopVisitId{}
svs := vehicleJourney.model.StopVisits().FindByVehicleJourneyId(vehicleJourney.id)
for i := range svs {
stopVisitIds = append(stopVisitIds, svs[i].Id())
}
if len(stopVisitIds) > 0 {
aux.StopVisits = stopVisitIds
}
return json.Marshal(&aux)
}
func (vehicleJourney *VehicleJourney) ToFormat() []string {
return []string{"RouteRef", "JourneyPatternRef", "DatedVehicleJourneyRef"}
}
func (vehicleJourney *VehicleJourney) Attribute(key string) (string, bool) {
value, present := vehicleJourney.Attributes[key]
return value, present
}
func (vehicleJourney *VehicleJourney) Reference(key string) (Reference, bool) {
value, present := vehicleJourney.References.Get(key)
return value, present
}
func (vehicleJourney *VehicleJourney) UnmarshalJSON(data []byte) error {
type Alias VehicleJourney
aux := &struct {
Codes map[string]string
References map[string]Reference
*Alias
}{
Alias: (*Alias)(vehicleJourney),
}
err := json.Unmarshal(data, aux)
if err != nil {
return err
}
if aux.Codes != nil {
vehicleJourney.CodeConsumer.codes = NewCodesFromMap(aux.Codes)
}
if aux.References != nil {
vehicleJourney.References.SetReferences(aux.References)
}
return nil
}
func (vehicleJourney *VehicleJourney) Save() bool {
return vehicleJourney.model.VehicleJourneys().Save(vehicleJourney)
}
type MemoryVehicleJourneys struct {
uuid.UUIDConsumer
model Model
mutex *sync.RWMutex
byIdentifier map[VehicleJourneyId]*VehicleJourney
byCode *CodeIndex
byLine *Index
byBroadcastedFull map[string]map[VehicleJourneyId]struct{}
}
type VehicleJourneys interface {
uuid.UUIDInterface
New() *VehicleJourney
Find(VehicleJourneyId) (*VehicleJourney, bool)
FindByCode(code Code) (*VehicleJourney, bool)
FindByLineId(LineId) []*VehicleJourney
FullVehicleJourneyExistBySubscriptionId(string, VehicleJourneyId) bool
FindAll() []*VehicleJourney
Save(*VehicleJourney) bool
SetFullVehicleJourneyBySubscriptionId(string, VehicleJourneyId)
Delete(*VehicleJourney) bool
DeleteById(VehicleJourneyId) bool
}
func NewMemoryVehicleJourneys() *MemoryVehicleJourneys {
extractor := func(instance ModelInstance) ModelId { return ModelId((instance.(*VehicleJourney)).LineId) }
return &MemoryVehicleJourneys{
mutex: &sync.RWMutex{},
byIdentifier: make(map[VehicleJourneyId]*VehicleJourney),
byCode: NewCodeIndex(),
byLine: NewIndex(extractor),
byBroadcastedFull: make(map[string]map[VehicleJourneyId]struct{}),
}
}
func (manager *MemoryVehicleJourneys) New() *VehicleJourney {
return NewVehicleJourney(manager.model)
}
func (manager *MemoryVehicleJourneys) SetFullVehicleJourneyBySubscriptionId(id string, vehicleJourneyId VehicleJourneyId) {
manager.mutex.Lock()
vjIds, ok := manager.byBroadcastedFull[id]
if !ok {
vjIds = make(map[VehicleJourneyId]struct{})
manager.byBroadcastedFull[id] = vjIds
}
vjIds[vehicleJourneyId] = struct{}{}
manager.mutex.Unlock()
}
func (manager *MemoryVehicleJourneys) FullVehicleJourneyExistBySubscriptionId(id string, vehicleJourneyId VehicleJourneyId) bool {
manager.mutex.RLock()
_, ok := manager.byBroadcastedFull[id][vehicleJourneyId]
manager.mutex.RUnlock()
return ok
}
func (manager *MemoryVehicleJourneys) TestLenFullVehicleJourneyBySubscriptionId() int {
manager.mutex.RLock()
defer manager.mutex.RUnlock()
return len(manager.byBroadcastedFull)
}
func (manager *MemoryVehicleJourneys) Find(id VehicleJourneyId) (*VehicleJourney, bool) {
manager.mutex.RLock()
vehicleJourney, ok := manager.byIdentifier[id]
manager.mutex.RUnlock()
if ok {
return vehicleJourney.copy(), true
}
return &VehicleJourney{}, false
}
func (manager *MemoryVehicleJourneys) FindByCode(code Code) (*VehicleJourney, bool) {
manager.mutex.RLock()
defer manager.mutex.RUnlock()
id, ok := manager.byCode.Find(code)
if ok {
return manager.byIdentifier[VehicleJourneyId(id)].copy(), true
}
return &VehicleJourney{}, false
}
func (manager *MemoryVehicleJourneys) FindByLineId(id LineId) (vehicleJourneys []*VehicleJourney) {
manager.mutex.RLock()
ids, _ := manager.byLine.Find(ModelId(id))
for _, id := range ids {
vj := manager.byIdentifier[VehicleJourneyId(id)]
vehicleJourneys = append(vehicleJourneys, vj.copy())
}
manager.mutex.RUnlock()
return
}
func (manager *MemoryVehicleJourneys) FindAll() (vehicleJourneys []*VehicleJourney) {
manager.mutex.RLock()
for _, vehicleJourney := range manager.byIdentifier {
vehicleJourneys = append(vehicleJourneys, vehicleJourney.copy())
}
manager.mutex.RUnlock()
return
}
func (manager *MemoryVehicleJourneys) Save(vehicleJourney *VehicleJourney) bool {
manager.mutex.Lock()
defer manager.mutex.Unlock()
if vehicleJourney.Id() == "" {
vehicleJourney.id = VehicleJourneyId(manager.NewUUID())
}
vehicleJourney.model = manager.model
manager.byIdentifier[vehicleJourney.Id()] = vehicleJourney
manager.byCode.Index(vehicleJourney)
manager.byLine.Index(vehicleJourney)
return true
}
func (manager *MemoryVehicleJourneys) Delete(vehicleJourney *VehicleJourney) bool {
return manager.DeleteById(vehicleJourney.id)
}
func (manager *MemoryVehicleJourneys) DeleteById(id VehicleJourneyId) bool {
manager.mutex.Lock()
defer manager.mutex.Unlock()
delete(manager.byIdentifier, id)
manager.byCode.Delete(ModelId(id))
manager.byLine.Delete(ModelId(id))
for subscriptionId, vehicleJourneyIds := range manager.byBroadcastedFull {
delete(vehicleJourneyIds, id)
if len(vehicleJourneyIds) == 0 {
delete(manager.byBroadcastedFull, subscriptionId)
}
}
return true
}
func (manager *MemoryVehicleJourneys) Load(referentialSlug string) error {
var selectVehicleJourneys []SelectVehicleJourney
modelName := manager.model.Date()
sqlQuery := fmt.Sprintf("select * from vehicle_journeys where referential_slug = '%s' and model_name = '%s'", referentialSlug, modelName.String())
_, err := Database.Select(&selectVehicleJourneys, sqlQuery)
if err != nil {
return err
}
for _, vj := range selectVehicleJourneys {
vehicleJourney := manager.New()
vehicleJourney.id = VehicleJourneyId(vj.Id)
if vj.Name.Valid {
vehicleJourney.Name = vj.Name.String
}
if vj.LineId.Valid {
vehicleJourney.LineId = LineId(vj.LineId.String)
}
if vj.OriginName.Valid {
vehicleJourney.OriginName = vj.OriginName.String
}
if vj.DestinationName.Valid {
vehicleJourney.DestinationName = vj.DestinationName.String
}
if vj.DirectionType.Valid {
vehicleJourney.DirectionType = vj.DirectionType.String
}
if vj.Attributes.Valid && len(vj.Attributes.String) > 0 {
if err = json.Unmarshal([]byte(vj.Attributes.String), &vehicleJourney.Attributes); err != nil {
return err
}
}
if vj.References.Valid && len(vj.References.String) > 0 {
references := make(map[string]Reference)
if err = json.Unmarshal([]byte(vj.References.String), &references); err != nil {
return err
}
vehicleJourney.References.SetReferences(references)
}
if vj.Codes.Valid && len(vj.Codes.String) > 0 {
codeMap := make(map[string]string)
if err = json.Unmarshal([]byte(vj.Codes.String), &codeMap); err != nil {
return err
}
vehicleJourney.codes = NewCodesFromMap(codeMap)
}
manager.Save(vehicleJourney)
}
return nil
}