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    }