001 /** 002 * Do we want to use this space for anything? Eg, revision history? 003 */ 004 package edu.nrao.sss.model.proposal; 005 006 import java.util.ArrayList; 007 import java.util.Date; 008 import java.util.EnumSet; 009 import java.util.List; 010 import java.util.HashSet; 011 import java.util.Set; 012 013 import edu.nrao.sss.model.UserAccountable; 014 import edu.nrao.sss.model.project.Project; 015 import edu.nrao.sss.model.resource.Resource; 016 import edu.nrao.sss.model.resource.TelescopeType; 017 import edu.nrao.sss.model.source.Source; 018 import edu.nrao.sss.util.Identifiable; 019 import edu.nrao.sss.util.XmlSerializable; 020 021 //TODO Method comments! 022 023 /** <i>Placeholder for time when we integrate proposal work.</i> 024 * A request for time to perform one or more projects on one or 025 * more telescopes. 026 * 027 * @version 1.1 028 * @since 2006-02-24 029 */ 030 public class Proposal 031 implements Identifiable, XmlSerializable, UserAccountable 032 { 033 private static final String NO_LEGACY_ID = "None"; 034 private static final String NO_PROPOSAL_CODE = "None"; 035 private static final String NO_OTHER_TYPE = ""; 036 private static final String NO_ABSTRACT = ""; 037 private static final String NO_TITLE = "[Title Goes Here]"; 038 039 //IDENTIFICATION & STATUS 040 private Long id; //A unique identifier for the persistence layer. 041 private String legacyId; //TODO What is this? 042 private String proposalCode; //This proposal's identifier; a problem-domain concept. 043 private Set<String> previousCodes; //Other codes this proposal has had (from submit-w/d-resubmit) 044 private String title; 045 private ProposalType proposalType; 046 private ProposalStatus status; 047 048 //OTHER PROPOSALS 049 private Set<String> previousProposals; //Other proposals by PI? 050 private Set<String> relatedProposals; 051 052 //USER TRACKING 053 private Long createdBy; //This is a user ID 054 private Date createdOn; 055 private Long lastUpdatedBy; //This is a user ID 056 private Date lastUpdatedOn; 057 private Date submittedOn; 058 059 //PEOPLE 060 private Long editor; //This is a user ID 061 private Long contactPerson; //This is a user ID 062 private Long principalInvestigator; //This is a user ID 063 064 private List<Author> authors; 065 066 //SCIENCE 067 private String abstractText; 068 private Set<TelescopeType> telescopes; 069 private Set<ObservingType> observingTypes; 070 private String observingTypeOther; 071 private ScientificType scientificCategory; 072 private String scientificCategoryOther; 073 074 private Set<Session> sessions; 075 private Set<Source> sources; 076 private Set<Resource> resources; 077 078 private JustificationFileDescriptor justificationFile; 079 080 //OTHER ATTRIBUTES 081 private boolean observerToBePresent; 082 private SupportType staffSupport; 083 private StudentSupport studentSupport; 084 085 /** Creates a new instance. */ 086 public Proposal() 087 { 088 previousCodes = new HashSet<String>(); 089 previousProposals = new HashSet<String>(); 090 relatedProposals = new HashSet<String>(); 091 092 authors = new ArrayList<Author>(); 093 telescopes = EnumSet.noneOf(TelescopeType.class); 094 observingTypes = EnumSet.noneOf(ObservingType.class); 095 096 sessions = new HashSet<Session>(); 097 sources = new HashSet<Source>(); 098 resources = new HashSet<Resource>(); 099 100 justificationFile = new JustificationFileDescriptor(); 101 102 studentSupport = new StudentSupport(); 103 104 initialize(); 105 } 106 107 /** Initializes the instance variables of this class. */ 108 private void initialize() 109 { 110 //IDENTIFICATION & STATUS 111 id = Identifiable.UNIDENTIFIED; 112 legacyId = NO_LEGACY_ID; 113 proposalCode = NO_PROPOSAL_CODE; 114 title = NO_TITLE; 115 proposalType = ProposalType.UNKNOWN; 116 status = ProposalStatus.DRAFT; 117 118 //USER TRACKING 119 createdBy = UserAccountable.NULL_USER_ID; 120 createdOn = new Date(); 121 lastUpdatedBy = UserAccountable.NULL_USER_ID; 122 lastUpdatedOn = new Date(); 123 submittedOn = new Date(); 124 125 //PEOPLE 126 editor = Identifiable.UNIDENTIFIED; 127 contactPerson = Identifiable.UNIDENTIFIED; 128 principalInvestigator = Identifiable.UNIDENTIFIED; 129 130 //SCIENCE 131 abstractText = NO_ABSTRACT; 132 observingTypeOther = NO_OTHER_TYPE; 133 scientificCategory = ScientificType.UNKNOWN; 134 scientificCategoryOther = NO_OTHER_TYPE; 135 136 //OTHER ATTRIBUTES 137 observerToBePresent = false; 138 staffSupport = SupportType.UNKNOWN; 139 } 140 141 /** 142 * Resets this proposal to its initial state. A reset proposal has the same 143 * state as a new proposal. 144 */ 145 // public void reset() 146 // { 147 // initialize(); 148 // 149 // previousCodes.clear(); 150 // previousProposals.clear(); 151 // relatedProposals.clear(); 152 // 153 // authors.clear(); 154 // telescopes.clear(); 155 // observingTypes.clear(); 156 // 157 // sessions.clear() or some other way? 158 // sources.clear(); 159 // resources.clear(); 160 // 161 // justificationFile.reset(); 162 // studentSupport.reset(); 163 // } 164 165 //============================================================================ 166 // IDENTIFICATION & STATUS 167 //============================================================================ 168 169 /* (non-Javadoc) 170 * @see edu.nrao.sss.model.util.Identifiable#getId() 171 */ 172 public Long getId() 173 { 174 return id; 175 } 176 177 @SuppressWarnings("unused") 178 private void setId(Long id) 179 { 180 this.id = id; 181 } 182 183 /** 184 * @return XXX What is a legacy id? 185 */ 186 public String getLegacyId() 187 { 188 return legacyId; 189 } 190 191 /** 192 * @see #getLegacyId 193 */ 194 public void setLegacyId( String id ) 195 { 196 legacyId = id; 197 } 198 199 /** 200 * @return The comittee assigned id for this proposal. 201 */ 202 public String getProposalCode() 203 { 204 return proposalCode; 205 } 206 207 //TODO Should there BE a public setProposalCode? 208 public void setProposalCode(String newCode) 209 { 210 proposalCode = (newCode == null) ? NO_PROPOSAL_CODE : newCode; 211 } 212 213 public String getTitle() 214 { 215 return title; 216 } 217 218 public void setTitle(String title) 219 { 220 this.title = title; 221 } 222 223 public ProposalType getProposalType() 224 { 225 return proposalType; 226 } 227 228 public void setProposalType(ProposalType proposalType) 229 { 230 this.proposalType = (proposalType == null) ? ProposalType.UNKNOWN 231 : proposalType; 232 } 233 234 public ProposalStatus getStatus() 235 { 236 return status; 237 } 238 239 public void setStatus(ProposalStatus newStatus) 240 { 241 status = (newStatus == null) ? ProposalStatus.UNKNOWN : newStatus; 242 } 243 244 //============================================================================ 245 // OTHER PROPOSALS 246 //============================================================================ 247 248 public Set<String> getPreviousCodes() 249 { 250 return previousCodes; 251 } 252 253 public void setPreviousCodes(Set<String> newSetOfCodes) 254 { 255 //TODO null check 256 previousCodes = newSetOfCodes; 257 } 258 259 public Set<String> getPreviousProposals() 260 { 261 return previousProposals; 262 } 263 264 public void setPreviousProposals(Set<String> prevProposals) 265 { 266 //TODO null check 267 previousProposals = prevProposals; 268 } 269 270 public Set<String> getRelatedProposals() 271 { 272 return relatedProposals; 273 } 274 275 public void setRelatedProposals(Set<String> rProposals) 276 { 277 //TODO null check 278 relatedProposals = rProposals; 279 } 280 281 //============================================================================ 282 // INTERFACE UserAccountable 283 //============================================================================ 284 285 public void setCreatedBy(Long userId) 286 { 287 createdBy = (userId == null) ? UserAccountable.NULL_USER_ID : userId; 288 } 289 290 public void setCreatedOn(Date d) 291 { 292 if (d != null) 293 createdOn = d; 294 } 295 296 public void setLastUpdatedBy(Long userId) 297 { 298 lastUpdatedBy = (userId == null) ? UserAccountable.NULL_USER_ID : userId; 299 } 300 301 public void setLastUpdatedOn(Date d) 302 { 303 if (d != null) 304 lastUpdatedOn = d; 305 } 306 307 public Long getCreatedBy() { return createdBy; } 308 public Date getCreatedOn() { return createdOn; } 309 public Long getLastUpdatedBy() { return lastUpdatedBy; } 310 public Date getLastUpdatedOn() { return lastUpdatedOn; } 311 312 public Date getSubmittedOn() 313 { 314 return submittedOn; 315 } 316 317 public void setSubmittedOn(Date submit) 318 { 319 if (submit != null) 320 submittedOn = submit; 321 } 322 323 //============================================================================ 324 // PEOPLE 325 //============================================================================ 326 327 public Long getEditor() 328 { 329 return editor; 330 } 331 332 public void setEditor(Long editorId) 333 { 334 editor = (editorId == null) ? Identifiable.UNIDENTIFIED 335 : editorId; 336 } 337 338 public Long getContactPerson() 339 { 340 return contactPerson; 341 } 342 343 public void setContactPerson(Long contactPersonId) 344 { 345 contactPerson = (contactPersonId == null) ? Identifiable.UNIDENTIFIED 346 : contactPersonId; 347 } 348 349 public Long getPrincipalInvestigator( ) 350 { 351 return principalInvestigator; 352 } 353 354 public void setPrincipalInvestigator(Long principalInvestigatorId) 355 { 356 principalInvestigator = 357 (principalInvestigatorId == null) ? Identifiable.UNIDENTIFIED 358 : principalInvestigatorId; 359 } 360 361 public List<Author> getAuthors() 362 { 363 return authors; 364 } 365 366 @SuppressWarnings("unused") 367 private void setAuthors(List<Author> authorList) 368 { 369 if (authorList != null) 370 authors = authorList; 371 else 372 authors.clear(); 373 //TODO As above, or: 374 // authors.clear(); 375 // if (authorList != null) 376 // authors.addAll(authorList); 377 } 378 379 public void addAuthor(Author newAuthor) 380 { 381 if (newAuthor != null) 382 authors.add(newAuthor); 383 } 384 385 public void removeAuthor(Author oldAuthor) 386 { 387 if (oldAuthor != null) 388 authors.remove(oldAuthor); 389 } 390 391 //============================================================================ 392 // SCIENCE 393 //============================================================================ 394 395 public void addTelescope(TelescopeType newTelescope) 396 { 397 if (newTelescope != null) 398 telescopes.add(newTelescope); 399 } 400 401 public void removeTelescope(TelescopeType oldTelescope) 402 { 403 if (oldTelescope != null) 404 telescopes.remove(oldTelescope); 405 } 406 407 public Set<TelescopeType> getTelescopes() 408 { 409 return telescopes; 410 } 411 412 @SuppressWarnings("unused") 413 private void setTelescopes(Set<TelescopeType> telescopes) 414 { 415 if (telescopes != null) 416 this.telescopes = telescopes; 417 else 418 this.telescopes.clear(); 419 } 420 421 public Set<ObservingType> getObservingTypes() 422 { 423 return observingTypes; 424 } 425 426 public void setObservingTypes(Set<ObservingType> observingTypes) 427 { 428 if (observingTypes != null) 429 this.observingTypes = observingTypes; 430 else 431 this.observingTypes.clear(); 432 //TODO As above, or: 433 // this.observingTypes.clear(); 434 // if (observingTypes != null) 435 // this.observingTypes.addAll(authorList); 436 } 437 438 public String getObservingTypeOther() 439 { 440 return observingTypeOther; 441 } 442 443 public void setObservingTypeOther( String other ) 444 { 445 observingTypeOther = (other == null) ? "" : other; 446 } 447 448 public ScientificType getScientificCategory() 449 { 450 return scientificCategory; 451 } 452 453 public void setScientificCategory(ScientificType scienceCategory) 454 { 455 scientificCategory = (scienceCategory == null) ? ScientificType.UNKNOWN 456 : scienceCategory; 457 } 458 459 public String getScientificCategoryOther() 460 { 461 return scientificCategoryOther; 462 } 463 464 public void setScientificCategoryOther( String s ) 465 { 466 scientificCategoryOther = (s == null) ? "" : s; 467 } 468 469 /** 470 * @return the abstract 471 */ 472 public String getAbstract() 473 { 474 return abstractText; 475 } 476 477 public void setAbstract(String newAbstract) 478 { 479 abstractText = (newAbstract == null) ? NO_ABSTRACT : newAbstract; 480 } 481 482 public JustificationFileDescriptor getJustificationFile() 483 { 484 return justificationFile; 485 } 486 487 public void setJustificationFile(JustificationFileDescriptor newDescriptor) 488 { 489 //TODO null check 490 justificationFile = newDescriptor; 491 } 492 493 @SuppressWarnings("unused") 494 private void setSessions(Set<Session> ss ) 495 { 496 sessions = ss; 497 } 498 499 public Set<Session> getSessions() 500 { 501 return sessions; 502 } 503 504 public void addSession( Session s ) 505 { 506 if (sessions == null) 507 sessions = new HashSet<Session>(); 508 509 sessions.add(s); 510 } 511 512 public void deleteSession( Session s ) 513 { 514 sessions.remove(s); 515 } 516 517 @SuppressWarnings("unused") 518 private void setSources(Set<Source> ss ) 519 { 520 sources = ss; 521 } 522 523 public Set<Source> getSources() 524 { 525 return sources; 526 } 527 528 /** 529 * Returns a set that contains one copy of each of the sources in this 530 * proposal. 531 * 532 * @return a set of sources cloned from this proposal's set of sources. 533 */ 534 public Set<Source> getSourceClones() 535 { 536 Set<Source> clones = new HashSet<Source>(); 537 538 for (Source s : getSources()) 539 clones.add((Source)s.clone()); 540 541 return clones; 542 } 543 544 public void addSource( Source s ) 545 { 546 if (sources == null) 547 sources = new HashSet<Source>(); 548 549 sources.add(s); 550 } 551 552 public void deleteSource( Source s ) 553 { 554 sources.remove(s); 555 } 556 557 @SuppressWarnings("unused") 558 private void setResources(Set<Resource> ss ) 559 { 560 resources = ss; 561 } 562 563 public Set<Resource> getResources() 564 { 565 return resources; 566 } 567 568 public void addResource( Resource s ) 569 { 570 if (resources == null) 571 resources = new HashSet<Resource>(); 572 573 resources.add(s); 574 } 575 576 public void deleteResource( Resource s ) 577 { 578 resources.remove(s); 579 } 580 581 //============================================================================ 582 // OTHER ATTRIBUTES 583 //============================================================================ 584 585 public boolean isObserverToBePresent() 586 { 587 return observerToBePresent; 588 } 589 590 public void setObserverToBePresent(boolean toBePresent) 591 { 592 observerToBePresent = toBePresent; 593 } 594 595 public SupportType getStaffSupport() 596 { 597 return staffSupport; 598 } 599 600 public void setStaffSupport(SupportType sSupport) 601 { 602 staffSupport = (sSupport == null) ? SupportType.UNKNOWN : sSupport; 603 } 604 605 public StudentSupport getStudentSupport() 606 { 607 return studentSupport; 608 } 609 610 public void setStudentSupport( StudentSupport ss ) 611 { 612 //TODO How handle ss==null ? 613 studentSupport = ss; 614 } 615 616 //============================================================================ 617 // 618 //============================================================================ 619 620 //TODO: Move this method to an existing or new class in the project package. 621 // This method is the only link from the proposal pkg to the project pkg. 622 // If we remove it, we can have the proposal pkg completely decoupled 623 // from the project pkg. 624 /** 625 * Creates and returns a set of projects based on the information 626 * in this proposal. 627 * <p> 628 * One project is returned for each {@link TelescopeType telescope} 629 * specified in this proposal. (If no telescopes have been specified, 630 * the returned set will be empty.) Each project in the returned set 631 * will have had this proposal sent to its 632 * {@link Project#setProposal(Proposal) setProposal} method.</p> 633 * 634 * @return a set of projects based on the information in this proposal. 635 */ 636 public Set<Project> createProjects() 637 { 638 Set<Project> projects = new HashSet<Project>(); 639 640 for (TelescopeType telescope : getTelescopes()) 641 { 642 Project project = Project.createProject(telescope); 643 project.setProposal(this); 644 projects.add(project); 645 } 646 647 return projects; 648 } 649 650 public String toString() 651 { 652 return getProposalCode() + "\n" + 653 getTitle() + "\n" + 654 getAbstract(); 655 } 656 657 //============================================================================ 658 // XML 659 //============================================================================ 660 661 /** 662 * @return a string containing the xml representation of a proposal. 663 * @see edu.nrao.sss.util.XmlSerializable#fromXml(java.lang.String) 664 public String toXML( int indent ) 665 { 666 StringBuilder sb = new StringBuilder(); 667 sb.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<proposal" ); 668 sb.append( " proposal_id=\"" + getPropId() + "\"\n" ); 669 sb.append( " legacy_id=\"" + getLegacyId() + "\"\n" ); 670 sb.append( " create_date=\""+getCreated() + "\"\n" ); 671 sb.append( " modify_date=\"" + getModified() + "\"\n" ); 672 if ( submitted != null ){ 673 sb.append( " submit_date=\"" + submitted + "\"\n" ); 674 } 675 else { 676 sb.append( " submit_date=\"\"\n"); 677 } 678 sb.append( " editor=\""+getEditor()+ "\"\n" ); 679 sb.append( " contact=\""+getContact() + "\"\n"); 680 sb.append( " pi=\""+getPI() + "\"\n" ); 681 sb.append( " previous_proposal_ids=\"" + getPrevSubmittedPropIds() + "\"\n" ); 682 sb.append( " status=\""+getStatus() + "\">\n" ); 683 sb.append( " <proposal_title>"+getTitle() + "</proposal_title>\n" ); 684 if ( previousProposals != null ){ 685 sb.append( " <previous_proposal>" + previousProposals + "</previous_proposal>\n" ); 686 } 687 else { 688 sb.append( " <previous_proposal></previous_proposal>\n" ); 689 } 690 sb.append( " <related_proposal>" + getRelatedProposals() + "</related_proposal>\n" ); 691 sb.append( " <science_category>" + scientificCategory + "</science_category>\n" ); 692 if ( scientificCategory != null && ScientificType.OTHER.equals( scientificCategory ) ){ 693 sb.append( " <science_category_other>" +scientificCategoryOther + "</science_category_other>\n" ); 694 } 695 696 if ( abstractStr != null ){ 697 sb.append( " <abstract>" + abstractStr + "</abstract>\n" ); 698 } 699 sb.append( " <support_request present=\"" + getPresent() + "\"" ); 700 sb.append( " staff_support=\""+getStaffSupport() + "\"/>\n" ); 701 sb.append( " <proposal_type>"+proposalType+"</proposal_type>/>\n" ); 702 sb.append( " <observing_types>\n" ); 703 for ( ObservingType type: observingTypes ){ 704 sb.append( " <observing_type>"+type+"</observing_type>\n"); 705 } 706 sb.append( " </observing_types>\n"); 707 if ( observingTypeOther != null ){ 708 sb.append( " <other_observing_type>"+observingTypeOther + "</other_observing_type>\n"); 709 } 710 else { 711 sb.append( " <other_observing_type></other_observing_type>\n" ); 712 } 713 714 if ( justificationFileName != null ){ 715 sb.append( " <scientific_technical_justification file_type=\"" + justificationFileName + "\"" ); 716 sb.append( " file_name=\"" + justFileType + "\" size=\"" + byteSize + "\"/>\n" ); 717 } 718 else { 719 sb.append( " <scientific_technical_justification file_type=\"\" file_name=\"\" size=\"\"/>\n"); 720 } 721 722 return sb.toString(); 723 } 724 */ 725 726 /* (non-Javadoc) 727 * @see edu.nrao.sss.model.util.XmlSerializable#toXml() 728 */ 729 public String toXml() 730 { 731 // TODO Auto-generated method stub 732 return ""; 733 } 734 735 /* (non-Javadoc) 736 * @see edu.nrao.sss.model.util.XmlSerializable#fromXml(java.lang.String) 737 */ 738 public void fromXml(String xml) 739 { 740 // TODO Auto-generated method stub 741 } 742 }