minor fixes
[sgn.git] / lib / CXGN / Trial / Folder.pm
blobac414c00417236c5413adabd14ca74d7f466069f
2 package CXGN::Trial::Folder;
4 use CXGN::Chado::Cvterm;
6 use Moose;
7 use SGN::Model::Cvterm;
8 use Data::Dumper;
10 has 'bcs_schema' => ( isa => 'Bio::Chado::Schema',
11 is => 'rw',
12 required => 1,
15 has 'folder_id' => (isa => "Int",
16 is => 'rw',
19 has 'children' => (is => 'rw',
20 lazy => 1,
21 default => sub {
22 my $self = shift;
23 $self->_get_children();
27 has 'is_folder' => (isa => 'Bool',
28 is => 'rw',
29 default => 0,
32 has 'folder_type' => (isa => 'Str',
33 is => 'rw',
36 has 'name' => (isa => 'Str',
37 is => 'rw',
38 default => 'Untitled',
41 has 'breeding_program_trial_relationship_id' => (isa => 'Int',
42 is => 'rw',
45 has 'project_parent' => (isa => 'Bio::Chado::Schema::Result::Project::Project',
46 is => 'rw',
49 has 'breeding_program' => (isa => 'Bio::Chado::Schema::Result::Project::Project',
50 is => 'rw',
53 has 'breeding_program_cvterm_id' => (isa => 'Int',
54 is => 'rw',
57 has 'folder_cvterm_id' => (isa => 'Int',
58 is => 'rw',
62 sub BUILD {
63 my $self = shift;
65 my $row = $self->bcs_schema()->resultset('Project::Project')->find( { project_id=>$self->folder_id() });
67 if (!$row) {
68 die "The specified folder with id ".$self->folder_id()." does not exist!";
71 $self->name($row->name());
73 my $breeding_program_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema,'breeding_program', 'project_property')->cvterm_id();
74 $self->breeding_program_cvterm_id($breeding_program_type_id);
76 my $folder_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema,'trial_folder', 'project_property')->cvterm_id();
77 $self->folder_cvterm_id($folder_cvterm_id);
79 my $breeding_program_trial_relationship_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema,'breeding_program_trial_relationship', 'project_relationship')->cvterm_id();
80 $self->breeding_program_trial_relationship_id($breeding_program_trial_relationship_id);
82 my $folder_type = $self->bcs_schema()->resultset('Project::Projectprop')-> search( { project_id => $self->folder_id() });
84 while (my $folder_type_row = $folder_type->next) {
85 if ($folder_type_row->type_id() == $self->folder_cvterm_id() ) {
86 $self->folder_type("folder");
87 $self->is_folder(1);
89 elsif ($folder_type_row->type_id() == $self->breeding_program_cvterm_id()) {
90 #print STDERR "Setting folder type to breeding_program.\n";
91 $self->folder_type("breeding_program");
95 if (!$self->folder_type) {
96 my $cross_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross', 'stock_type')->cvterm_id;
98 my $trial_type_rs = $self->bcs_schema->resultset("Project::Project")->search({ 'me.project_id' => $self->folder_id })->search_related('projectprops');
99 while (my $tt = $trial_type_rs->next()) {
100 if ($tt->type_id == $cross_cvterm_id) {
101 $self->folder_type("cross");
102 } elsif ($tt->value eq 'genotyping_plate') {
103 $self->folder_type("genotyping_trial");
107 if (!$self->folder_type) {
108 $self->folder_type("trial");
112 my $breeding_program_rel_row = $self->bcs_schema()->resultset('Project::ProjectRelationship')->find( { subject_project_id => $self->folder_id(), type_id => $self->breeding_program_trial_relationship_id() });
113 if ($breeding_program_rel_row) {
114 my $parent_row = $self->bcs_schema()->resultset('Project::Project')->find( { project_id=> $breeding_program_rel_row->object_project_id() });
115 $self->project_parent($parent_row);
116 $self->breeding_program($parent_row);
119 my $folder_rel_row = $self->bcs_schema()->resultset('Project::ProjectRelationship')->find( { subject_project_id => $self->folder_id(), type_id => $self->folder_cvterm_id() });
120 if ($folder_rel_row) {
121 my $parent_row = $self->bcs_schema()->resultset('Project::Project')->find( { project_id=> $folder_rel_row->object_project_id() });
122 $self->project_parent($parent_row);
127 # class methods
129 sub create {
130 my $class = shift;
131 my $args = shift;
133 # check if name is already taken
135 my $check_rs = $args->{bcs_schema}->resultset('Project::Project')->search( { name => $args->{name} } );
137 if ($check_rs->count() > 0) {
138 die "The name ".$args->{name}." cannot be used for a folder because it already exists.";
141 my $folder_cvterm = SGN::Model::Cvterm->get_cvterm_row($args->{bcs_schema},'trial_folder', 'project_property');
143 my $project_row = $args->{bcs_schema}->resultset('Project::Project')->create(
145 name => $args->{name},
146 description => $args->{description} || "",
149 my $project_id = $project_row->project_id();
151 my $folder_projectprop_row = $args->{bcs_schema}->resultset('Project::Projectprop')->create(
153 project_id => $project_id,
154 type_id => $folder_cvterm->cvterm_id() }
157 my $folder = CXGN::Trial::Folder->new( { bcs_schema => $args->{bcs_schema}, folder_id => $project_id });
159 $folder->associate_parent($args->{parent_folder_id});
160 $folder->associate_breeding_program($args->{breeding_program_id});
162 return $folder;
166 sub list {
167 my $class = shift;
168 my $args = shift;
169 my $schema = $args->{bcs_schema};
171 my $folder_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema,'trial_folder', 'project_property')->cvterm_id();
172 my $breeding_program_trial_relationship_id = SGN::Model::Cvterm->get_cvterm_row($schema,'breeding_program_trial_relationship', 'project_relationship')->cvterm_id();
174 my $breeding_program_rel;
175 if ($args->{breeding_program_id}) {
176 $breeding_program_rel = $schema->resultset('Project::ProjectRelationship')->search({ 'me.object_project_id' => $args->{breeding_program_id}, 'me.type_id' => $breeding_program_trial_relationship_id })->search_related("subject_project")->search_related("projectprops", {'projectprops.type_id'=>$folder_cvterm_id}, {'+select'=>'subject_project.name', '+as'=>'name' } );
177 } else {
178 $breeding_program_rel = $schema->resultset('Project::ProjectRelationship')->search({ 'me.type_id' => $breeding_program_trial_relationship_id })->search_related("subject_project")->search_related("projectprops", {'projectprops.type_id'=>$folder_cvterm_id}, {'+select'=>'subject_project.name', '+as'=>'name' } );
182 my @folders;
183 while (my $row = $breeding_program_rel->next()) {
184 push @folders, [ $row->project_id(), $row->get_column('name') ];
187 return @folders;
192 ### OBJECT METHODS
195 # return a resultset with children of the folder
197 sub _get_children {
198 my $self = shift;
200 my @children;
202 my $rs = $self->bcs_schema()->resultset("Project::Project")->search_related( 'project_relationship_subject_projects', { object_project_id => $self->folder_id() }, { order_by => 'me.name' });
204 @children = map { $_->subject_project_id() } $rs->all();
206 my @child_folders;
207 foreach my $id (@children) {
208 my $folder = CXGN::Trial::Folder->new( { bcs_schema=> $self->bcs_schema(), folder_id=>$id });
210 if ($self->folder_type() eq "breeding_program") {
211 if ($folder->project_parent()) {
212 if ($folder->project_parent()->name() eq $self->name()) {
213 #print STDERR "Pushing ".$folder->name().$folder->folder_type."\n";
214 push @child_folders, $folder;
217 } else {
218 #print STDERR "parent is not a breeding program... pushing ".$folder->name().$folder->folder_type."...\n";
219 push @child_folders, $folder;
223 return \@child_folders;
226 sub associate_parent {
227 my $self = shift;
228 my $parent_id = shift;
230 my $folder_cvterm_id = $self->folder_cvterm_id();
231 my $breeding_program_trial_relationship_id = $self->breeding_program_trial_relationship_id();
233 #If the user selects 'None' to remove the trial from the folder, then the parent_id will be passed as 0. No new parent will be created.
234 if ($parent_id == 0) {
235 $self->remove_parents;
236 return;
239 my $parent_row = $self->bcs_schema()->resultset("Project::Project")->find( { project_id => $parent_id } );
241 if (!$parent_row) {
242 print STDERR "The folder specified as parent does not exist";
243 return;
246 my $parentprop_row = $self->bcs_schema()->resultset("Project::Projectprop")->find( { project_id => $parent_id, type_id => { -in => [ $folder_cvterm_id, $breeding_program_trial_relationship_id ] } } );
248 if (!$parentprop_row) {
249 print STDERR "The specified parent folder is not of type folder or breeding program. Ignoring.";
250 return;
253 $self->remove_parents;
255 my $project_rel_row = $self->bcs_schema()->resultset('Project::ProjectRelationship')->create({
256 object_project_id => $parent_id,
257 subject_project_id => $self->folder_id(),
258 type_id => $folder_cvterm_id,
260 $project_rel_row->insert();
262 $self->project_parent($parent_row);
264 my $parent_is_child = check_if_folder_is_child_in_tree($self->bcs_schema, $parent_id, $self->children());
265 if ($parent_is_child) {
266 print STDERR 'Parent '.$parent_id.' is child in tree of folder '.$self->folder_id()."\n";
267 my $parent_folder = CXGN::Trial::Folder->new({
268 bcs_schema => $self->bcs_schema,
269 folder_id => $parent_id
271 $parent_folder->remove_parents;
276 sub remove_parents {
277 my $self = shift;
278 #Remove any previous parents
279 my $project_rels = $self->bcs_schema()->resultset('Project::ProjectRelationship')->search({
280 subject_project_id => $self->folder_id(),
281 type_id => $self->folder_cvterm_id()
284 if ($project_rels->count() > 0) {
285 while (my $p = $project_rels->next()) {
286 print STDERR $p->subject_project_id." : ".$p->object_project_id." : Removing parent folder association...\n";
287 $p->delete();
290 return;
293 sub check_if_folder_is_child_in_tree {
294 my $schema = shift;
295 my $folder_id = shift;
296 my $children = shift;
297 foreach (@$children) {
298 my $child_folder_id = $_->folder_id();
299 if ($child_folder_id == $folder_id) {
300 return 1;
301 } else{
302 #print STDERR $child_folder_id."\n";
303 my $child_folder = CXGN::Trial::Folder->new({
304 bcs_schema => $schema,
305 folder_id => $child_folder_id
307 return check_if_folder_is_child_in_tree($schema, $folder_id, $child_folder->children() );
311 return;
314 sub associate_breeding_program {
315 my $self = shift;
316 my $breeding_program_id = shift;
318 if (!$breeding_program_id) {
319 print STDERR "No breeding_program_id provided. Ignoring association.\n";
320 return;
323 my $project_rel_row = $self->bcs_schema()->resultset('Project::ProjectRelationship')->find(
324 { object_project_id => $breeding_program_id,
325 subject_project_id => $self->folder_id(),
328 if (! $project_rel_row) {
329 #print STDERR "Creating folder association with breeding program id= $breeding_program_id, folder_id = ".$self->folder_id().", type_id = ".$self->breeding_program_trial_relationship_id()."\n";
330 $project_rel_row = $self->bcs_schema()->resultset('Project::ProjectRelationship')->create(
332 object_project_id => $breeding_program_id,
333 subject_project_id => $self->folder_id(),
334 type_id => $self->breeding_program_trial_relationship_id(),
337 $project_rel_row->insert();
339 else {
340 $project_rel_row->object_project_id($breeding_program_id);
341 $project_rel_row->update();
344 my $row = $self->bcs_schema()->resultset('Project::Project')->find( { project_id=> $project_rel_row->object_project_id() });
345 $self->breeding_program($row);
349 sub delete_folder {
350 my $self = shift;
352 my $children = $self->children();
353 if (scalar(@$children) > 0) {
354 return;
356 my $delete_folder = $self->bcs_schema->resultset("Project::Project")->find({ project_id => $self->folder_id })->delete();
357 return 1;
360 sub remove_parent {
366 sub remove_child {
371 sub get_jstree_html {
372 my $self = shift;
373 my $parent_type = shift;
374 my $project_type_of_interest = shift // 'trial';
376 my $html = "";
378 $html .= $self->_jstree_li_html($parent_type, $self->folder_id(), $self->name());
379 $html .= "<ul>";
380 my $children = $self->children();
382 if (@$children > 0) {
383 foreach my $child (@$children) {
384 if ($child->is_folder()) {
385 $html .= $child->get_jstree_html('folder', $project_type_of_interest);
387 else {
388 #Only display $project of interest types.
389 if ($child->folder_type eq $project_type_of_interest) {
390 $html .= $self->_jstree_li_html($child->folder_type(), $child->folder_id(), $child->name())."</li>";
395 $html .= '</ul></li>';
396 return $html;
399 sub _jstree_li_html {
400 my $self = shift;
401 my $type = shift;
402 my $id = shift;
403 my $name = shift;
405 my $url = '#';
406 if ($type eq 'trial') {
407 $url = "/breeders/trial/".$id;
408 } elsif ($type eq 'folder') {
409 $url = "/folder/".$id;
410 } elsif ($type eq 'cross') {
411 print STDERR "$id : $name \n";
412 my $cross_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'cross', 'stock_type')->cvterm_id();
413 my $cross_stock = $self->bcs_schema->resultset("Project::Project")->search({ 'me.project_id' => $id })->search_related('nd_experiment_projects')->search_related('nd_experiment')->search_related('nd_experiment_stocks')->search_related('stock', {'stock.type_id'=>$cross_type_id})->first();
414 if ($cross_stock) {
415 $id = $cross_stock->stock_id();
416 $url = "/cross/".$id;
417 return "<li data-jstree='{\"type\":\"$type\"}' id=\"$id\"><a href=\"$url\">".$name.'</a>';
418 } else {
419 return;
423 return "<li data-jstree='{\"type\":\"$type\"}' id=\"$id\"><a href=\"$url\">".$name.'</a>';
429 __PACKAGE__->meta->make_immutable();