001    package org.hackystat.projectbrowser.page.projects;
002    
003    import java.io.Serializable;
004    import java.text.SimpleDateFormat;
005    import java.util.ArrayList;
006    import java.util.Calendar;
007    import java.util.Date;
008    import java.util.GregorianCalendar;
009    import java.util.List;
010    import java.util.Locale;
011    import javax.xml.datatype.DatatypeConfigurationException;
012    import javax.xml.datatype.DatatypeFactory;
013    import javax.xml.datatype.XMLGregorianCalendar;
014    import org.apache.wicket.IClusterable;
015    import org.hackystat.projectbrowser.ProjectBrowserSession;
016    import org.hackystat.sensorbase.resource.projects.jaxb.Invitations;
017    import org.hackystat.sensorbase.resource.projects.jaxb.Members;
018    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
019    import org.hackystat.sensorbase.resource.projects.jaxb.Properties;
020    import org.hackystat.sensorbase.resource.projects.jaxb.Property;
021    import org.hackystat.sensorbase.resource.projects.jaxb.Spectators;
022    import org.hackystat.sensorbase.resource.projects.jaxb.UriPatterns;
023    import org.hackystat.utilities.tstamp.Tstamp;
024    
025    /**
026     * Provides a model for the management of projects.
027     * 
028     * @author Philip Johnson.
029     * @author Randy Cox.
030     */
031    public class ProjectsModel implements Serializable, IClusterable {
032    
033      /** For serialization. */
034      private static final long serialVersionUID = 1L;
035    
036      /** Default project name. */
037      private static final String DEFAULT_PROJECT = "Default";
038      
039      /** The projects for this user. */
040      private List<Project> projects = null;
041    
042      /** Selected project for this user. */
043      private Project project = null;
044    
045      /** Current selected members from member list. */
046      private List<String> memberSelection = new ArrayList<String>();
047    
048      /** Feedback message. */
049      private String feedback = "";
050    
051      /** Feedback message. */
052      private String projectRename = "";
053    
054      /** Holds rows of property uris. */
055      private List<PropUriRowModel> propUriRowsView = new ArrayList<PropUriRowModel>();
056    
057      /** Extra property uri rows after data. */
058      private int extraPropertyUriRows = 1;
059    
060      /**
061       * The default constructor, required by Wicket.
062       */
063      public ProjectsModel() {
064        // does nothing.
065      }
066    
067      /**
068       * The sets user selected project.
069       * 
070       * @param selectedProject User selected project.
071       */
072      public ProjectsModel(Project selectedProject) {
073        setProject(selectedProject);
074      }
075    
076      /**
077       * Returns the list of projects.
078       * 
079       * @return The list of projects.
080       */
081      public List<Project> getProjects() {
082        ProjectBrowserSession.get().clearProjectList();
083        this.setProjects(ProjectBrowserSession.get().getProjectList());
084        return this.projects;
085      }
086    
087      /**
088       * Sets the projects.
089       * 
090       * @param projects The projects.
091       */
092      public void setProjects(List<Project> projects) {
093        this.projects = projects;
094      }
095    
096      /**
097       * Return the Project for this page.
098       * 
099       * @return The project.
100       */
101      public Project getProject() {
102        return this.project;
103      }
104    
105      /**
106       * Updates the ProjectsModel with the project summary instance.
107       * 
108       * @param project The project for this summary.
109       */
110      public final void setProject(Project project) {
111        this.project = project;
112      }
113    
114      /**
115       * Create an empty project with all strings allocated.
116       */
117      public final void createProject() {
118        this.project = new Project();
119        this.project.setName("");
120        this.project.setOwner(ProjectBrowserSession.get().getUserEmail());
121        this.project.setDescription("");
122    
123        GregorianCalendar startDate = new GregorianCalendar();
124        GregorianCalendar endDate = new GregorianCalendar();
125        endDate.roll(Calendar.YEAR, true);
126    
127        DatatypeFactory factory;
128        try {
129          factory = DatatypeFactory.newInstance();
130          this.project.setStartTime(factory.newXMLGregorianCalendar(startDate));
131          this.project.setEndTime(factory.newXMLGregorianCalendar(endDate));
132        }
133        catch (DatatypeConfigurationException e) {
134          e.printStackTrace();
135        }
136        this.project.setMembers(new Members());
137        this.project.setInvitations(new Invitations());
138        this.project.setSpectators(new Spectators());
139        this.project.setProperties(new Properties());
140        UriPatterns uriPatterns = new UriPatterns();
141        uriPatterns.getUriPattern().add("*");
142        this.project.setUriPatterns(uriPatterns);
143        loadPropUriRowsView();
144      }
145    
146      /**
147       * Gets string representation of data.
148       * @return String of project information.
149       */
150      public String getProjectStr() {
151        String result = "Project = \n"
152          + "  name = " + getProjectName() + "\n"
153          + "  owner = " + getProjectOwner() + "\n"
154          + "  desc = " + getProjectDesc() + "\n"
155          + "  start = " + getProjectStartDate().toString() + "\n"
156          + "  end = " + getProjectEndDate().toString() + "\n"
157          + "  members = " + this.getProjectMembersStr() + "\n"
158          + "  invitations = " + this.getProjectInvitationsStr() + "\n"
159          + "  spectators = " + this.getProjectSpectatorsStr() + "\n"
160          + "  properties = " + this.getProjectPropertiesStr() + "\n"
161          + "  uris = " + this.getProjectUriPatternsStr() + "\n";
162        return result;
163      }
164    
165      /**
166       * Get the name of current project.
167       * 
168       * @return current project
169       */
170      public String getProjectName() {
171        return this.project.getName();
172      }
173    
174      /**
175       * Set the name of the current project.
176       * 
177       * @param name of project.
178       */
179      public void setProjectName(String name) {
180        this.project.setName(name);
181      }
182    
183      /**
184       * Parses string and adds bold to any sub-string that matches the current user email.
185       * 
186       * @param string String to parse for user email
187       * @return String with all user email sub-string in bold.
188       */
189      private String convertUserEmailToBold(String string) {
190        String line = string.toLowerCase(Locale.ENGLISH);
191        String user = ProjectBrowserSession.get().getUserEmail().toLowerCase();
192        String boldUser = "<b>" + user + "</b>";
193        return line.replaceAll(user, boldUser);
194      }
195    
196      /**
197       * Parses string and adds bold to any sub-string that matches the current user email.
198       * 
199       * @param string String to parse for user email
200       * @return String with all user email sub-string in bold.
201       */
202      public String removeBold(String string) {
203        String result = string.toLowerCase(Locale.ENGLISH);
204        result = result.replaceAll("<b>", "");
205        return result.replaceAll("</b>", "");
206      }
207    
208      /**
209       * Return project owner, bold if owner is current user.
210       * 
211       * @return project owner.
212       */
213      public String getProjectOwner() {
214        return getProject().getOwner();
215      }
216    
217      /**
218       * Return project owner, bold if owner is current user.
219       * 
220       * @return project owner.
221       */
222      public String getProjectOwnerBold() {
223        String result = getProject().getOwner();
224        result = convertUserEmailToBold(result);
225        return result;
226      }
227    
228      /**
229       * Set project owner.
230       * 
231       * @param owner Project owner
232       */
233      public void setProjectOwner(String owner) {
234        getProject().setOwner(removeBold(owner));
235      }
236    
237      /**
238       * Get start date, convert from project.startTime.
239       * 
240       * @return project start date in GregorianCalendar date format.
241       */
242      public Date getProjectStartDate() {
243        Project project = getProject();
244        Calendar startTime = project.getStartTime().toGregorianCalendar();
245        return startTime.getTime();
246      }
247    
248      /**
249       * Set start date, convert to project.startTime.
250       * 
251       * @param newDate start date in GregorianCalendar date format.
252       */
253      public void setProjectStartDate(Date newDate) {
254        XMLGregorianCalendar startTime = Tstamp.makeTimestamp(newDate.getTime());
255        getProject().setStartTime(startTime);
256      }
257    
258      /**
259       * Get start date, convert from project.startTime.
260       * 
261       * @return project start date in GregorianCalendar date format.
262       */
263      public Date getProjectEndDate() {
264        Project project = getProject();
265        Calendar endTime = project.getEndTime().toGregorianCalendar();
266        return endTime.getTime();
267      }
268    
269      /**
270       * Set end date, convert to project.startTime.
271       * 
272       * @param newDate project end date in GregorianCalendar date format.
273       */
274      public void setProjectEndDate(Date newDate) {
275        XMLGregorianCalendar endTime = Tstamp.makeTimestamp(newDate.getTime());
276        getProject().setEndTime(endTime);
277      }
278    
279      /**
280       * Get project span: start and end date in one string.
281       * 
282       * @return project date span
283       */
284      public String getProjectSpan() {
285        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
286        String result = dateFormat.format(getProjectStartDate()) + "\n"
287            + dateFormat.format(getProjectEndDate());
288        return result;
289      }
290    
291      /**
292       * Get project description.
293       * 
294       * @return project description.
295       */
296      public String getProjectDesc() {
297        return getProject().getDescription();
298      }
299    
300      /**
301       * Set project description.
302       * 
303       * @param desc project description.
304       */
305      public void setProjectDesc(String desc) {
306        Project project = getProject();
307        project.setDescription(desc);
308        setProject(project);
309      }
310    
311      /**
312       * Builds a string of members with a suffix of "(N)". N is the member type passed in by
313       * "type".
314       * 
315       * @param members List of member names.
316       * @param type Member type (M = member, I = Invitee, O = Observer).
317       * @return list of members with (N) attached to denote type.
318       */
319      private String buildMemberListStr(List<String> members, String type) {
320        StringBuffer result = new StringBuffer();
321        for (String member : members) {
322          if (result.length() == 0) {
323            result.append(member).append(" (").append(type).append(')');
324          }
325          else {
326            result.append('\n').append(member).append(" (").append(type).append(')');
327          }
328        }
329        return convertUserEmailToBold(result.toString());
330      }
331    
332      /**
333       * Builds a string list of members with a suffix of "(N)". N is the member type passed in by
334       * "type".
335       * 
336       * @param members List of member names.
337       * @param type Member type (M = member, I = Invitee, O = Observer).
338       * @return list of members with (N) attached to denote type.
339       */
340      private List<String> buildMemberList(List<String> members, String type) {
341        List<String> list = new ArrayList<String>();
342        for (String member : members) {
343          String result = member + " (" + type + ')';
344          list.add(result);
345        }
346        return list;
347      }
348    
349      /**
350       * Get the project members in comma delimited form.
351       * 
352       * @param members collection of members to build string with.
353       * @param delimitor to add between members.
354       * @return List of project members in comma delimited form.
355       */
356      public String buildMembersStr(List<String> members, String delimitor) {
357        StringBuffer result = new StringBuffer();
358        for (String member : members) {
359          if (result.length() == 0) {
360            result.append(member);
361          }
362          else {
363            result.append(delimitor).append(member);
364          }
365        }
366        return result.toString();
367      }
368    
369      /**
370       * Parse the project members in comma delimited form into a collection.
371       * 
372       * @param membersStr string to parse
373       * @return List of project members in comma delimited form.
374       */
375      public List<String> parseMembersStr(String membersStr) {
376        String comma = ",";
377        List<String> result = new ArrayList<String>();
378        if ((membersStr != null) && (!"".equals(membersStr))) {
379          String str = membersStr.replace("\n", comma);
380          str = str.replace(",,", comma);
381          for (String member : str.split(comma)) {
382            result.add(member.trim());
383          }
384        }
385        return result;
386      }
387    
388      /**
389       * Remove members for project.
390       * 
391       * @param members List of project members to remove.
392       */
393      public void removeMembers(List<String> members) {
394        getProject().getMembers().getMember().removeAll(members);
395      }
396    
397      /**
398       * Get the project members.
399       * 
400       * @return List of project members.
401       */
402      public List<String> getProjectMembers() {
403        List<String> members;
404        if ((getProject() == null) || (getProject().getMembers() == null)) {
405          members = new ArrayList<String>();
406        }
407        else {
408          members = getProject().getMembers().getMember();
409        }
410        return members;
411      }
412    
413      /**
414       * Set the project members.
415       * 
416       * @param members list of project members.
417       */
418      public void setProjectMembers(List<String> members) {
419        getProject().getMembers().getMember().clear();
420        getProject().getMembers().getMember().addAll(members);
421      }
422    
423      /**
424       * Get the project members in comma delimited form.
425       * 
426       * @return List of project members in comma delimited form.
427       */
428      public String getProjectMembersStr() {
429        return buildMembersStr(getProjectMembers(), ", ");
430      }
431    
432      /**
433       * Set the project members from the comma delimited member string.
434       * 
435       * @param memberStr comma delimited member string to parse.
436       */
437      public void setProjectMembersStr(String memberStr) {
438        setProjectMembers(parseMembersStr(memberStr));
439      }
440    
441      /**
442       * Set help note for project members, display when no members present.
443       * @return help string
444       */
445      public String getProjectMemberHelp() {
446        String msg = "To add members, please enter the emails of the "
447          + "members you wish to invite in the Invitation field.  "
448          + "When the invitee logs into this application, he/she will "
449          + "be able to accept or decline your invitation.  If accepted "
450          + "the invitee will become a member of your project.";
451        return msg;
452      }
453    
454      /**
455       * Get the project invitations.
456       * 
457       * @return Invitations.
458       */
459      public List<String> getProjectInvitations() {
460        return getProject().getInvitations().getInvitation();
461      }
462    
463      /**
464       * Set the project invitations.
465       * 
466       * @param members list of project invitations.
467       */
468      public void setProjectInvitations(List<String> members) {
469        getProject().getInvitations().getInvitation().clear();
470        getProject().getInvitations().getInvitation().addAll(members);
471      }
472    
473      /**
474       * Get the project invitations in comma delimited form.
475       * 
476       * @return List of project invitations in comma delimited form.
477       */
478      public String getProjectInvitationsStr() {
479        return buildMembersStr(getProjectInvitations(), ", ");
480      }
481    
482      /**
483       * Set the project invitations from the comma delimited member string.
484       * 
485       * @param memberStr comma delimited invitation string to parse.
486       */
487      public void setProjectInvitationsStr(String memberStr) {
488        setProjectInvitations(parseMembersStr(memberStr));
489      }
490    
491      /**
492       * Get the project spectators.
493       * 
494       * @return Spectators.
495       */
496      public List<String> getProjectSpectators() {
497        return getProject().getSpectators().getSpectator();
498      }
499    
500      /**
501       * Set the project invitations.
502       * 
503       * @param members list of project invitations.
504       */
505      public void setProjectSpectators(List<String> members) {
506        getProject().getSpectators().getSpectator().clear();
507        getProject().getSpectators().getSpectator().addAll(members);
508      }
509    
510      /**
511       * Get the project spectators in comma delimited form.
512       * 
513       * @return List of project spectators in comma delimited form.
514       */
515      public String getProjectSpectatorsStr() {
516        return buildMembersStr(getProjectSpectators(), ", ");
517      }
518    
519      /**
520       * Set the project spectators from the comma delimited member string.
521       * 
522       * @param memberStr comma delimited spectator string to parse.
523       */
524      public void setProjectSpectatorsStr(String memberStr) {
525        setProjectSpectators(parseMembersStr(memberStr));
526      }
527    
528      /**
529       * Get string representation of project members.
530       * 
531       * @return String representation of project members, comma delimited.
532       */
533      public String getProjectConsolidatedMembersStr() {
534        String result = buildMemberListStr(getProjectMembers(), "M");
535        result += ("".equals(result) ? "" : "\n" );
536        result += buildMemberListStr(getProjectInvitations(), "I");
537        result += ("".equals(result) ? "" : "\n" );
538        result += buildMemberListStr(getProjectSpectators(), "S");
539        return result;
540      }
541    
542      /**
543       * Get string representation of project members.
544       * 
545       * @return List representation of project members, invitees and spectators.
546       */
547      public List<String> getProjectConsolidatedMembers() {
548        List<String> list = new ArrayList<String>();
549        list.addAll(buildMemberList(getProjectMembers(), "M"));
550        list.addAll(buildMemberList(getProjectInvitations(), "I"));
551        list.addAll(buildMemberList(getProjectSpectators(), "S"));
552        return list;
553      }
554    
555      /**
556       * Get the project properties.
557       * 
558       * @return list of properties.
559       */
560      public List<Property> getProjectProperties() {
561        return getProject().getProperties().getProperty();
562      }
563    
564      /**
565       * Set the project properties.
566       * 
567       * @param items list of project properties.
568       */
569      public void setProjectProperties(List<Property> items) {
570        getProject().getProperties().getProperty().clear();
571        getProject().getProperties().getProperty().addAll(items);
572      }
573    
574      /**
575       * Get project properties with = signs.
576       * 
577       * @return string of properties with equal signs.
578       */
579      public String getProjectPropertiesStr() {
580        List<String> list = new ArrayList<String>();
581        for (Property property : getProjectProperties()) {
582          list.add(property.getKey() + "=" + property.getValue());
583        }
584        return buildMembersStr(list, "\n");
585      }
586    
587      /**
588       * Get the project UriPatterns.
589       * 
590       * @return UriPattern.
591       */
592      public List<String> getProjectUriPatterns() {
593        return getProject().getUriPatterns().getUriPattern();
594      }
595    
596      /**
597       * Set the project UriPatterns.
598       * 
599       * @param items Uri patterns to update.
600       */
601      public void setProjectUriPatterns(List<String> items) {
602        getProject().getUriPatterns().getUriPattern().clear();
603        getProject().getUriPatterns().getUriPattern().addAll(items);
604      }
605    
606      /**
607       * Get string representation of URL patterns.
608       * 
609       * @return String representation of project URI patterns.
610       */
611      public String getProjectUriPatternsStr() {
612        return buildMembersStr(getProjectUriPatterns(), "\n");
613      }
614    
615      /**
616       * Get the project URIs in comma delimited form.
617       * 
618       * @return List of project URIs in comma delimited form.
619       */
620      public String getProjectUriCommaStr() {
621        return buildMembersStr(getProjectUriPatterns(), ", ");
622      }
623    
624      /**
625       * Return the members selected from multiple list choice control.
626       * 
627       * @return set of members selected.
628       */
629      public List<String> getMemberSelection() {
630        return this.memberSelection;
631      }
632    
633      /**
634       * Sets the members selected from the multiple list choice control.
635       * 
636       * @param memberSelection list of members in selection list
637       */
638      public void setMemberSelection(List<String> memberSelection) {
639        this.memberSelection = memberSelection;
640      }
641    
642      /**
643       * True if this model contains no data.
644       * 
645       * @return True if this model has no data.
646       */
647      public boolean isEmpty() {
648        return this.project == null;
649      }
650    
651      /**
652       * True if project can be edited.
653       * 
654       * @return True if project can be edited
655       */
656      public boolean isEditable() {
657        if (this.isEmpty()) {
658          return false;
659        }
660        Boolean editable = false;
661        String owner = this.project.getOwner();
662        String user = ProjectBrowserSession.get().getUserEmail();
663        if (owner.compareToIgnoreCase(user) == 0) {
664          editable = true;
665        }
666        if ((this.project.getName() != null)
667            && (this.project.getName().compareToIgnoreCase(DEFAULT_PROJECT) == 0)) {
668          editable = false;
669        }
670        return editable;
671      }
672    
673      /**
674       * True if project can be renamed.
675       * 
676       * @return True if project can be renamed
677       */
678      public boolean isRenameable() {
679        if (this.isEmpty()) {
680          return false;
681        }
682        Boolean renameable = false;
683        String owner = this.project.getOwner();
684        String user = ProjectBrowserSession.get().getUserEmail();
685        if (owner.compareToIgnoreCase(user) == 0) {
686          renameable = true;
687        }
688        if (this.project.getName().compareToIgnoreCase(DEFAULT_PROJECT) == 0) {
689          renameable = false;
690        }
691        return renameable;
692      }
693    
694      /**
695       * True if project can be deleted.
696       * 
697       * @return True if project can be deleted.
698       */
699      public boolean isDeletable() {
700        if (this.isEmpty()) {
701          return false;
702        }
703        Boolean deletable = false;
704        String owner = this.project.getOwner();
705        String user = ProjectBrowserSession.get().getUserEmail();
706        if (owner.compareToIgnoreCase(user) == 0) {
707          deletable = true;
708        }
709        if (this.project.getName().compareToIgnoreCase(DEFAULT_PROJECT) == 0) {
710          deletable = false;
711        }
712        return deletable;
713      }
714    
715      /**
716       * True if project can be left.
717       * 
718       * @return True if project can be left.
719       */
720      public boolean isLeavable() {
721        if (this.isEmpty()) {
722          return false;
723        }
724        Boolean leavable = false;
725        String owner = this.project.getOwner();
726        String user = ProjectBrowserSession.get().getUserEmail();
727        List<String> members = this.project.getMembers().getMember();
728        if (members.contains(user)) {
729          leavable = true;
730        }
731        if (owner.compareToIgnoreCase(user) == 0) {
732          leavable = false;
733        }
734        if (this.project.getName().compareToIgnoreCase(DEFAULT_PROJECT) == 0) {
735          leavable = false;
736        }
737        return leavable;
738      }
739    
740      /**
741       * True if you have an invitation to this project.
742       * 
743       * @return True if project can be left.
744       */
745      public boolean isRepliable() {
746        if (this.isEmpty()) {
747          return false;
748        }
749        Boolean repliable = false;
750        String user = ProjectBrowserSession.get().getUserEmail();
751        List<String> members = this.project.getInvitations().getInvitation();
752        if (members.contains(user)) {
753          repliable = true;
754        }
755        return repliable;
756      }
757    
758      /**
759       * True if project's cache can be cleared.
760       * 
761       * @return True if project's cache can be cleared.
762       */
763      public boolean isClearCacheable() {
764        if (this.isEmpty()) {
765          return false;
766        }
767        Boolean clearable = false;
768        String owner = this.project.getOwner();
769        String user = ProjectBrowserSession.get().getUserEmail();
770        if (owner.compareToIgnoreCase(user) == 0) {
771          clearable = true;
772        }
773        List<String> members = this.project.getMembers().getMember();
774        if (members.contains(user)) {
775          clearable = true;
776        }
777        List<String> spectators = this.project.getSpectators().getSpectator();
778        if (spectators.contains(user)) {
779          clearable = true;
780        }
781        return clearable;
782      }
783    
784      /**
785       * Gets current feedback string.
786       * 
787       * @return the feedback
788       */
789      public String getFeedback() {
790        return this.feedback;
791      }
792    
793      /**
794       * Sets the feedback string.
795       * 
796       * @param feedback the feedback to set
797       */
798      public void setFeedback(String feedback) {
799        this.feedback = feedback;
800      }
801    
802      /**
803       * Get the list of properties and uris at bottom of edit form.
804       * 
805       * @return the propertyUriRows
806       */
807      public List<PropUriRowModel> getPropUriRowsView() {
808        return propUriRowsView;
809      }
810    
811      /**
812       * Set the list of properties and uris at bottom of edit form.
813       * 
814       * @param propertyUriRows the propertyUriRows to set
815       */
816      public void setPropUriRowsView(List<PropUriRowModel> propertyUriRows) {
817        this.propUriRowsView = propertyUriRows;
818      }
819    
820      /**
821       * Load propertyUriRows from project data.
822       */
823      public void loadPropUriRowsView() {
824        if (this.project != null) {
825          this.propUriRowsView.clear();
826    
827          Boolean propertyDone = false;
828          Boolean uriDone = false;
829          Boolean extraRowDone = false;
830          int propertyIndex = 0;
831          int uriIndex = 0;
832          int filledRowCount = 0;
833          List<Property> properties = this.project.getProperties().getProperty();
834          List<String> uris = this.project.getUriPatterns().getUriPattern();
835    
836          while (!propertyDone || !uriDone || !extraRowDone) {
837            PropUriRowModel row = new PropUriRowModel();
838    
839            if (propertyIndex < properties.size()) {
840              row.propertyLabel = properties.get(propertyIndex).getKey();
841              row.propertyValue = properties.get(propertyIndex).getValue();
842              propertyIndex++;
843            }
844            else {
845              row.propertyLabel = null;
846              row.propertyValue = null;
847            }
848            propertyDone = (propertyIndex >= properties.size());
849    
850            row.uriPattern1 = (uriIndex < uris.size()) ? uris.get(uriIndex++) : null;
851            row.uriPattern2 = (uriIndex < uris.size()) ? uris.get(uriIndex++) : null;
852            row.uriPattern3 = (uriIndex < uris.size()) ? uris.get(uriIndex++) : null;
853            uriDone = (uriIndex >= uris.size());
854    
855            this.propUriRowsView.add(row);
856    
857            if (propertyDone && uriDone) {
858              filledRowCount = (filledRowCount == 0) ? (this.propUriRowsView.size()) : filledRowCount;
859              extraRowDone = (this.propUriRowsView.size() >= (filledRowCount + 
860                this.extraPropertyUriRows));
861            }
862          }
863        }
864      }
865    
866      /**
867       * Save data from property rows into the project object.
868       */
869      public void savePropUriRowsSave() {
870        Properties projectProperties = new Properties();
871        List<Property> properties = projectProperties.getProperty();
872        UriPatterns projectUris = new UriPatterns();
873        List<String> uris = projectUris.getUriPattern();
874    
875        for (PropUriRowModel row : getPropUriRowsView()) {
876          if ((row.getPropertyLabel() != null) || (row.getPropertyValue() != null)
877              || (row.getUriPattern1() != null) || (row.getUriPattern2() != null)
878              || (row.getUriPattern3() != null)) {
879    
880            if ((row.propertyLabel != null) && (!"".equals(row.propertyLabel))) {
881              Property property = new Property();
882              property.setKey(row.propertyLabel);
883              property.setValue(row.propertyValue);
884              properties.add(property);
885            }
886            if ((row.uriPattern1 != null) && (!"".equals(row.uriPattern1))) {
887              uris.add(row.uriPattern1);
888            }
889            if ((row.uriPattern2 != null) && (!"".equals(row.uriPattern2))) {
890              uris.add(row.uriPattern2);
891            }
892            if ((row.uriPattern3 != null) && (!"".equals(row.uriPattern3))) {
893              uris.add(row.uriPattern3);
894            }
895          }
896        }
897        this.getProject().setProperties(projectProperties);
898        this.getProject().setUriPatterns(projectUris);
899      }
900    
901      /**
902       * Add one row to bottom of Properties and URI pattern rows.
903       */
904      public void addPropUriRow() {
905        getPropUriRowsView().add(new PropUriRowModel());
906      }
907    
908      /**
909       * Get the amount of blank lines to set under populated properties/uris.
910       * 
911       * @return the extraPropertyUriRows
912       */
913      public int getExtraPropertyUriRows() {
914        return extraPropertyUriRows;
915      }
916    
917      /**
918       * Set the amount of blank lines to set under populated properties/uris.
919       * 
920       * @param extraPropertyUriRows the extraPropertyUriRows to set
921       */
922      public void setExtraPropertyUriRows(int extraPropertyUriRows) {
923        this.extraPropertyUriRows = extraPropertyUriRows;
924      }
925    
926      /**
927       * Get name to rename project with.
928       * 
929       * @return the projectRename
930       */
931      public String getProjectRename() {
932        return projectRename;
933      }
934    
935      /**
936       * Set name to rename project with.
937       * 
938       * @param projectRename the projectRename to set
939       */
940      public void setProjectRename(String projectRename) {
941        this.projectRename = projectRename;
942      }
943    
944      /**
945       * Semantic check of project.
946       * 
947       * @return true is semantic check passes.
948       */
949      public boolean isSemanticCheckOk() {
950        boolean ok = true;
951    
952        Project project = getProject();
953    
954        // Check name for spaces
955        if ((project.getName() == null) || (project.getName().contains(" ")) 
956            || (project.getName().contains("/"))) {
957          this.feedback = "Invalid project name.";
958          ok = false;
959        }
960    
961        // Check dates
962        GregorianCalendar start = project.getStartTime().toGregorianCalendar();
963        GregorianCalendar end = project.getEndTime().toGregorianCalendar();
964        if (start.after(end) || start.equals(end)) {
965          this.feedback = "Project start should be earlier than project end date.";
966          ok = false;
967        }
968    
969        // Check for URI
970        if (project.getUriPatterns().getUriPattern().isEmpty()) {
971          this.feedback = "Project needs at least one URI.";
972          ok = false;
973        }
974        return ok;
975      }
976    }