Track Editor/MariaTrackServiceEngine source

From Maria GDK Wiki
Jump to navigation Jump to search

< Back to: Track_service_engine

public class MariaTrackServiceEngine 
{
    private ITrackServiceClient _trackServiceClient;

    #region Connection        
        private void SetDisposed()
        {
            if (_trackServiceClient != null)
            {
                _trackServiceClient.Dispose();
            }
        }
        private void HandleConnect()
        {
            _trackServiceClient.Connect();

            // client is using async connection pattern. Must wait for connection.
            // TODO: Find a better mechanism....
            var cnt = 0;
            while (!_trackServiceClient.Connected && cnt++ < 25) // Max 5 sec or give up....
            {
                Thread.Sleep(200);
            }
            Trace.WriteLine("TrackServiceClient connected on: " + cnt);
        }

        /// <summary>
        /// Get current connection status.
        /// </summary>
        /// <returns>
        /// True if connected, false if not.
        /// </returns>
        public bool IsConnected()
        {     
            if (_trackServiceClient == null || !_trackServiceClient.Connected)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Connect to specified track service
        /// </summary>
        /// <param name="uri">
        /// Track service uri. If not supplied, configuration file definition is used.
        /// </param>
        /// <returns>
        /// True if connected, false if not.
        /// </returns>
        public bool ConnectToTrackService(ref string uri)
        {
            string endpointConfigurationTrack = "TrackService";

            IBindingFactory bindingFactory = new BindingFactory();
            IEndpointAddressFactory endpointAddressFactory = new EndpointAddressFactory();

            SetDisposed();

            Binding binding = bindingFactory.NewFromConfigurationFile(endpointConfigurationTrack);

            EndpointAddress endpoint;

            if (!string.IsNullOrWhiteSpace(uri))
            {
                endpoint = endpointAddressFactory.New(uri);
            }
            else
            {
                endpoint = endpointAddressFactory.NewFromConfigurationFile(endpointConfigurationTrack);
            }

            _trackServiceClient = new TrackServiceClient(binding, endpoint);

            HandleConnect();

            if (!IsConnected())
                return false;

            uri = endpoint.Uri.AbsoluteUri;
            return true;
        }

        /// <summary>
        /// Disconnect from service.
        /// </summary>
        public void Disconnect()
        {
            SetDisposed();
            _trackServiceClient = null;
        }
        #endregion Connection

    #region TrackLists
    /// <summary>
    /// Retreive available tracklists matching the search criterias. 
    /// </summary>
    /// <param name="useFilter">  </param>
    /// <param name="filter">Filter value to use if useFilter is true.</param>
    /// <returns>List of available track list ids.</returns>
    public List<string> GetTrackLists(bool useFilter, string filter)
    {
        if (!IsConnected())
            return null;

        var res = _trackServiceClient.GetTrackListIds();

        if (!useFilter || String.IsNullOrWhiteSpace(filter))
            return new List<string>(res);

        var filteredLists = new List<string>();
        foreach (var tracklist in res)
        {
            if (tracklist.ToUpper().Contains(filter.ToUpper()))
                filteredLists.Add(tracklist);
        }
        return filteredLists;
    }

    /// <summary>
    /// Create a new track list
    /// </summary>
    /// <param name="newList">Track list id (name) of the list to be created.</param>
    /// <returns>True if successfull, othervice false.</returns>
    public bool AddTrackList(string newList)
    {
        if (!IsConnected())
            return false;

        _trackServiceClient.AddTrackList(newList);
        return true;
    }

    /// <summary>
    /// Remove track list, and all track info, if any.
    /// </summary>
    /// <param name="list">Id (name) of list to be removed.</param>
    /// <returns>True if successfull, othervice false.</returns>
    public bool RemoveTrackList(string list)
    {
        if (!IsConnected())
            return false;

        _trackServiceClient.RemoveTrackList(list);
        return true;
    }

    #endregion TrackLists

    #region Track History Options
    /// <summary>
    /// Set default track history options for new track lists. 
    /// </summary>
    /// <param name="options">Track history options</param>
    internal void SetDefaultTrackHistoryOptions(ITrackHistoryOptions options)
    {
        _trackServiceClient.SetDefaultTrackHistoryOptions(TrackHistOptionsToSettings(options));
    }

    /// <summary>
    /// Set track history options for specified track list.
    /// </summary>
    /// <param name="trackList">Track list id</param>
    /// <param name="options">Desired options.</param>
    public void SetTrackHistoryOptions(string trackList, ITrackHistoryOptions options)
    {
        if (!string.IsNullOrWhiteSpace(trackList) /*&& options != null*/)
        {
            _trackServiceClient.SetTrackHistoryOptions(trackList, TrackHistOptionsToSettings(options));
        }
    }

    /// <summary>
    /// Retreive track history options for specified track list.
    /// </summary>
    /// <param name="tracklist"></param>
    /// <returns></returns>
    public ITrackHistoryOptions GetTrackHistoryOptions(string tracklist)
    {
        if (string.IsNullOrWhiteSpace(tracklist))
            return null;

        var tracksQuery = CreateTrackQuery(tracklist, new string[] { });
        var historyQuery = CreateTrackHistoryQuery(new TrackHistoryFilterSpec(), tracksQuery);
        var trackRawHistoryResult = _trackServiceClient.GetSpatialTrackHistory(tracklist, historyQuery);

        if (trackRawHistoryResult == null || trackRawHistoryResult.HistorySettings == null)
        {
            return null;
        }

        return new TrackHistoryOptions
        {
            ChunkEntryCount = trackRawHistoryResult.HistorySettings.ChunkEntryCount,
            PosResolutionCm = trackRawHistoryResult.HistorySettings.PosResolutionCm,
            TimeResolutionMs = trackRawHistoryResult.HistorySettings.TimeResolutionMs
        };
    }

    private static TrackHistorySettings TrackHistOptionsToSettings(ITrackHistoryOptions opt)
    {
        if (opt == null)
            return null;

        var set = new TrackHistorySettings();
        if (opt.ChunkEntryCount.HasValue)
            set.ChunkEntryCount = opt.ChunkEntryCount.Value;

        if (opt.PosResolutionCm.HasValue)
            set.PosResolutionCm = opt.PosResolutionCm.Value;
        if (opt.TimeResolutionMs.HasValue)
            set.TimeResolutionMs = opt.TimeResolutionMs.Value;

        return set;
    }
    #endregion Track History Options

    #region Tracks
    /// <summary>
    /// Retreive available tracks from a specific track list, matching the search criterias. 
    /// </summary>
    /// <param name="tracklist">Track list id</param>
    /// <param name="useIdFilter">True or false</param>
    /// <param name="idFilter">
    ///    If useIdFilter is true and idFilter not empty, only tracks with track id matching the filter are returned. 
    ///    </param>
    /// <param name="useTagFilter">True or false</param>
    /// <param name="tagFilterKey">
    ///     If useTagFilter is true and tagFilterKey not empty, only tracks with tag name matching the filter are returned.
    /// </param>
    /// <param name="tagFilterValue">
    ///     If useTagFilter is true and tagFilterKey and tagFilterValue not empty, 
    ///     only tracks with tag name and value matching the filters are returned.
    /// </param>
    /// <returns>Array of tracks</returns>
    public ITrackData[] GetAllTracks(
        string tracklist, 
        bool useIdFilter, 
        string idFilter, 
        bool useTagFilter, 
        string tagFilterKey, 
        string tagFilterValue)
    {
        if (!IsConnected() || string.IsNullOrWhiteSpace(tracklist))
            return null;

        var trackServiceReader = new TrackServiceReader(new TrackServiceClientResources(_trackServiceClient));
        var tracks = trackServiceReader.GetTracks(tracklist, DateTime.UtcNow);

        if ((!useIdFilter || string.IsNullOrWhiteSpace(idFilter))
            && (!useTagFilter || string.IsNullOrWhiteSpace(tagFilterKey)))
            return tracks.ToArray();

        var returnValues = new List<ITrackData>();
        foreach (var track in tracks)
        {

            if (useIdFilter)
            {
                if (track.TrackItemId.InstanceId.ToUpper().Contains(idFilter.ToUpper()))
                {
                    if (!useTagFilter || string.IsNullOrWhiteSpace(tagFilterKey))
                    {
                        returnValues.Add(track);
                    }
                    else
                    {
                        foreach (var field in track.Fields)
                        {
                            if (field.Key.ToUpper().Contains(tagFilterKey.ToUpper()) &&
                                (string.IsNullOrWhiteSpace(tagFilterValue) ||
                                 field.Value.ToUpper().Contains(tagFilterValue.ToUpper())))
                            {
                                returnValues.Add(track);
                                break;
                            }
                        }
                    }
                }
            }
            else if (useTagFilter)
            {
                foreach (var field in track.Fields)
                {
                    if (field.Key.ToUpper().Contains(tagFilterKey.ToUpper()) &&
                        (string.IsNullOrWhiteSpace(tagFilterValue) ||
                         field.Value.ToUpper().Contains(tagFilterValue.ToUpper())))
                    {
                        returnValues.Add(track);
                        break;
                    }
                }
            }
        }

        return returnValues.ToArray();
    }

    /// <summary>
    /// Retreive specified tracks from a specific track list.
    /// </summary>
    /// <param name="tracklist">Track list id</param>
    /// <param name="trackIds">List of track id of tracks to be retreived.</param>
    /// <returns>Array of tracks</returns>
    public ITrackData[] GetTrackData(string tracklist, params string[] trackIds)
    {
        if (!IsConnected())
            return null;

        ITrackServiceReader trackServiceReader = new TrackServiceReader(new TrackServiceClientResources(_trackServiceClient));
        var tracks = trackServiceReader.GetTracks(tracklist, new List<string>(trackIds), DateTime.UtcNow).ToArray();

        return tracks;
    }

    /// <summary>
    /// Create or update specific track.
    /// </summary>
    /// <param name="tracklist">Track list id</param>
    /// <param name="trackData">Track data.</param>
    /// <returns></returns>
    public bool AddOrUpdateTrack(string tracklist, ITrackData trackData)
    {
        if (!IsConnected())
            return false;

        ITrackServiceWriter trackServiceWriter = new TrackServiceWriter(new TrackServiceClientResources(_trackServiceClient));
        trackServiceWriter.WriteTracks(tracklist, new[] { trackData }, DateTime.UtcNow);

        return true;
    }

    /// <summary>
    /// Remove specified track from specific track list
    /// </summary>
    /// <param name="tracklist">Track list id</param>
    /// <param name="track">Track id</param>
    /// <returns>True if successfull, othervice false.</returns>
    public bool RemoveTrack(string tracklist, string track)
    {
        if (!IsConnected())
            return false;

        // _mariaTrackAccessAPI.DeleteTrackData(_trackServiceClient, tracklist, track) == MariaAPIResult.OperationSucceeded;

        var fdefs = new TrackFieldDefinitions(tracklist);
        var tracks = PackedDeleteMessages(fdefs, new[] { track });

        var trackUpdates = new PackedTrackUpdates { CodedWith = fdefs.GetDefaultFieldDefinitionsQuery().Context };
        trackUpdates.Messages.AddRange(tracks);

        var processResult = _trackServiceClient.ProcessPackedTracks(tracklist, trackUpdates);

        if (processResult == null || processResult.Deleted == 0)
        {
            return false;
        }
        return true;
    }

    #endregion Tracks

    #region Track History
    /// <summary>
    /// Retreive available track history information for specified track & track list, according to filter criterias. 
    /// </summary>
    /// <param name="list"></param>
    /// <param name="historyFilterSpec"></param>
    /// <param name="track"></param>
    /// <returns></returns>
    public List<ITrackHistoryData> GetTrackHistory(string list, ITrackHistoryFilterSpec historyFilterSpec, string track)
    {
        var tracksQuery = CreateTrackQuery(list, new[] { track });

        ITrackServiceReader trackServiceReader = new TrackServiceReader(new TrackServiceClientResources(_trackServiceClient));
        var history = trackServiceReader.GetTrackHistory(list, tracksQuery, historyFilterSpec, DateTime.UtcNow);
        return history;
    }

    #endregion Track History 

    #region Local functions
        private IEnumerable<PackedTrackMessage> PackedDeleteMessages(
                        ITrackFieldDefinitions fieldDefinitions, IEnumerable<string> trackIds)
        {
            var messages = new List<PackedTrackMessage>();
            foreach (var trackId in trackIds)
            {
                var packedMessage = new PackedTrackMessage { MessageType = TrackMessageType.TrackMessageDelete };
                TrackCodec.SetId(trackId, fieldDefinitions, packedMessage);
                messages.Add(packedMessage);
            }
            return messages;
        }
        private static TrackHistoryQuery CreateTrackHistoryQuery(ITrackHistoryFilterSpec historyFilterSpec, TrackQuery tracksQuery)
        {
            var historyQuery = new TrackHistoryQuery();

            var queryItem = new TrackHistoryQueryItem
            {
                Query = tracksQuery,
                CurrentTimeRef = historyFilterSpec.CurrentTimeRef.ToFileTimeUtc()
            };

            if (historyFilterSpec.HistoryTimeLimit.HasValue)
                queryItem.MaxAge = (uint)historyFilterSpec.HistoryTimeLimit.Value.TotalSeconds;

            if (historyFilterSpec.HistoryElementLimit.HasValue)
                queryItem.MaxHistoryPoints = historyFilterSpec.HistoryElementLimit.Value;

            historyQuery.Queries.Add(queryItem);

            return historyQuery;
        }
        private static TrackQuery CreateTrackAreaQuery(GeoRect searchArea)
        {
            var query = new TrackQuery();
            var gq = new TrackGeoQuery { Area = new TrackAreaQuery() };

            gq.Area.AreaPoly.Add(new Position { Lat = searchArea.LowerLeft.Lat, Lon = searchArea.LowerLeft.Lon });
            gq.Area.AreaPoly.Add(new Position { Lat = searchArea.UpperRight.Lat, Lon = searchArea.UpperRight.Lon });

            query.GeoQueries.Add(gq);
            return query;
        }
        private static TrackQuery CreateTrackQuery(string trackListId, IEnumerable<string> trackIds)
        {
            var itemIds = new List<ItemId>();
            foreach (var id in trackIds)
            {
                itemIds.Add(new ItemId(trackListId, id));
            }
            var query = TrackQueryGenerator.CreateMultiTracksQuery(itemIds);
            return query;
        }

       #endregion Local functions
}