1 /* Options.java 2 * 3 * created: Thu Dec 10 1998 4 * 5 * This file is part of Artemis 6 * 7 * Copyright (C) 1998,1999,2000 Genome Research Limited 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 2 12 * of the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 * 23 * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/Options.java,v 1.15 2009-06-19 15:18:04 tjc Exp $ 24 **/ 25 26 package uk.ac.sanger.artemis; 27 28 import uk.ac.sanger.artemis.util.*; 29 import uk.ac.sanger.artemis.components.Splash; 30 import uk.ac.sanger.artemis.io.Key; 31 import uk.ac.sanger.artemis.io.KeyVector; 32 import uk.ac.sanger.artemis.io.QualifierInfo; 33 import uk.ac.sanger.artemis.io.QualifierInfoVector; 34 import uk.ac.sanger.artemis.io.QualifierInfoException; 35 import uk.ac.sanger.artemis.io.EntryInformation; 36 import uk.ac.sanger.artemis.io.SimpleEntryInformation; 37 38 39 import java.awt.Color; 40 import java.awt.Font; 41 import java.io.File; 42 import java.io.IOException; 43 import java.io.InputStream; 44 import java.util.Enumeration; 45 import java.util.Hashtable; 46 import java.util.Properties; 47 import java.util.Vector; 48 49 50 /** 51 * An object of this class is used to read, write and store all the 52 * configurable options in Diana. The method Properties.load () is used to 53 * read in new options. 54 * 55 * @author Kim Rutherford 56 * @version $Id: Options.java,v 1.15 2009-06-19 15:18:04 tjc Exp $ 57 **/ 58 59 public class Options extends Properties 60 { 61 private static final long serialVersionUID = 1L; 62 63 /** 64 * This is the object that will be returned by getOptions(). 65 **/ 66 static private Options options = new Options(); 67 68 /** The name of the "direct edit" option. */ 69 static private final String direct_edit_string = "direct_edit"; 70 71 /** The name of the "eukaryotic mode" option. */ 72 static private final String eukaryotic_mode_string = "organism_type"; 73 74 /** The name of the "highlight active entry" option. */ 75 static private final String highlight_active_entry_string = 76 "highlight_active_entry"; 77 78 /** Cache for getDisplayQualifierNames(). */ 79 private static StringVector display_gene_qualifier_names = null; 80 81 /** Cache for getSystematicQualifierNames(). */ 82 private static StringVector systematic_gene_qualifier_names = null; 83 84 /** Cache for getAllGeneNames(). */ 85 private static StringVector all_gene_qualifier_names = null; 86 87 /** Used as cache by readWritePossible(). */ 88 private static Boolean read_succeeded = null; 89 90 /** The EntryInformation object to use for EMBL and GENBANK entries. */ 91 private static EntryInformation extended_entry_information; 92 93 /** The EntryInformation object to use for EMBL and GENBANK entries. */ 94 private static EntryInformation db_entry_information; 95 96 /** The default font that should be used for all windows. */ 97 private Font font = null; 98 99 /** 100 * A map of colour numbers to Color object. This is initialised by 101 * setDefaultColourMap(). 102 **/ 103 private Vector<Color> colour_map = null; 104 105 /** A vector containing ExternalProgram objects that we can run. */ 106 private ExternalProgramVector external_programs = null; 107 108 /** A vector containing ExternalProgram objects that we can run. */ 109 private ExternalProgramVector ncbi_programs = null; 110 111 /** A vector of those objects listening for option change events. */ 112 private Hashtable option_listener_hash = new Hashtable(); 113 114 /** Set by getInvisibleQualifiers() and reset by resetCachedValues() */ 115 private StringVector invisible_qualifiers = null; 116 117 public static String CACHE_PATH = 118 System.getProperty("user.home") + File.separatorChar + 119 ".artemis" + File.separatorChar + "cache" + File.separatorChar; 120 121 /** 122 * Create a new Options object with default settings for the options. 123 **/ Options()124 public Options() 125 { 126 try 127 { 128 put("font_size", "14"); 129 reset(); 130 } 131 catch(Throwable e) 132 { 133 e.printStackTrace(); 134 } 135 } 136 137 /** 138 * Returns true if and only if the given String is not "no", "false", "n" 139 * or "f". 140 **/ getPropertyTruthValueInternal(final String value)141 private boolean getPropertyTruthValueInternal(final String value) 142 { 143 if(value == null) 144 return false; 145 146 final String lowercase_value = value.toLowerCase(); 147 148 if(lowercase_value.equals("false") || 149 lowercase_value.equals("f") || lowercase_value.equals("no") || 150 lowercase_value.equals("n")) 151 return false; 152 else 153 return true; 154 } 155 156 /** 157 * Returns true if and only if the given property is set and is not "no", 158 * "false", "n" or "f". 159 **/ getPropertyTruthValue(final String name)160 public boolean getPropertyTruthValue(final String name) 161 { 162 return getPropertyTruthValueInternal(getProperty(name)); 163 } 164 165 /** 166 * Names of qualifiers to search when attempting to find the primary or 167 * display name of a gene. 168 **/ getDisplayQualifierNames()169 public StringVector getDisplayQualifierNames() 170 { 171 if(display_gene_qualifier_names == null) 172 { 173 final String name_string = getProperty("display_name_qualifiers"); 174 175 if(name_string == null) 176 { 177 display_gene_qualifier_names = new StringVector(); 178 display_gene_qualifier_names.add("gene"); 179 } 180 else 181 display_gene_qualifier_names = StringVector.getStrings(name_string); 182 } 183 return display_gene_qualifier_names; 184 } 185 186 /** 187 * Names of qualifiers to search when attempting to find the systematic 188 * name of a gene. 189 **/ getSystematicQualifierNames()190 public StringVector getSystematicQualifierNames() 191 { 192 if(systematic_gene_qualifier_names == null) 193 { 194 final String name_string = getProperty("systematic_name_qualifiers"); 195 196 if(name_string == null) 197 { 198 systematic_gene_qualifier_names = new StringVector(); 199 systematic_gene_qualifier_names.add("gene"); 200 } 201 else 202 systematic_gene_qualifier_names = 203 StringVector.getStrings(name_string); 204 } 205 return systematic_gene_qualifier_names; 206 } 207 208 /** 209 * Return all possible gene names by combining the return values of 210 * getSystematicQualifierNames() and getDisplayQualifierNames() 211 **/ getAllGeneNames()212 public StringVector getAllGeneNames() 213 { 214 if(all_gene_qualifier_names == null) 215 { 216 all_gene_qualifier_names = getSystematicQualifierNames().copy(); 217 all_gene_qualifier_names.add(getDisplayQualifierNames()); 218 } 219 220 return all_gene_qualifier_names; 221 } 222 223 224 /** 225 * Read the options from the options file and uk.ac.sanger.artemis.ini 226 **/ readOptions()227 private void readOptions() 228 { 229 try 230 { 231 final InputStream options_input_stream = 232 Options.class.getResourceAsStream("/etc/options"); 233 234 if(options_input_stream == null) 235 return; 236 237 load(options_input_stream); 238 239 final boolean run_quietly = 240 getPropertyTruthValueInternal(System.getProperty("run_quietly")); 241 242 if(readWritePossible()) 243 { 244 final String user_home = System.getProperty("user.home"); 245 246 // properties are read in order from these files. 247 // the null is replaced by the file name given by the extra_options 248 // system property (if it is set) 249 final String [] standard_option_file_names = 250 { 251 "Diana.ini", 252 "options", 253 "options.txt", 254 "options.text", 255 user_home + File.separator + ".artemis_options" 256 }; 257 258 String [] option_file_names = standard_option_file_names; 259 260 final Properties system_properties = System.getProperties(); 261 262 if(system_properties != null) 263 { 264 final String extra_options_prop = 265 system_properties.getProperty("extra_options"); 266 267 if(extra_options_prop !=null) 268 { 269 final StringVector extra_option_file_names = 270 StringVector.getStrings(extra_options_prop, ":"); 271 272 option_file_names = 273 new String [option_file_names.length + 274 extra_option_file_names.size()]; 275 276 for(int i = 0 ; i < extra_option_file_names.size() ; ++i) 277 { 278 final String extra_option_file_name = 279 (String)extra_option_file_names.elementAt(i); 280 281 if(new File(extra_option_file_name).canRead()) 282 option_file_names[i] = extra_option_file_name; 283 else 284 { 285 System.err.println("warning: could not read options from \"" + 286 extra_option_file_name + "\""); 287 option_file_names[i] = null; 288 } 289 } 290 291 for(int i = 0 ; i < standard_option_file_names.length ; ++i) 292 option_file_names[i + extra_option_file_names.size()] = 293 standard_option_file_names[i]; 294 } 295 } 296 297 for(int i = 0 ; i < option_file_names.length ; ++i) 298 { 299 final String this_options_file = option_file_names[i]; 300 301 if(this_options_file == null) 302 continue; 303 304 final Document options_document = 305 new FileDocument(new File(this_options_file)); 306 307 // read the option files if they exist 308 if(options_document.readable()) 309 { 310 311 final InputStream options_document_stream = 312 options_document.getInputStream(); 313 314 /*if(!run_quietly) 315 System.err.println("reading options from \"" + 316 this_options_file + "\"");*/ 317 318 Splash.appendToLog(this_options_file+" options read"); 319 load(options_document_stream); 320 } 321 else 322 Splash.appendToLog(this_options_file+" not found"); 323 } 324 } 325 } 326 catch(IOException e) 327 { 328 System.err.println("could not read an options file : " + e); 329 } 330 331 for(Enumeration enumProp = propertyNames(); enumProp.hasMoreElements();) 332 { 333 final String property_name = (String)enumProp.nextElement(); 334 fireChangeEvent(property_name); 335 } 336 } 337 338 /** 339 * Reset this Options object by setting all the options to their default 340 * values and then call readOptions(). 341 **/ reset()342 public void reset() 343 { 344 clear(); 345 346 setDefaultFeatureColours(); 347 setDefaultColourMap(); 348 349 readOptions(); 350 setChadoOptions(); 351 352 readSystemOptions(); 353 resetCachedValues(); 354 355 ///// 356 // final Enumeration keys = propertyNames(); 357 // while (keys.hasMoreElements()) 358 // { 359 // final String key = (String)keys.nextElement(); 360 // final String value = getProperty(key); 361 // if(key.startsWith("colo")) 362 // System.out.println(key+" \t"+value); 363 // } 364 ///// 365 366 } 367 setChadoOptions()368 private void setChadoOptions() 369 { 370 final StringVector exon_models = getOptionValues("chado_exon_model"); 371 if(exon_models != null) 372 { 373 DatabaseDocument.EXONMODEL = (String)exon_models.elementAt(0); 374 if(getProperty("colour_of_" + DatabaseDocument.EXONMODEL) == null) 375 put("colour_of_" + DatabaseDocument.EXONMODEL, "7"); 376 } 377 378 final StringVector chado_transcript = getOptionValues("chado_transcript"); 379 if(chado_transcript != null) 380 { 381 DatabaseDocument.TRANSCRIPT = (String)chado_transcript.elementAt(0); 382 if(getProperty("colour_of_" + DatabaseDocument.TRANSCRIPT) == null) 383 put("colour_of_" + DatabaseDocument.TRANSCRIPT, "1"); 384 } 385 386 DatabaseDocument.CHADO_INFER_CDS = getPropertyTruthValue("chado_infer_CDS_UTR"); 387 if(DatabaseDocument.CHADO_INFER_CDS) 388 DatabaseDocument.EXONMODEL = "exon"; 389 } 390 391 /** 392 * Call load() from the super class and then reset the cached values for 393 * Font and Color objects. 394 **/ load(InputStream in_stream)395 public void load(InputStream in_stream) 396 throws IOException 397 { 398 super.load(in_stream); 399 400 resetCachedValues(); 401 } 402 403 /** 404 * Return the reference of the global Options object. 405 **/ getOptions()406 public static Options getOptions() 407 { 408 return options; 409 } 410 411 /** 412 * Return true if and only if we are running on a Unix machine. 413 **/ isUnixHost()414 public static boolean isUnixHost() 415 { 416 if(System.getProperty("artemis.environment") != null && 417 System.getProperty("artemis.environment").equals("UNIX")) 418 return true; 419 else 420 return false; 421 } 422 423 /** 424 * Return true if and only if Artemis is in "Noddy mode", meaning there 425 * will be lots of requesters asking for confirmation when delete/editing. 426 **/ isNoddyMode()427 public static boolean isNoddyMode() 428 { 429 return !isBlackBeltMode(); 430 } 431 432 /** 433 * Return true if and only if isNoddyMode() will return false. 434 **/ isBlackBeltMode()435 public static boolean isBlackBeltMode() 436 { 437 return getOptions().getPropertyTruthValue("black_belt_mode"); 438 } 439 440 /** 441 * Return true if and only if we are running in an applet. 442 **/ readWritePossible()443 public static boolean readWritePossible() 444 { 445 if(read_succeeded == null) 446 { 447 try 448 { 449 final File temp_file = File.createTempFile("dummy", "dummy"); 450 read_succeeded = new Boolean(true); 451 } 452 catch(Throwable t) 453 { 454 read_succeeded = new Boolean(false); 455 } 456 } 457 458 return read_succeeded.booleanValue(); 459 } 460 461 /** 462 * Return a StringVector containing the values of the given option or null 463 * if there is no such option. The values are separated by spaces in the 464 * properties file. 465 * 466 * @see #getPropertyValues() 467 **/ getOptionValues(final String option)468 public StringVector getOptionValues(final String option) 469 { 470 return getPropertyValues(this, option); 471 } 472 473 /** 474 * Return a StringVector containing the values of the given option in the 475 * given Properties object or null if there is no such option. The values 476 * are separated by spaces in the properties file. For example, asking for 477 * the property foo in a Properties object where foo has the value: "thing1 478 * thing2 thing3", will return a vector containing three String objects: 479 * "thing1", "thing2", "thing3" 480 **/ getPropertyValues(final Properties properties, final String option)481 public static StringVector getPropertyValues(final Properties properties, 482 final String option) 483 { 484 final String option_value = properties.getProperty(option); 485 486 if(option_value == null) 487 return null; 488 489 return StringVector.getStrings(option_value); 490 } 491 492 /** 493 * Return a QualifierInfoVector object containing one object for each 494 * qualifier given in extra_qualifiers option. 495 **/ getExtraQualifiers()496 public QualifierInfoVector getExtraQualifiers() 497 { 498 return getExtraQualifiers("extra_qualifiers"); 499 } 500 501 /** 502 * Return a QualifierInfoVector object containing one object for each 503 * qualifier given in extra_qualifiers option. 504 **/ getExtraGffQualifiers()505 public QualifierInfoVector getExtraGffQualifiers() 506 { 507 return getExtraQualifiers("extra_qualifiers_gff"); 508 } 509 510 /** 511 * Return a QualifierInfoVector object containing one object for each 512 * qualifier given in extra_qualifiers option. 513 **/ getExtraQualifiers(final String qualifier_options_flag)514 private QualifierInfoVector getExtraQualifiers(final String qualifier_options_flag) 515 { 516 final QualifierInfoVector return_vector = 517 new QualifierInfoVector(); 518 519 final StringVector extra_qualifiers_strings = 520 getOptionValues(qualifier_options_flag); 521 522 for(int i = 0 ; i < extra_qualifiers_strings.size() / 2 ; ++i) 523 { 524 final String name = (String)extra_qualifiers_strings.elementAt(i * 2); 525 final String type_string = 526 (String)extra_qualifiers_strings.elementAt(i * 2 + 1); 527 final int type = QualifierInfo.getQualifierTypeID(type_string); 528 529 return_vector.add(new QualifierInfo(name, type, null, null, false)); 530 } 531 532 return return_vector; 533 } 534 535 /** 536 * Return a Vector of the names of those qualifiers that shouldn't be shown 537 * by the QualifierChoice popup. 538 **/ getInvisibleQualifiers(boolean isGFF)539 public StringVector getInvisibleQualifiers(boolean isGFF) 540 { 541 if(invisible_qualifiers == null) 542 { 543 invisible_qualifiers = getOptionValues("invisible_qualifiers"); 544 545 if(isGFF) 546 invisible_qualifiers.add( getOptionValues("invisible_qualifiers_gff") ); 547 548 if(invisible_qualifiers == null) 549 invisible_qualifiers = new StringVector(); 550 } 551 552 return invisible_qualifiers; 553 } 554 555 /** 556 * Return the path of the default sequence file or null if there is no 557 * default. This will usually have been set in the uk.ac.sanger.artemis.ini file, 558 * eg. SEQUENCE_FILE='c5H10.seq' 559 **/ getDefaultSequenceFileName()560 public String getDefaultSequenceFileName() 561 { 562 final String property_string = getProperty("SEQUENCE_FILE"); 563 564 if(property_string == null) 565 return null; 566 else 567 { 568 if(property_string.length() == 0) 569 return null; 570 571 // trim the quotes from the name 572 if(property_string.startsWith("'") && 573 property_string.endsWith("'") && 574 property_string.length() > 2) 575 return property_string.substring(1, property_string.length() - 1); 576 else 577 return property_string; 578 } 579 } 580 581 /** 582 * Return the path of the default feature file or null if there is no 583 * default. This will usually have been set in the uk.ac.sanger.artemis.ini file, 584 * eg. FEATURE_FILE='c5H10_embl.tab' 585 **/ getDefaultFeatureFileName()586 public String getDefaultFeatureFileName() 587 { 588 final String property_string = getProperty("FEATURE_FILE"); 589 590 if(property_string == null) 591 return null; 592 else 593 { 594 if(property_string.length() == 0) 595 return null; 596 597 // trim the quotes from the name 598 if(property_string.startsWith("'") && 599 property_string.endsWith("'") && 600 property_string.length() > 2) 601 return property_string.substring(1, property_string.length() - 1); 602 else 603 return property_string; 604 } 605 } 606 607 /** 608 * Return the minimum open reading frame size used when automatically 609 * creating ORFs with the "Mark Open Reading Frames" function. 610 **/ getMinimumORFSize()611 public int getMinimumORFSize() 612 { 613 final Integer minimum_orf_size = getIntegerProperty("minimum_orf_size"); 614 615 if(minimum_orf_size == null) // default value 616 return 100; 617 else 618 return minimum_orf_size.intValue(); 619 } 620 621 /** 622 * Get the default colour for the given feature key, as specified in the 623 * options file. If no colour is specified in the file then null is 624 * returned. 625 * @param key The feature key to get the colour of. 626 **/ getDefaultFeatureColour(Key key)627 public Color getDefaultFeatureColour(Key key) 628 { 629 final Integer colour_integer = getIntegerProperty("colour_of_" + key); 630 631 if(colour_integer == null) 632 return null; 633 else 634 return getColorFromColourNumber(colour_integer.intValue()); 635 } 636 637 /** 638 * Given a colour number (perhaps from a /colour qualifier) return an 639 * appropriate Color object. 640 **/ getColorFromColourNumber(int colour_number)641 public Color getColorFromColourNumber(int colour_number) 642 { 643 // first look up colour_map for speed. if that fails we then try to look 644 // for an appropriate property and turn into a Color object. 645 if(colour_number < 0) 646 return null; 647 648 if(colour_number >= colour_map.size() || 649 colour_map.elementAt(colour_number) == null) 650 { 651 String col = getProperty("colour_" + colour_number); 652 if(col != null) 653 return parseColour(col); 654 655 // there is no colour for this colour_number 656 return null; 657 } 658 else 659 return colour_map.elementAt(colour_number); 660 } 661 662 /** 663 * Given a String containing three space separated integers (0-255), return 664 * a Color object. The three integers represent red, green and blue 665 * respectively. If a Color can't be parsed null is returned. 666 **/ parseColour(String colour_string)667 private Color parseColour(String colour_string) 668 { 669 try 670 { 671 // first get three integers from the String 672 673 // trim any whitespace from the ends 674 final StringVector value_strings = 675 StringVector.getStrings(colour_string.trim()); 676 677 final int first_int = 678 Integer.valueOf((String)value_strings.elementAt(0)).intValue(); 679 final int second_int = 680 Integer.valueOf((String)value_strings.elementAt(1)).intValue(); 681 final int third_int = 682 Integer.valueOf((String)value_strings.elementAt(2)).intValue(); 683 684 return new Color(first_int, second_int, third_int); 685 686 } 687 catch(NumberFormatException e) 688 { 689 return null; 690 } 691 } 692 693 /** 694 * Get the default Color for a colour 695 **/ setDefaultColourMap()696 public void setDefaultColourMap() 697 { 698 put("colour_0", "255 255 255"); // white 699 put("colour_1", "100 100 100"); // dark grey 700 put("colour_2", "255 0 0"); // red 701 put("colour_3", "0 255 0"); // green 702 put("colour_4", "0 0 255"); // blue 703 put("colour_5", "0 255 255"); // cyan 704 put("colour_6", "255 0 255"); // magenta 705 put("colour_7", "255 255 0"); // yellow 706 put("colour_8", "152 251 152"); // pale green 707 put("colour_9", "135 206 250"); // light sky blue 708 put("colour_10", "255 165 0"); // orange 709 put("colour_11", "200 150 100"); // brown 710 put("colour_12", "255 200 200"); // pink 711 } 712 713 /** 714 * Return a vector containing the ExternalProgram objects of all the 715 * external programs that we can use. 716 **/ getExternalPrograms()717 public ExternalProgramVector getExternalPrograms() 718 { 719 if(external_programs == null) 720 { 721 external_programs = new ExternalProgramVector(); 722 723 final StringVector protein_value_strings = 724 getOptionValues("feature_protein_programs"); 725 726 if(protein_value_strings != null) 727 { 728 for(int i = 0; i < protein_value_strings.size() / 2; ++i) 729 { 730 final String program_name = 731 (String)protein_value_strings.elementAt(i * 2); 732 final String program_options = 733 (String)protein_value_strings.elementAt(i * 2 + 1); 734 735 final ExternalProgram program = 736 new ExternalProgram(program_name, program_options, 737 ExternalProgram.AA_PROGRAM); 738 739 external_programs.add(program); 740 } 741 } 742 743 final StringVector dna_value_strings = 744 getOptionValues("feature_dna_programs"); 745 746 if(dna_value_strings != null) 747 { 748 for(int i = 0; i < dna_value_strings.size() / 2; ++i) 749 { 750 final String program_name = 751 (String)dna_value_strings.elementAt(i * 2); 752 final String program_options = 753 (String)dna_value_strings.elementAt(i * 2 + 1); 754 755 final ExternalProgram program = 756 new ExternalProgram(program_name, program_options, 757 ExternalProgram.DNA_PROGRAM); 758 759 external_programs.add(program); 760 } 761 } 762 763 final StringVector application_value_strings = 764 getOptionValues("application_programs"); 765 766 if(application_value_strings != null) 767 { 768 for(int i = 0; i < application_value_strings.size(); ++i) 769 { 770 final String program_name = (String)application_value_strings.elementAt(i); 771 772 final ExternalProgram program = 773 new ExternalProgram(program_name, null, 774 ExternalProgram.APPLICATION); 775 776 external_programs.add(program); 777 } 778 } 779 } 780 return external_programs; 781 } 782 783 784 785 /** 786 * Return a vector containing the ncbi ExternalProgram objects of all the 787 * external programs that we can use. 788 **/ getNCBIPrograms()789 public ExternalProgramVector getNCBIPrograms() 790 { 791 if(ncbi_programs == null) 792 { 793 ncbi_programs = new ExternalProgramVector(); 794 795 final StringVector protein_value_strings = 796 getOptionValues("ncbi_protein_search"); 797 798 if(protein_value_strings != null) 799 { 800 for(int i = 0; i < protein_value_strings.size() / 2; ++i) 801 { 802 final String program_name = 803 (String)protein_value_strings.elementAt(i * 2); 804 final String program_options = 805 (String)protein_value_strings.elementAt(i * 2 + 1); 806 807 final ExternalProgram program = 808 new ExternalProgram(program_name, program_options, 809 ExternalProgram.AA_PROGRAM); 810 811 ncbi_programs.add(program); 812 } 813 } 814 815 final StringVector dna_value_strings = 816 getOptionValues("ncbi_dna_search"); 817 818 if(dna_value_strings != null) 819 { 820 for(int i = 0; i < dna_value_strings.size() / 2; ++i) 821 { 822 final String program_name = 823 (String)dna_value_strings.elementAt(i * 2); 824 final String program_options = 825 (String)dna_value_strings.elementAt(i * 2 + 1); 826 827 final ExternalProgram program = 828 new ExternalProgram(program_name, program_options, 829 ExternalProgram.DNA_PROGRAM); 830 831 ncbi_programs.add(program); 832 } 833 } 834 } 835 return ncbi_programs; 836 } 837 838 /** 839 * Return a StringVector containing the bases of the possible start codons 840 * for prokaryotes. This is stored in the prokaryotic_start_codons option 841 * in the options file. 842 **/ 843 //public StringVector getProkaryoticStartCodons() 844 //{ 845 // final StringVector option_values = 846 // getOptionValues("prokaryotic_start_codons"); 847 848 // for(int i = 0; i<option_values.size() ; ++i) 849 // { 850 // final String new_value = option_values.elementAt(i).toLowerCase(); 851 // option_values.setElementAt(new_value, i); 852 // } 853 // return option_values; 854 //} 855 856 /** 857 * Return a StringVector containing the bases of the possible eukaryotic 858 * start codons. This is stored in the eukaryotic_start_codons option in 859 * the options file. 860 **/ 861 //public StringVector getEukaryoticStartCodons() 862 //{ 863 // final StringVector option_values = 864 // getOptionValues("eukaryotic_start_codons"); 865 866 // for(int i = 0; i<option_values.size() ; ++i) 867 // { 868 // final String new_value = option_values.elementAt(i).toLowerCase(); 869 // option_values.setElementAt(new_value, i); 870 // } 871 872 // return option_values; 873 //} 874 getStartCodons()875 public StringVector getStartCodons() 876 { 877 final StringVector option_values; 878 879 if(getProperty("start_codons") == null) 880 { 881 if(isEukaryoticMode()) 882 option_values = getOptionValues("eukaryotic_start_codons"); 883 else 884 option_values = getOptionValues("prokaryotic_start_codons"); 885 } 886 else 887 option_values = getOptionValues("start_codons"); 888 889 for(int i = 0; i<option_values.size() ; ++i) 890 { 891 final String new_value = ((String)option_values.elementAt(i)).toLowerCase(); 892 option_values.setElementAt(new_value, i); 893 } 894 895 return option_values; 896 } 897 898 /** 899 * Return the default font that should be used for all windows. 900 **/ getFont()901 public Font getFont() 902 { 903 return font; 904 } 905 906 /** 907 * Return the UIResource for the default font that should be used for all 908 * windows. 909 **/ getFontUIResource()910 public javax.swing.plaf.FontUIResource getFontUIResource() 911 { 912 return new javax.swing.plaf.FontUIResource(getFont()); 913 } 914 915 /** 916 * Adds the specified event listener to receive option change events from 917 * this object. 918 * @param l the event change listener. 919 **/ addOptionChangeListener(OptionChangeListener l)920 public void addOptionChangeListener(OptionChangeListener l) 921 { 922 option_listener_hash.put(l, this); 923 } 924 925 /** 926 * Removes the specified event listener so that it no longer receives 927 * option change events from this object. 928 * @param l the event change listener. 929 **/ removeOptionChangeListener(OptionChangeListener l)930 public void removeOptionChangeListener(OptionChangeListener l) 931 { 932 option_listener_hash.remove(l); 933 } 934 935 /** 936 * Read all the system properties and overwrite this Options object with 937 * those values. 938 **/ readSystemOptions()939 private void readSystemOptions() 940 { 941 if(readWritePossible()) 942 { 943 final Properties system_properties = System.getProperties(); 944 if(system_properties != null) 945 { 946 final Enumeration enumeration = system_properties.keys(); 947 while(enumeration.hasMoreElements()) 948 { 949 final String key = (String)enumeration.nextElement(); 950 final String value = system_properties.getProperty(key); 951 put(key, value); 952 } 953 } 954 } 955 } 956 957 /** 958 * Set the default colour number for each a feature key. 959 **/ setDefaultFeatureColours()960 private void setDefaultFeatureColours() 961 { 962 final Object[] key_colour_map = 963 { 964 "CDS", "5", 965 "cds?", "7", 966 "BLASTCDS", "2", 967 "BLASTN_HIT", "6", 968 "source", "0", 969 "prim_tran", "0", 970 "stem_loop", "2", 971 "misc_feature", "3", 972 "delta", "3", 973 "repeat_region", "9", 974 "repeat_unit", "9", 975 "terminator", "3", 976 "promoter", "3", 977 "intron", "1", 978 "exon", "7", 979 DatabaseDocument.EXONMODEL, "7", 980 "mRNA", "1", 981 "tRNA", "8", 982 "TATA", "3", 983 "bldA", "2" 984 }; 985 986 for(int i = 0 ; i < key_colour_map.length / 2 ; ++i) 987 put("colour_of_" + key_colour_map[i*2], key_colour_map[i*2+1]); 988 } 989 990 /** 991 * Clear all cached values (such as the font) and then recalculate. 992 **/ resetCachedValues()993 private void resetCachedValues() 994 { 995 /*final*/ int font_size; 996 997 try 998 { 999 final Integer font_size_integer = getIntegerProperty("font_size"); 1000 1001 if(font_size_integer == null) 1002 font_size = 12; 1003 else 1004 font_size = font_size_integer.intValue(); 1005 } 1006 catch(NumberFormatException e) 1007 { 1008 System.err.println("error in options file - " + 1009 "font_size should be an integer"); 1010 // a default value 1011 font_size = 14; 1012 put("font_size", String.valueOf(font_size)); 1013 } 1014 1015 if(getProperty("font_name") == null) 1016 put("font_name", "Monospaced"); 1017 1018 font = new Font(getProperty("font_name"), Font.PLAIN, font_size); 1019 1020 colour_map = new Vector<Color>(25); 1021 1022 int colour_number = 0; 1023 1024 while(true) 1025 { 1026 final String colour_value_string = 1027 getProperty("colour_" + colour_number); 1028 1029 if(colour_value_string == null) 1030 // we know nothing about this colour number so we assume that there 1031 // aren't any more 1032 break; 1033 else 1034 { 1035 final Color new_colour = parseColour(colour_value_string); 1036 1037 if(new_colour == null) 1038 { 1039 // we couldn't parse the colour 1040 System.err.println("error in options file could not understand " + 1041 "this number: " + colour_value_string); 1042 } 1043 else 1044 { 1045 if(colour_number >= colour_map.size()) 1046 colour_map.setSize(colour_number + 50); 1047 colour_map.setElementAt(new_colour, colour_number); 1048 } 1049 } 1050 ++colour_number; 1051 } 1052 1053 invisible_qualifiers = null; 1054 1055 display_gene_qualifier_names = null; 1056 systematic_gene_qualifier_names = null; 1057 all_gene_qualifier_names = null; 1058 } 1059 1060 /** 1061 * Return the value of a property/option as an Integer. If the property 1062 * does not exist or cannot be parsed as an Integer, the method returns 1063 * null. 1064 **/ getIntegerProperty(String property_name)1065 public Integer getIntegerProperty(String property_name) 1066 { 1067 final String property_string = getProperty(property_name); 1068 1069 if(property_string == null) 1070 return null; 1071 else 1072 return Integer.valueOf(property_string); 1073 } 1074 1075 /** 1076 * Return the number of levels of undo to save or 0 if undo is disabled. 1077 **/ getUndoLevels()1078 public int getUndoLevels() 1079 { 1080 final Integer undo_integer = getIntegerProperty("undo_levels"); 1081 if(undo_integer == null) 1082 return 0; 1083 else 1084 { 1085 if(undo_integer.intValue() < 0) 1086 return 0; 1087 else 1088 return undo_integer.intValue(); 1089 } 1090 } 1091 1092 /** 1093 * Enable direct editing if and only if the argument is true. "Direct 1094 * Editing" allows feature locations to be changed by dragging the ends of 1095 * the features around with the mouse. 1096 **/ setDirectEdit(final boolean direct_edit)1097 public void setDirectEdit(final boolean direct_edit) 1098 { 1099 if(direct_edit) 1100 { 1101 if(!canDirectEdit()) 1102 { 1103 put(direct_edit_string, "true"); 1104 fireChangeEvent(direct_edit_string); 1105 } 1106 } 1107 else 1108 { 1109 if(canDirectEdit()) 1110 { 1111 put(direct_edit_string, "false"); 1112 fireChangeEvent(direct_edit_string); 1113 } 1114 } 1115 } 1116 1117 /** 1118 * Returns true if and only if direct editing is enabled. 1119 **/ canDirectEdit()1120 public boolean canDirectEdit() 1121 { 1122 if(getPropertyTruthValue(direct_edit_string)) 1123 return true; 1124 else 1125 return false; 1126 } 1127 setGeneticCode(String table)1128 public void setGeneticCode(String table) 1129 { 1130 put("translation_table",table); 1131 fireChangeEvent("translation_table"); 1132 } 1133 setDisplayNameQualifiers(final String display_name_qualifiers)1134 public void setDisplayNameQualifiers(final String display_name_qualifiers) 1135 { 1136 display_gene_qualifier_names = null; 1137 put("display_name_qualifiers", display_name_qualifiers); 1138 fireChangeEvent("display_name_qualifiers"); 1139 } 1140 1141 /** 1142 * Names of qualifiers to search when attempting to find the systematic 1143 * name of a gene. 1144 **/ setSystematicQualifierNames(final String systematic_name_qualifiers)1145 public void setSystematicQualifierNames(final String systematic_name_qualifiers) 1146 { 1147 systematic_gene_qualifier_names = null; 1148 put("systematic_name_qualifiers", systematic_name_qualifiers); 1149 fireChangeEvent("systematic_name_qualifiers"); 1150 } 1151 1152 /** 1153 * Set the organism type to eukaryotic if and only if the argument is 1154 * true. The other alternative is prokaryotic. 1155 **/ setEukaryoticMode(final boolean eukaryotic_mode)1156 public void setEukaryoticMode(final boolean eukaryotic_mode) 1157 { 1158 if(eukaryotic_mode) 1159 { 1160 if(!isEukaryoticMode()) 1161 { 1162 put(eukaryotic_mode_string, "eukaryotic"); 1163 fireChangeEvent(eukaryotic_mode_string); 1164 } 1165 } 1166 else 1167 { 1168 if(isEukaryoticMode()) 1169 { 1170 put(eukaryotic_mode_string, "prokaryotic"); 1171 fireChangeEvent(eukaryotic_mode_string); 1172 } 1173 } 1174 } 1175 1176 /** 1177 * Returns true if and only if we should be using the eukaryotic settings. 1178 * This is only the default. 1179 **/ isEukaryoticMode()1180 public boolean isEukaryoticMode() 1181 { 1182 final String organism_type_prop = getProperty("organism_type"); 1183 1184 if(organism_type_prop == null || 1185 organism_type_prop.equals("eukaryotic") || 1186 organism_type_prop.equals("eukaryote") || 1187 organism_type_prop.equals("euk")) 1188 return true; 1189 else 1190 return false; 1191 } 1192 1193 /** 1194 * Set whether or not to highlight the active entry. 1195 **/ setHighlightActiveEntryFlag(final boolean highlight_active)1196 public void setHighlightActiveEntryFlag(final boolean highlight_active) 1197 { 1198 if(highlight_active) 1199 { 1200 if(!highlightActiveEntryFlag()) 1201 { 1202 put(highlight_active_entry_string, "true"); 1203 fireChangeEvent(highlight_active_entry_string); 1204 } 1205 } 1206 else 1207 { 1208 if(highlightActiveEntryFlag()) 1209 { 1210 put(highlight_active_entry_string, "false"); 1211 fireChangeEvent(highlight_active_entry_string); 1212 } 1213 } 1214 } 1215 1216 /** 1217 * Returns true if and only if we should highlight the active entry in the 1218 * display. 1219 **/ highlightActiveEntryFlag()1220 public boolean highlightActiveEntryFlag() 1221 { 1222 if(getPropertyTruthValue(highlight_active_entry_string)) 1223 return true; 1224 else 1225 return false; 1226 } 1227 1228 /** 1229 * Returns true if this version of Java is running on a GNU/Linux machine 1230 * and is version 1.2.0 or later. 1231 **/ isBuggyLinuxVM()1232 public boolean isBuggyLinuxVM() 1233 { 1234 if(!readWritePossible()) 1235 // Java in a browser has problems, but not this problem 1236 return false; 1237 1238 final String os_name = (String) System.getProperties().get("os.name"); 1239 1240 if(os_name.equals("Linux")) 1241 { 1242 final String java_version = 1243 (String) System.getProperties().get("java.version"); 1244 1245 if(java_version.startsWith("1.1.")) 1246 return false; 1247 else 1248 return true; 1249 } 1250 else 1251 return false; 1252 } 1253 1254 1255 /** 1256 * Return the EntryInformation object to use for EMBL and GENBANK entries. 1257 **/ getDBEntryInformation()1258 public static EntryInformation getDBEntryInformation() 1259 { 1260 return db_entry_information; 1261 } 1262 1263 /** 1264 * The EntryInformation object that has all the information that 1265 * getDBEntryInformation () would return, but which has the non-standard 1266 * qualifiers and keys added. 1267 **/ getArtemisEntryInformation()1268 public static EntryInformation getArtemisEntryInformation() 1269 { 1270 return extended_entry_information; 1271 } 1272 1273 /** 1274 * Return an EntryInformation object that is suitable for EMBL and GENBANK 1275 * entries. 1276 **/ makeEntryInformation()1277 private static EntryInformation makeEntryInformation() 1278 throws IOException, QualifierInfoException 1279 { 1280 final InputStream feature_keys_stream = 1281 Options.class.getResourceAsStream("/etc/feature_keys"); 1282 1283 final InputStream qualifier_types_stream = 1284 Options.class.getResourceAsStream("/etc/qualifier_types"); 1285 1286 QualifierInfoVector qualifier_info_vector = 1287 readQualifierInfo(qualifier_types_stream, feature_keys_stream); 1288 1289 final EntryInformation entry_information = new SimpleEntryInformation(); 1290 1291 for(int i = 0 ; i < qualifier_info_vector.size() ; ++i) 1292 { 1293 final QualifierInfo qualifier_info = 1294 qualifier_info_vector.elementAt(i); 1295 1296 entry_information.addQualifierInfo(qualifier_info); 1297 } 1298 1299 entry_information.setEMBLFormat(true); 1300 1301 return entry_information; 1302 } 1303 1304 /** 1305 * Return an EntryInformation object that is suitable for EMBL and GENBANK 1306 * entries, and has some useful non-standard additions (specified by the 1307 * options file). 1308 **/ 1309 private static EntryInformation makeArtemisEntryInformation(final EntryInformation standard_entry_info)1310 makeArtemisEntryInformation(final EntryInformation standard_entry_info) 1311 throws QualifierInfoException 1312 { 1313 1314 final StringVector extra_keys = 1315 getOptions().getOptionValues("extra_keys"); 1316 1317 final QualifierInfoVector extra_qualifiers = 1318 getOptions().getExtraQualifiers(); 1319 1320 final EntryInformation return_entry_information = 1321 new SimpleEntryInformation(standard_entry_info); 1322 1323 for(int i = 0 ; i < extra_keys.size() ; ++i) 1324 { 1325 final Key new_key = new Key((String)extra_keys.elementAt(i)); 1326 return_entry_information.addKey(new_key); 1327 } 1328 1329 for(int i = 0 ; i < extra_qualifiers.size() ; ++i) 1330 { 1331 final QualifierInfo new_qualifier_info = extra_qualifiers.elementAt(i); 1332 return_entry_information.addQualifierInfo(new_qualifier_info); 1333 } 1334 1335 // make a add qualifier info for each search program. eg. add blastp_file 1336 // for blastp 1337 final ExternalProgramVector external_programs = 1338 getOptions().getExternalPrograms(); 1339 1340 for(int i = 0 ; i < external_programs.size() ; ++i) 1341 { 1342 final ExternalProgram external_program = external_programs.elementAt(i); 1343 1344 if(external_program.getType() == ExternalProgram.AA_PROGRAM || 1345 external_program.getType() == ExternalProgram.DNA_PROGRAM) 1346 { 1347 final QualifierInfo new_qualifier_info = 1348 new QualifierInfo(external_program.getName() + "_file", 1349 QualifierInfo.QUOTED_TEXT, 1350 null, 1351 null, 1352 true); 1353 1354 return_entry_information.addQualifierInfo(new_qualifier_info); 1355 } 1356 } 1357 1358 return_entry_information.setEMBLFormat(false); 1359 1360 return return_entry_information; 1361 } 1362 1363 /** 1364 * Read the possible feature key and qualifier names and types from the two 1365 * given streams (see etc/feature_keys and etc/qualifier_types for details 1366 * on the formats). 1367 **/ 1368 private static QualifierInfoVector readQualifierInfo(final InputStream qualifier_types_stream, final InputStream feature_keys_stream)1369 readQualifierInfo(final InputStream qualifier_types_stream, 1370 final InputStream feature_keys_stream) 1371 throws IOException 1372 { 1373 1374 final QualifierInfoVector return_vector = new QualifierInfoVector(); 1375 1376 Properties feature_properties = new Properties(); 1377 final Properties qualifier_properties = new Properties(); 1378 1379 feature_properties.load(feature_keys_stream); 1380 qualifier_properties.load(qualifier_types_stream); 1381 1382 // parse the feature_properties 1383 1384 { 1385 final Properties new_feature_properties = new Properties(); 1386 1387 final Enumeration feature_enum = feature_properties.propertyNames(); 1388 1389 while(feature_enum.hasMoreElements()) { 1390 String current_feature_name = (String) feature_enum.nextElement(); 1391 1392 final StringVector property_values = 1393 Options.getPropertyValues(feature_properties, current_feature_name); 1394 1395 new_feature_properties.put(current_feature_name, property_values); 1396 } 1397 1398 feature_properties = new_feature_properties; 1399 } 1400 1401 final Enumeration qualifier_enum = qualifier_properties.propertyNames(); 1402 1403 while(qualifier_enum.hasMoreElements()) 1404 { 1405 String current_qualifier_name = (String) qualifier_enum.nextElement(); 1406 1407 final StringVector current_qualifier_values = 1408 Options.getPropertyValues(qualifier_properties, 1409 current_qualifier_name); 1410 1411 final boolean once_only = 1412 current_qualifier_values.elementAt(0).equals("yes"); 1413 1414 final String type_string = (String)current_qualifier_values.elementAt(1); 1415 1416 // find the keys for which this qualifier name is valid or required 1417 1418 final KeyVector valid_keys = new KeyVector(); 1419 final KeyVector required_keys = new KeyVector(); 1420 1421 final Enumeration features_enum = feature_properties.propertyNames(); 1422 1423 while(features_enum.hasMoreElements()) 1424 { 1425 final String current_key_string = (String)features_enum.nextElement(); 1426 1427 final Key current_key = new Key(current_key_string); 1428 1429 final StringVector current_feature_qualifiers = 1430 (StringVector) feature_properties.get(current_key_string); 1431 1432 if(current_feature_qualifiers.contains(current_qualifier_name)) 1433 valid_keys.add(current_key); 1434 else 1435 if(current_feature_qualifiers.contains("@" + 1436 current_qualifier_name)) 1437 { 1438 valid_keys.add(current_key); 1439 required_keys.add(current_key); 1440 } 1441 } 1442 1443 final int type = QualifierInfo.getQualifierTypeID(type_string); 1444 1445 final QualifierInfo qualifier_info = 1446 new QualifierInfo(current_qualifier_name, type, valid_keys, 1447 required_keys, once_only); 1448 1449 return_vector.add(qualifier_info); 1450 } 1451 1452 return return_vector; 1453 } 1454 1455 /** 1456 * Send a change event to all the listeners. 1457 * @param option_name The name of the option that changed. 1458 **/ fireChangeEvent(final String option_name)1459 private void fireChangeEvent(final String option_name) 1460 { 1461 for(final Enumeration e = option_listener_hash.keys() ; 1462 e.hasMoreElements() ;) 1463 { 1464 final OptionChangeEvent event = 1465 new OptionChangeEvent(this, option_name); 1466 1467 final OptionChangeListener target = 1468 (OptionChangeListener) e.nextElement(); 1469 1470 target.optionChanged(event); 1471 } 1472 } 1473 1474 static 1475 { 1476 try 1477 { 1478 db_entry_information = makeEntryInformation(); 1479 extended_entry_information = 1480 makeArtemisEntryInformation(db_entry_information); 1481 } 1482 catch(QualifierInfoException e) 1483 { 1484 System.err.println("could not initialise the embl package: " + 1485 e.getMessage()); 1486 System.exit(1); 1487 } 1488 catch(IOException e) 1489 { 1490 System.err.println("could not initialise the embl package: " + 1491 e.getMessage()); 1492 System.exit(1); 1493 } 1494 } 1495 1496 } 1497