4 CXGN::Location - helper class for locations
8 my $location = CXGN::Location->new( { bcs_schema => $schema } );
9 $location->set_altitude(280);
14 Bryan Ellerbrock <bje24@cornell.edu>
20 package CXGN
::Location
;
25 use SGN
::Model
::Cvterm
;
28 isa
=> 'Bio::Chado::Schema',
34 isa
=> 'Bio::Chado::Schema::Result::NaturalDiversity::NdGeolocation',
38 has
'nd_geolocation_id' => (
48 has
'abbreviation' => (
53 has
'country_name' => (
58 has
'country_code' => (
63 has
'breeding_program' => (
68 has
'location_type' => (
91 print STDERR
"RUNNING BUILD FOR LOCATION.PM...\n";
93 if ($self->nd_geolocation_id){
94 $location = $self->bcs_schema->resultset("NaturalDiversity::NdGeolocation")->find( { nd_geolocation_id
=> $self->nd_geolocation_id });
95 $self->location($location);
97 if (defined $location) {
98 $self->location( $self->location || $location );
99 $self->nd_geolocation_id( $self->nd_geolocation_id || $location->nd_geolocation_id );
100 $self->name( $self->name || $location->description );
101 $self->latitude( $self->latitude || $location->latitude );
102 $self->longitude( $self->longitude || $location->longitude );
103 $self->altitude( $self->altitude || $location->altitude );
104 $self->abbreviation( $self->abbreviation || $self->_get_ndgeolocationprop('abbreviation', 'geolocation_property') );
105 $self->country_name( $self->country_name || $self->_get_ndgeolocationprop('country_name', 'geolocation_property') );
106 $self->country_code( $self->country_code || $self->_get_ndgeolocationprop('country_code', 'geolocation_property') );
107 $self->breeding_program( $self->breeding_program || $self->_get_ndgeolocationprop('breeding_program', 'project_property') );
108 $self->location_type( $self->location_type || $self->_get_ndgeolocationprop('location_type', 'geolocation_property') );
116 my $schema = $self->bcs_schema();
119 my $nd_geolocation_id = $self->nd_geolocation_id();
120 my $name = $self->name();
121 my $abbreviation = $self->abbreviation();
122 my $country_name = $self->country_name();
123 my $country_code = $self->country_code();
124 my $breeding_program = $self->breeding_program();
125 my $location_type = $self->location_type();
126 my $latitude = $self->latitude();
127 my $longitude = $self->longitude();
128 my $altitude = $self->altitude();
130 # Validate properties
132 if (!$nd_geolocation_id && !$name) {
133 return { error
=> "Cannot add a new location with an undefined name. A location name is required" };
135 elsif (!$nd_geolocation_id && !$self->_is_valid_name($name)) { # can't add a new location with name that already exists
136 return { error
=> "The location - $name - already exists. Please choose another name, or use the existing location" };
139 if ($abbreviation && !$self->_is_valid_abbreviation($abbreviation)) {
140 return { error
=> "Abbreviation $abbreviation already exists in the database. Please choose another abbreviation" };
143 if ($country_name && $country_name =~ m/[0-9]/) {
144 return { error
=> "Country name $country_name is not a valid ISO standard country name." };
147 if ($country_code && ($country_code !~ m/^[^a-z]*$/) || (length($country_code) != 3 )) {
148 return { error
=> "Country code $country_code is not a valid ISO Alpha-3 code." };
151 if ($breeding_program && !$self->_is_valid_program($breeding_program)) { # can't use a breeding program that doesn't exist
152 return { error
=> "Breeding program $breeding_program doesn't exist in the database." };
155 if ($location_type && !$self->_is_valid_type($location_type)) {
156 return { error
=> "Location type $location_type must be must be one of the following: Farm, Field, Greenhouse, Screenhouse, Lab, Storage, Other." };
159 if ( ($latitude && $latitude !~ /^-?[0-9.]+$/) || ($latitude && $latitude < -90) || ($latitude && $latitude > 90)) {
160 return { error
=> "Latitude (in degrees) must be a number between 90 and -90." };
163 if ( ($longitude && $longitude !~ /^-?[0-9.]+$/) || ($longitude && $longitude < -180) || ($longitude && $longitude > 180)) {
164 return { error
=> "Longitude (in degrees) must be a number between 180 and -180." };
167 if ( ($altitude && $altitude !~ /^-?[0-9.]+$/) || ($altitude && $altitude < -418) || ($altitude && $altitude > 8848) ) {
168 return { error
=> "Altitude (in meters) must be a number between -418 (Dead Sea) and 8,848 (Mt. Everest)." };
171 # Add new location if no id supplied
172 if (!$nd_geolocation_id) {
173 print STDERR
"Checks completed, adding new location $name\n";
175 my $new_row = $schema->resultset('NaturalDiversity::NdGeolocation')
177 description
=> $name,
180 if ($longitude) { $new_row->longitude($longitude); }
181 if ($latitude) { $new_row->latitude($latitude); }
182 if ($altitude) { $new_row->altitude($altitude); }
185 #$self->ndgeolocation_id($new_row->ndgeolocation_id());
186 $self->location($new_row);
189 $self->_store_ndgeolocationprop('abbreviation', 'geolocation_property', $abbreviation);
192 $self->_store_ndgeolocationprop('country_name', 'geolocation_property', $country_name);
195 $self->_store_ndgeolocationprop('country_code', 'geolocation_property', $country_code);
197 if ($breeding_program){
198 my $id = $self->bcs_schema->resultset("Project::Project")->search({ name
=> $breeding_program })->first->project_id();
199 $self->_store_ndgeolocationprop('breeding_program', 'project_property', $id);
202 $self->_store_ndgeolocationprop('location_type', 'geolocation_property', $location_type);
211 print STDERR
"Error creating location $name: $error\n";
212 return { error
=> $error };
214 print STDERR
"Location $name added successfully\n";
215 return { success
=> "Location $name added successfully\n" };
218 # Edit existing location if id supplied
219 elsif ($nd_geolocation_id) {
220 print STDERR
"Checks completed, editing existing location $name\n";
222 my $row = $schema->resultset("NaturalDiversity::NdGeolocation")->find({ nd_geolocation_id
=> $nd_geolocation_id });
223 $row->description($name);
224 $row->latitude($latitude);
225 $row->longitude($longitude);
226 $row->altitude($altitude);
230 $self->_store_ndgeolocationprop('abbreviation', 'geolocation_property', $abbreviation);
233 $self->_store_ndgeolocationprop('country_name', 'geolocation_property', $country_name);
236 $self->_store_ndgeolocationprop('country_code', 'geolocation_property', $country_code);
238 if ($breeding_program){
239 my $id = $self->bcs_schema->resultset("Project::Project")->search({ name
=> $breeding_program })->first->project_id();
240 $self->_store_ndgeolocationprop('breeding_program', 'project_property', $id);
243 $self->_store_ndgeolocationprop('location_type', 'geolocation_property', $location_type);
251 print STDERR
"Error editing location $name: $error\n";
252 return { error
=> $error };
254 print STDERR
"Location $name was successfully updated\n";
255 return { success
=> "Location $name was successfully updated\n" };
260 sub delete_location
{
263 my $row = $self->bcs_schema->resultset("NaturalDiversity::NdGeolocation")->find({ nd_geolocation_id
=> $self->nd_geolocation_id() });
264 my $name = $row->description();
265 my @experiments = $row->nd_experiments;
266 #print STDERR "Associated experiments: ".Dumper(@experiments)."\n";
269 my $error = "Location $name cannot be deleted because there are ".scalar @experiments." measurements associated with it from at least one trial.\n";
271 return { error
=> $error };
275 return { success
=> "Location $name was successfully deleted.\n" };
279 sub _get_ndgeolocationprop
{
284 my $ndgeolocationprop_type_id = SGN
::Model
::Cvterm
->get_cvterm_row($self->bcs_schema, $type, $cv)->cvterm_id();
285 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdGeolocationprop")->search({ nd_geolocation_id
=> $self->nd_geolocation_id(), type_id
=> $ndgeolocationprop_type_id }, { order_by
=> {-asc
=> 'nd_geolocationprop_id'} });
288 while (my $r = $rs->next()){
289 push @results, $r->value;
291 my $res = join ',', @results;
295 sub _store_ndgeolocationprop
{
300 #print STDERR " Storing value $value with type $type\n";
301 my $type_id = SGN
::Model
::Cvterm
->get_cvterm_row($self->bcs_schema, $type, $cv)->cvterm_id();
302 my $row = $self->bcs_schema()->resultset("NaturalDiversity::NdGeolocationprop")->find( { type_id
=>$type_id, nd_geolocation_id
=> $self->nd_geolocation_id() } );
308 my $stored_ndgeolocationprop = $self->location->create_geolocationprops({ $type => $value}, {cv_name
=> $cv });
312 sub _remove_ndgeolocationprop
{
317 my $type_id = SGN
::Model
::Cvterm
->get_cvterm_row($self->bcs_schema, $type, $cv)->cvterm_id();
318 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdGeolocationprop")->search( { type_id
=>$type_id, nd_geolocation_id
=> $self->nd_geolocation_id(), value
=>$value } );
320 if ($rs->count() == 1) {
321 $rs->first->delete();
324 elsif ($rs->count() == 0) {
328 print STDERR
"Error removing ndgeolocationprop from location ".$self->ndgeolocation_id().". Please check this manually.\n";
337 my $schema = $self->bcs_schema();
338 my $existing_name_count = $schema->resultset('NaturalDiversity::NdGeolocation')->search( { description
=> $name } )->count();
339 if ($existing_name_count > 0) {
347 sub _is_valid_abbreviation
{
349 my $abbreviation = shift;
350 my $schema = $self->bcs_schema();
351 my $existing_abbreviation_count = $schema->resultset('NaturalDiversity::NdGeolocationprop')->search( { value
=> $abbreviation } )->count();
352 if ($existing_abbreviation_count > 0) {
360 sub _is_valid_program
{
363 my $schema = $self->bcs_schema();
364 my $existing_program_count = $schema->resultset('Project::Project')->search(
366 'type.name'=> 'breeding_program',
367 'me.name' => $program
376 if ($existing_program_count < 1) {
396 if (!$valid_types{$type}) {