<commit_before>package GenomeDB;

use strict;
use warnings;
use File::Spec;

use FeatureTrack;
use JsonFileStorage;

my $defaultTracklist = {
                        formatVersion => 1,
                        tracks => []
                       };

my $trackListPath = "trackList.json";
my @trackDirHeirarchy = ("tracks", "{tracklabel}", "{refseq}");

sub new {
    my ($class, $dataDir) = @_;

    my $self = {
                dataDir => $dataDir,
                rootStore => JsonFileStorage->new($dataDir, 0, {pretty => 1}),
                trackDirTempl => File::Spec->join($dataDir, @trackDirHeirarchy),
                trackUrlTempl => join("/", @trackDirHeirarchy)
               };
    bless $self, $class;

    return $self;
}

sub writeTrackEntry {
    my ($self, $track) = @_;

    my $setTrackEntry = sub {
        my ($trackData) = @_;
        unless (defined($trackData)) {
            $trackData = $defaultTracklist;
        }
        # we want to add this track entry to the "tracks" list,
        # replacing any existing entry with the same label,
        # and preserving the original ordering
        my $trackIndex;
        my $trackList = $trackData->{tracks};
        foreach my $index (0..$#{$trackList}) {
            $trackIndex = $index
              if ($trackList->[$index]->{label} eq $track->label);
        }
        $trackIndex = ($#{$trackList} + 1) unless defined($trackIndex);

        $trackList->[$trackIndex] = {
                                     label => $track->label,
                                     key => $track->key,
                                     type => $track->type,
                                     config => $track->config
                                    };
        return $trackData;
    };

    $self->{rootStore}->modify($trackListPath, $setTrackEntry);
}

sub createFeatureTrack {
    my ($self, $trackLabel, $config, $key) = @_;
    (my $baseUrl = $self->{trackUrlTempl}) =~ s/\{tracklabel\}/$trackLabel/g;
    return FeatureTrack->new($self->trackDir($trackLabel), $baseUrl,
                             $trackLabel, $config, $key);
}

sub getTrack {
    my ($self, $trackLabel) = @_;

    my $trackList = $self->{rootStore}->get($trackListPath,
                                            $defaultTracklist);
    my @selected = grep { $_->{label} eq $trackLabel } @{$trackList->{tracks}};

    return undef
      if ($#selected < 0);
    # this should never happen
    die "multiple tracks labeled $trackLabel"
      if $#selected > 0;
    my $trackDesc = $selected[0];
    if ($trackDesc->{type} eq "FeatureTrack") {
	(my $baseUrl = $self->{trackUrlTempl}) =~
            s/\{tracklabel\}/$trackLabel/g;
        return FeatureTrack->new($self->trackDir($trackLabel),
				 $baseUrl,
                                 $trackDesc->{label},
                                 $trackDesc->{config},
                                 $trackDesc->{key});
    }
    die "track type \"" . $trackDesc->{type} . "\" not implemented";
}

sub trackDir {
    my ($self, $trackLabel) = @_;
    (my $result = $self->{trackDirTempl}) =~ s/\{tracklabel\}/$trackLabel/g;
    return $result;
}

1;

=head1 AUTHOR

<NAME> E<lt><EMAIL>E<gt>

Copyright (c) 2007-2011 The Evolutionary Software Foundation
<commit_msg>add some basic POD to GenomeDB.pm<commit_after>=head1 NAME

GenomeDB - central "handle" for a directory tree of JBrowse JSON data

=head1 SYNOPSIS

    my $gdb = GenomeDB->new( '/path/to/data/dir' );

    my $track = $gdb->getTrack($tableName);
    #returns an object for the track, e.g. a FeatureTrack

    unless( defined $track ) {
        $track = $gdb->createFeatureTrack( $tableName,
                                           $trackConfig,
                                           $track->{shortLabel} );
    }

=head1 DESCRIPTION

Central "handle" on a directory tree of JBrowse JSON data, containing
accessors for accessing the tracks and (soon) reference sequences it
contains.

=head1 METHODS

=cut

package GenomeDB;

use strict;
use warnings;
use File::Spec;

use FeatureTrack;
use JsonFileStorage;

my $defaultTracklist = {
                        formatVersion => 1,
                        tracks => []
                       };

my $trackListPath = "trackList.json";
my @trackDirHeirarchy = ("tracks", "{tracklabel}", "{refseq}");

=head2 new( '/path/to/data/dir' )

Create a new handle for a data dir.

=cut

sub new {
    my ($class, $dataDir) = @_;

    my $self = {
                dataDir => $dataDir,
                rootStore => JsonFileStorage->new($dataDir, 0, {pretty => 1}),
                trackDirTempl => File::Spec->join($dataDir, @trackDirHeirarchy),
                trackUrlTempl => join("/", @trackDirHeirarchy)
               };
    bless $self, $class;

    return $self;
}

=head2 writeTrackEntry( $track_object )

Record an entry for a new track in the data dir.

=cut

sub writeTrackEntry {
    my ($self, $track) = @_;

    my $setTrackEntry = sub {
        my ($trackData) = @_;
        unless (defined($trackData)) {
            $trackData = $defaultTracklist;
        }
        # we want to add this track entry to the "tracks" list,
        # replacing any existing entry with the same label,
        # and preserving the original ordering
        my $trackIndex;
        my $trackList = $trackData->{tracks};
        foreach my $index (0..$#{$trackList}) {
            $trackIndex = $index
              if ($trackList->[$index]->{label} eq $track->label);
        }
        $trackIndex = ($#{$trackList} + 1) unless defined($trackIndex);

        $trackList->[$trackIndex] = {
                                     label => $track->label,
                                     key => $track->key,
                                     type => $track->type,
                                     config => $track->config
                                    };
        return $trackData;
    };

    $self->{rootStore}->modify($trackListPath, $setTrackEntry);
}

=head2 createFeatureTrack( $label, \%config, $key )

Create a new FeatureTrack object in this data dir with the given
label, config, and key.

=cut

sub createFeatureTrack {
    my ($self, $trackLabel, $config, $key) = @_;
    (my $baseUrl = $self->{trackUrlTempl}) =~ s/\{tracklabel\}/$trackLabel/g;
    return FeatureTrack->new($self->trackDir($trackLabel), $baseUrl,
                             $trackLabel, $config, $key);
}

=head2 getTrack( $trackLabel )

Get a track object (FeatureTrack or otherwise) from the GenomeDB.

=cut

sub getTrack {
    my ($self, $trackLabel) = @_;

    my $trackList = $self->{rootStore}->get($trackListPath,
                                            $defaultTracklist);
    my @selected = grep { $_->{label} eq $trackLabel } @{$trackList->{tracks}};

    return undef
      if ($#selected < 0);
    # this should never happen
    die "multiple tracks labeled $trackLabel"
      if $#selected > 0;
    my $trackDesc = $selected[0];
    if ($trackDesc->{type} eq "FeatureTrack") {
	(my $baseUrl = $self->{trackUrlTempl}) =~
            s/\{tracklabel\}/$trackLabel/g;
        return FeatureTrack->new($self->trackDir($trackLabel),
				 $baseUrl,
                                 $trackDesc->{label},
                                 $trackDesc->{config},
                                 $trackDesc->{key});
    }
    die "track type \"" . $trackDesc->{type} . "\" not implemented";
}

# private method
# Get the data subdirectory for a given track, using its label.
sub trackDir {
    my ($self, $trackLabel) = @_;
    (my $result = $self->{trackDirTempl}) =~ s/\{tracklabel\}/$trackLabel/g;
    return $result;
}

1;

=head1 AUTHOR

<NAME> E<lt><EMAIL>E<gt>

Copyright (c) 2007-2011 The Evolutionary Software Foundation

{'fraction_non_alphanumeric': 0.13973629782833505, 'fraction_numerical': 0.005687693898655636, 'mean_word_length': 1.9463061690784462, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1625749', 'n_tokens_mistral': 2338, 'n_tokens_neox': 2225, 'n_words': 581}