001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.odf.program; 017 018import java.time.LocalDate; 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Collections; 022import java.util.HashSet; 023import java.util.LinkedHashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.Optional; 027import java.util.Set; 028import java.util.stream.Collectors; 029 030import javax.jcr.Node; 031 032import org.apache.commons.lang3.ArrayUtils; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.data.ContentDataHelper; 036import org.ametys.cms.data.ContentValue; 037import org.ametys.cms.data.Geocode; 038import org.ametys.cms.data.RichText; 039import org.ametys.odf.courselist.CourseList; 040import org.ametys.odf.courselist.CourseListContainer; 041import org.ametys.plugins.repository.AmetysObjectIterable; 042import org.ametys.plugins.repository.AmetysRepositoryException; 043import org.ametys.plugins.repository.RemovableAmetysObject; 044import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 045import org.ametys.plugins.repository.data.holder.group.ModelAwareRepeater; 046import org.ametys.plugins.repository.data.holder.group.ModelAwareRepeaterEntry; 047import org.ametys.runtime.model.ElementDefinition; 048import org.ametys.runtime.model.exception.UndefinedItemPathException; 049 050/** 051 * Abstract common superclass for {@link Program} and {@link SubProgram}. 052 * @param <F> The actual type of the factory 053 */ 054public abstract class AbstractProgram<F extends ProgramFactory> extends AbstractTraversableProgramPart<F> implements CourseListContainer 055{ 056 // ------------------------------------------------// 057 // 058 // PROGRAM ATTRIBUTES 059 // 060 // -----------------------------------------------// 061 /** Constants for attribute 'degree' */ 062 public static final String DEGREE = "degree"; 063 064 /** Constants for attribute 'certified' */ 065 public static final String CERTIFIED = "certified"; 066 067 /** Constants for attribute 'domain' */ 068 public static final String DOMAIN = "domain"; 069 070 /** Constants for attribute 'mention' */ 071 public static final String MENTION = "mention"; 072 073 /** Constants for attribute 'speciality' */ 074 public static final String SPECIALITY = "speciality"; 075 076 /** Constants for attribute 'educationLevel' */ 077 public static final String LEVEL = "educationLevel"; 078 079 /** Constants for attribute 'duration' */ 080 public static final String DURATION = "duration"; 081 082 /** Constants for attribute 'educationLanguage' */ 083 public static final String EDUC_LANGUAGE = "educationLanguage"; 084 085 /** Constants for attribute 'presentation' */ 086 public static final String PRESENTATION = "presentation"; 087 088 /** Constants for attribute 'objectives' */ 089 public static final String OBJECTIVES = "objectives"; 090 091 /** Constants for attribute 'qualification' */ 092 public static final String QUALIFICATION = "qualification"; 093 094 /** Constants for attribute 'teachingOrganization' */ 095 public static final String TEACHING_ORGANIZATION = "teachingOrganization"; 096 097 /** Constants for attribute 'alternationModality' */ 098 public static final String ALTERNATION_MODALITY = "alternationModality"; 099 100 /** Constants for attribute 'accessCondition' */ 101 public static final String ACCESS_CONDITION = "accessCondition"; 102 103 /** Constants for attribute 'neededPrerequisite' */ 104 public static final String NEEDED_PREREQUISITE = "neededPrerequisite"; 105 106 /** Constants for attribute 'recommendedPrerequisite' */ 107 public static final String RECOMMENDED_PREREQUISITE = "recommendedPrerequisite"; 108 109 /** Constants for attribute 'expectedResults' */ 110 public static final String EXPECTED_RESULTS = "expectedResults"; 111 112 /** Constants for attribute 'furtherStudy' */ 113 public static final String FURTHER_STUDY = "furtherStudy"; 114 115 /** Constants for attribute 'studyAbroad' */ 116 public static final String STUDY_ABROAD = "studyAbroad"; 117 118 /** Constants for attribute 'targetGroup' */ 119 public static final String TARGET_GROUP = "targetGroup"; 120 121 /** Constants for attribute 'jobOpportunities' */ 122 public static final String JOB_OPPORTUNITIES = "jobOpportunities"; 123 124 /** Constants for attribute 'trainingStrategy' */ 125 public static final String TRAINING_STRATEGY = "trainingStrategy"; 126 127 /** Constants for attribute 'knowledgeCheck' */ 128 public static final String KNOWLEDGE_CHECK = "knowledgeCheck"; 129 130 /** Constants for attribute 'universalAdjustment' */ 131 public static final String UNIVERSAL_ADJUSTMENT = "universalAdjustment"; 132 133 /** Constants for attribute 'certifying' */ 134 public static final String CERTIFYING = "certifying"; 135 136 /** Constants for attribute 'expenses' */ 137 public static final String EXPENSES = "expenses"; 138 139 /** Constants for attribute 'additionalInformations' */ 140 public static final String ADDITIONNAL_INFORMATIONS = "additionalInformations"; 141 142 /** Constants for attribute 'jointOrgUnit' */ 143 public static final String JOINT_ORGUNIT = "jointOrgUnit"; 144 145 /** Constants for attribute 'place' */ 146 public static final String PLACE = "place"; 147 148 /** Constants for attribute 'distanceLearning' */ 149 public static final String DISTANCE_LEARNING = "distanceLearning"; 150 151 /** Constants for attribute 'educationKind' */ 152 public static final String EDUCATION_KIND = "educationKind"; 153 154 /** Constant for attribute 'formofteachingOrg' */ 155 public static final String FORM_OF_TEACHING_ORG = "formofteachingOrg"; 156 157 /** Constants for attribute 'ects' */ 158 public static final String ECTS = "ects"; 159 160 /** Constants for attribute 'internship' */ 161 public static final String INTERNSHIP = "internship"; 162 163 /** Constants for attribute 'internshipDuration' */ 164 public static final String INTERNSHIP_DURATION = "internshipDuration"; 165 166 /** Constants for attribute 'internshipAbroad' */ 167 public static final String INTERNSHIP_ABROAD = "internshipAbroad"; 168 169 /** Constants for attribute 'internshipAbroadDuration' */ 170 public static final String INTERNSHIP_ABROAD_DURATION = "internshipAbroadDuration"; 171 172 /** Constants for attribute 'registrationStart' */ 173 public static final String REGISTRATION_START = "registrationStart"; 174 175 /** Constants for attribute 'registrationDeadline' */ 176 public static final String REGISTRATION_DEADLINE = "registrationDeadline"; 177 178 /** Constants for attribute 'teachingStart' */ 179 public static final String TEACHING_START = "teachingStart"; 180 181 /** Constants for attribute 'requiredSkills' */ 182 public static final String REQUIRED_SKILLS = "requiredSkills"; 183 184 /** Constants for attribute 'partnerSchools' */ 185 public static final String PARTNER_SCHOOLS = "partnerSchools"; 186 187 /** Constants for attribute 'partnerSchools/linkUrl' */ 188 public static final String PARTNER_SCHOOLS_LINK_URL = "linkUrl"; 189 190 /** Constants for attribute 'partnerSchools/linkLabel' */ 191 public static final String PARTNER_SCHOOLS_LINK_LABEL = "linkLabel"; 192 193 /** Constants for attribute 'partnerLaboratories' */ 194 public static final String PARTNER_LABORATORIES = "partnerLaboratories"; 195 196 /** Constants for attribute 'partnerLaboratories/linkUrl' */ 197 public static final String PARTNER_LABORATORIES_LINK_URL = "linkUrl"; 198 199 /** Constants for attribute 'partnerLaboratories/linkLabel' */ 200 public static final String PARTNER_LABORATORIES_LINK_LABEL = "linkLabel"; 201 202 /** Constants for attribute 'rncpCode' */ 203 public static final String RNCP_CODE = "rncpCode"; 204 205 /** Constants for attribute 'rncpLevel' */ 206 public static final String RNCP_LEVEL = "rncpLevel"; 207 208 /** Constants for attribute 'siseCode' */ 209 public static final String SISE_CODE = "siseCode"; 210 211 /** Constants for attribute 'Cite 97' */ 212 public static final String CITE97_CODE = "cite97Code"; 213 214 /** Constants for attribute 'erasmusCode' */ 215 public static final String ERASMUS_CODE = "erasmusCode"; 216 217 /** Constants for attribute 'erasmusCode' */ 218 public static final String DGESIP_CODE = "dgesipCode"; 219 220 /** Constants for attribute 'formacode' */ 221 public static final String FORMACODE = "formacode"; 222 223 /** Constants for attribute 'romeCode' */ 224 public static final String ROME_CODE = "romeCode"; 225 226 /** Constants for attribute 'fapCode' */ 227 public static final String FAP_CODE = "fapCode"; 228 229 /** Constants for attribute 'nsfCode' */ 230 public static final String NSF_CODE = "nsfCode"; 231 232 /** Constants for attribute 'programWebSite' */ 233 public static final String PROGRAM_WEBSITE = "programWebSite"; 234 235 /** Constants for attribute 'programWebSiteLabel' */ 236 public static final String PROGRAM_WEBSITE_LABEL = "programWebSiteLabel"; 237 238 /** Constants for attribute 'programWebSiteUrl' */ 239 public static final String PROGRAM_WEBSITE_URL = "programWebSiteUrl"; 240 241 /** Constants for attribute 'attachments' */ 242 public static final String ATTACHMENTS = "attachments"; 243 244 /** Constants for attribute 'attachments/attachment' */ 245 public static final String ATTACHMENTS_ATTACHMENT = "attachment"; 246 247 /** Constants for attribute 'attachments/attachment-text' */ 248 public static final String ATTACHMENTS_ATTACHMENT_TEXT = "attachment-text"; 249 250 /** Constants for attribute 'numberOfStudents' */ 251 public static final String NUMBER_OF_STUDENTS = "numberOfStudents"; 252 253 /** Constants for attribute 'successRate' */ 254 public static final String SUCCESSRATE = "successRate"; 255 256 /** Constants for attribute 'reorientation' */ 257 public static final String REORIENTATION = "reorientation"; 258 259 /** Constants for attribute 'keywords' */ 260 public static final String KEYWORDS = "keywords"; 261 262 /** Constants for attribute 'educationEntryLevel' */ 263 public static final String EDUCATION_ENTRY_LEVEL = "educationEntryLevel"; 264 265 /** Constants for attribute 'mandatoryEntryLevel' */ 266 public static final String MANDATORY_ENTRY_LEVEL = "mandatoryEntryLevel"; 267 268 /** Constants for attribute 'programField' */ 269 public static final String PROGRAM_FIELD = "programField"; 270 271 /** Constants for attribute 'availableCertification' */ 272 public static final String AVAILABLE_CERTIFICATION = "availableCertification"; 273 274 /** Constants for attribute 'disciplines' */ 275 public static final String DISCIPLINES = "disciplines"; 276 277 /** Constants for attribute 'sectors' */ 278 public static final String SECTORS = "sectors"; 279 280 /** Constants for attribute 'internshipOpen' */ 281 public static final String INTERNSHIP_OPEN = "internshipOpen"; 282 283 /** Constants for attribute 'internshipDescription' */ 284 public static final String INTERNSHIP_DESCRIPTION = "internshipDescription"; 285 286 /** Constants for attribute 'internshipDescription/title' */ 287 public static final String INTERNSHIP_DESCRIPTION_TITLE = "title"; 288 289 /** Constants for attribute 'internshipDescription/duration' */ 290 public static final String INTERNSHIP_DESCRIPTION_DURATION = "duration"; 291 292 /** Constants for attribute 'internshipDescription/period' */ 293 public static final String INTERNSHIP_DESCRIPTION_PERIOD = "period"; 294 295 /** Constants for attribute 'internshipDescription/kind' */ 296 public static final String INTERNSHIP_DESCRIPTION_KIND = "kind"; 297 298 /** Constants for attribute 'apprenticeshipOpen' */ 299 public static final String APPRENTICESHIP_OPEN = "apprenticeshipOpen"; 300 301 /** Constants for attribute 'apprenticeshipPeriod' */ 302 public static final String APPRENTICESHIP_PERIOD = "apprenticeshipPeriod"; 303 304 /** Constants for attribute 'apprenticeshipContract' */ 305 public static final String APPRENTICESHIP_CONTRACT = "apprenticeshipContract"; 306 307 /** Constants for attribute 'internationalEducation' */ 308 public static final String INTERNATIONAL_EDUCATION = "internationalEducation"; 309 310 /** Constants for attribute 'internationalDimension' */ 311 public static final String INTERNATIONAL_DIMENSION = "internationalDimension"; 312 313 /** Constants for attribute 'geoCode' */ 314 public static final String GEOCODE = "geoCode"; 315 316 /** Constants for attribute 'otherPartners' */ 317 public static final String OTHER_PARTNERS = "otherPartners"; 318 319 /** Constants for attribute 'otherPartners' */ 320 public static final String OTHER_CONTACT = "otherContact"; 321 322 /** Constants for attribute 'campus' */ 323 public static final String CAMPUS = "campus"; 324 325 /** Constants for attribute 'foreignPlace' */ 326 public static final String FOREIGN_PLACE = "foreignPlace"; 327 328 /** Constants for attribute 'inscription' */ 329 public static final String INSCRIPTION = "inscription"; 330 331 /** Constants for attribute 'furtherStudyPrograms' */ 332 public static final String FURTHER_STUDY_PROGRAMS = "furtherStudyPrograms"; 333 334 /** 335 * References 336 */ 337 338 /** Constants for attribute 'orgUnits' */ 339 public static final String ORG_UNITS_REFERENCES = "orgUnit"; 340 341 /** Constants for attribute 'contacts' */ 342 public static final String CONTACTS = "contacts"; 343 344 /** Constants for attribute 'contacts/role' */ 345 public static final String CONTACTS_ROLE = "role"; 346 347 /** Constants for attribute 'contacts/persons' */ 348 public static final String CONTACTS_PERSONS = "persons"; 349 350 private String _contextPath; 351 352 // ------------------------------------------------// 353 // 354 // PROGRAM METHODS 355 // 356 // -----------------------------------------------// 357 /** 358 * Constructor 359 * @param node The JCR node 360 * @param parentPath The parent path 361 * @param factory The factory 362 */ 363 public AbstractProgram(Node node, String parentPath, F factory) 364 { 365 super(node, parentPath, factory); 366 } 367 368 @Override 369 public void remove() throws AmetysRepositoryException, RepositoryIntegrityViolationException 370 { 371 AmetysObjectIterable<RemovableAmetysObject> children = this.getChildren(); 372 373 for (RemovableAmetysObject child : children) 374 { 375 child.remove(); 376 } 377 378 super.remove(); 379 } 380 381 /** 382 * Set the parent path for links and breadcrumb 383 * @param path the parent path 384 */ 385 public void setContextPath (String path) 386 { 387 _contextPath = path; 388 } 389 390 /** 391 * Get the parent path. Can be null. 392 * @return the parent path 393 */ 394 public String getContextPath () 395 { 396 return _contextPath; 397 } 398 399 // --------------------------------------------------------------------------------------// 400 // ORGUNITS 401 // --------------------------------------------------------------------------------------// 402 403 /** 404 * Return the list of orgUnits binded to this program 405 * @return a list of uuid 406 */ 407 public List<String> getOrgUnits() 408 { 409 try 410 { 411 return ContentDataHelper.getContentIdsListFromMultipleContentData(this, ORG_UNITS_REFERENCES); 412 } 413 catch (UndefinedItemPathException e) 414 { 415 return Collections.EMPTY_LIST; // this attribute is not part of model 416 } 417 } 418 419 // --------------------------------------------------------------------------------------// 420 // CONTACTS 421 // --------------------------------------------------------------------------------------// 422 423 /** 424 * Return the list of Persons in charge binded to this program 425 * @return a list of roles and UUID 426 */ 427 public Set<String> getContacts() 428 { 429 Set<String> contactIds = new HashSet<>(); 430 431 ModelAwareRepeater contacts = getRepeater(CONTACTS); 432 if (contacts != null) 433 { 434 for (ModelAwareRepeaterEntry contactEntry : contacts.getEntries()) 435 { 436 // Remove empty values 437 contactIds.addAll(ContentDataHelper.getContentIdsStreamFromMultipleContentData(contactEntry, CONTACTS_PERSONS) 438 .filter(contentId -> !contentId.isEmpty()) 439 .collect(Collectors.toSet())); 440 } 441 } 442 443 return contactIds; 444 } 445 446 /** 447 * Return the list of Persons in charge binded to this program 448 * @return a list of roles and UUID 449 */ 450 public Map<String, List<String>> getContactsByRole() 451 { 452 Map<String, List<String>> contactsByRole = new LinkedHashMap<>(); 453 454 ModelAwareRepeater contacts = getRepeater(CONTACTS); 455 if (contacts != null) 456 { 457 for (ModelAwareRepeaterEntry contactEntry : contacts.getEntries()) 458 { 459 // Remove empty values 460 List<String> persons = ContentDataHelper.getContentIdsStreamFromMultipleContentData(contactEntry, CONTACTS_PERSONS) 461 .filter(contentId -> !contentId.isEmpty()) 462 .collect(Collectors.toList()); 463 if (!persons.isEmpty()) 464 { 465 String role = ContentDataHelper.getContentIdFromContentData(contactEntry, CONTACTS_ROLE); 466 List<String> personList = contactsByRole.getOrDefault(role, new ArrayList<>()); 467 personList.addAll(persons); 468 contactsByRole.put(role, personList); 469 } 470 } 471 } 472 473 return contactsByRole; 474 } 475 476 // --------------------------------------------------------------------------------------// 477 // GETTERS AND SETTERS 478 // --------------------------------------------------------------------------------------// 479 /** 480 * Returns true if the {@link AbstractProgram} is certified 481 * @return true if certified 482 */ 483 public boolean isCertified() 484 { 485 return getValue(CERTIFIED, false, false); 486 } 487 488 /** 489 * Get the domain 490 * @return the domain or an empty array 491 */ 492 public String[] getDomain() 493 { 494 try 495 { 496 ElementDefinition definition = (ElementDefinition) getDefinition(DOMAIN); 497 if (definition.isMultiple()) 498 { 499 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, DOMAIN); 500 } 501 else 502 { 503 return new String[] {ContentDataHelper.getContentIdFromContentData(this, DOMAIN)}; 504 } 505 } 506 catch (UndefinedItemPathException e) 507 { 508 return null; // this attribute is not part of model 509 } 510 511 } 512 513 /** 514 * Get the education presentation 515 * @return the education presentation or null if not set 516 */ 517 public RichText getPresentation() 518 { 519 try 520 { 521 return getValue(PRESENTATION); 522 } 523 catch (UndefinedItemPathException e) 524 { 525 return null; // this attribute is not part of model 526 } 527 } 528 529 /** 530 * Get the education objectives 531 * @return the education objectives or null if not set 532 */ 533 public RichText getObjectives() 534 { 535 try 536 { 537 return getValue(OBJECTIVES); 538 } 539 catch (UndefinedItemPathException e) 540 { 541 return null; // this attribute is not part of model 542 } 543 } 544 545 /** 546 * Get the education qualification 547 * @return the education qualification or null if not set 548 */ 549 public RichText getQualification() 550 { 551 try 552 { 553 return getValue(QUALIFICATION); 554 } 555 catch (UndefinedItemPathException e) 556 { 557 return null; // this attribute is not part of model 558 } 559 } 560 561 /** 562 * Get the education organization 563 * @return the education organization or null if not set 564 */ 565 public RichText getTeachingOrganization() 566 { 567 try 568 { 569 return getValue(TEACHING_ORGANIZATION); 570 } 571 catch (UndefinedItemPathException e) 572 { 573 return null; // this attribute is not part of model 574 } 575 } 576 577 /** 578 * Get the alternation modality 579 * @return the alternation modality or null if not set 580 */ 581 public RichText getAlternationModality() 582 { 583 try 584 { 585 return getValue(ALTERNATION_MODALITY); 586 } 587 catch (UndefinedItemPathException e) 588 { 589 return null; // this attribute is not part of model 590 } 591 } 592 593 /** 594 * Get the access conditions 595 * @return the access conditions or null if not set 596 */ 597 public RichText getAccessCondition() 598 { 599 try 600 { 601 return getValue(ACCESS_CONDITION); 602 } 603 catch (UndefinedItemPathException e) 604 { 605 return null; // this attribute is not part of model 606 } 607 } 608 609 /** 610 * Get the education requirements 611 * @return the education requirements or null if not set 612 */ 613 public RichText getNeededPrerequisite() 614 { 615 try 616 { 617 return getValue(NEEDED_PREREQUISITE); 618 } 619 catch (UndefinedItemPathException e) 620 { 621 return null; // this attribute is not part of model 622 } 623 } 624 625 /** 626 * Get the education recommended prerequisite 627 * @return the education recommended prerequisite or null if not set 628 */ 629 public RichText getRecommendedPrerequisite() 630 { 631 try 632 { 633 return getValue(RECOMMENDED_PREREQUISITE); 634 } 635 catch (UndefinedItemPathException e) 636 { 637 return null; // this attribute is not part of model 638 } 639 } 640 641 /** 642 * Get the education expected results 643 * @return the education expected results or null if not set 644 */ 645 public RichText getExpectedResults() 646 { 647 try 648 { 649 return getValue(EXPECTED_RESULTS); 650 } 651 catch (UndefinedItemPathException e) 652 { 653 return null; // this attribute is not part of model 654 } 655 } 656 657 /** 658 * Get the education further study 659 * @return the education further study or null if not set 660 */ 661 public RichText getFurtherStudy() 662 { 663 try 664 { 665 return getValue(FURTHER_STUDY); 666 } 667 catch (UndefinedItemPathException e) 668 { 669 return null; // this attribute is not part of model 670 } 671 } 672 673 /** 674 * Get the education study abroard 675 * @return the education study abroard or null if not set 676 */ 677 public RichText getStudyAbroad() 678 { 679 try 680 { 681 return getValue(STUDY_ABROAD); 682 } 683 catch (UndefinedItemPathException e) 684 { 685 return null; // this attribute is not part of model 686 } 687 } 688 689 /** 690 * Get the education target 691 * @return the education target or null if not set 692 */ 693 public RichText getTargetGroup() 694 { 695 try 696 { 697 return getValue(TARGET_GROUP); 698 } 699 catch (UndefinedItemPathException e) 700 { 701 return null; // this attribute is not part of model 702 } 703 } 704 705 /** 706 * Get the job opportunities 707 * @return the job opportunities or null if not set 708 */ 709 public RichText getJobOpportunities() 710 { 711 try 712 { 713 return getValue(JOB_OPPORTUNITIES); 714 } 715 catch (UndefinedItemPathException e) 716 { 717 return null; // this attribute is not part of model 718 } 719 } 720 721 /** 722 * Get the training strategy 723 * @return the training strategy or null if not set 724 */ 725 public RichText getTrainingStrategy() 726 { 727 try 728 { 729 return getValue(TRAINING_STRATEGY); 730 } 731 catch (UndefinedItemPathException e) 732 { 733 return null; // this attribute is not part of model 734 } 735 } 736 737 /** 738 * Get acknowledgments 739 * @return acknowledgments or null if not set 740 */ 741 public RichText getKnowledgeCheck() 742 { 743 try 744 { 745 return getValue(KNOWLEDGE_CHECK); 746 } 747 catch (UndefinedItemPathException e) 748 { 749 return null; // this attribute is not part of model 750 } 751 } 752 753 /** 754 * Get universal adjustment 755 * @return universal adjustment or null if not set 756 */ 757 public RichText getUniversalAdjustment() 758 { 759 try 760 { 761 return getValue(UNIVERSAL_ADJUSTMENT); 762 } 763 catch (UndefinedItemPathException e) 764 { 765 return null; // this attribute is not part of model 766 } 767 } 768 769 /** 770 * Is certifying 771 * @return <code>true</code> if the progam is certifying 772 */ 773 public boolean isCertifying() 774 { 775 try 776 { 777 return getValue(CERTIFYING, false, false); 778 } 779 catch (UndefinedItemPathException e) 780 { 781 return false; // this attribute is not part of model 782 } 783 } 784 785 /** 786 * Get the additional informations 787 * @return the additional informations or null if not set 788 */ 789 public RichText getAdditionalInformations() 790 { 791 try 792 { 793 return getValue(ADDITIONNAL_INFORMATIONS); 794 } 795 catch (UndefinedItemPathException e) 796 { 797 return null; // this attribute is not part of model 798 } 799 } 800 801 /** 802 * Get the education level 803 * @return the education level or null 804 */ 805 public String getEducationLevel() 806 { 807 try 808 { 809 return ContentDataHelper.getContentIdFromContentData(this, LEVEL); 810 } 811 catch (UndefinedItemPathException e) 812 { 813 return null; // this attribute is not part of model 814 } 815 } 816 817 /** 818 * Get the RNCP code 819 * @return the RNCP code 820 */ 821 public String[] getRncpCode() 822 { 823 try 824 { 825 return getValue(RNCP_CODE, false, ArrayUtils.EMPTY_STRING_ARRAY); 826 } 827 catch (UndefinedItemPathException e) 828 { 829 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 830 } 831 } 832 833 /** 834 * Get the RNCP level 835 * @return the RNCP level 836 */ 837 public String[] getRncpLevel() 838 { 839 try 840 { 841 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, RNCP_LEVEL); 842 } 843 catch (UndefinedItemPathException e) 844 { 845 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 846 } 847 } 848 849 /** 850 * Get the SISE code 851 * @return the SISE code 852 */ 853 public String[] getSiseCode() 854 { 855 try 856 { 857 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, SISE_CODE); 858 } 859 catch (UndefinedItemPathException e) 860 { 861 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 862 } 863 } 864 865 /** 866 * Get the CITE97 code 867 * @return the CITE97 code 868 */ 869 public String[] getCite97Code() 870 { 871 try 872 { 873 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, CITE97_CODE); 874 } 875 catch (UndefinedItemPathException e) 876 { 877 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 878 } 879 } 880 881 /** 882 * Get the DGESIP code 883 * @return the DGESIP code 884 */ 885 public String[] getDGESIPCode() 886 { 887 try 888 { 889 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, DGESIP_CODE); 890 } 891 catch (UndefinedItemPathException e) 892 { 893 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 894 } 895 } 896 897 /** 898 * Get the Erasmus code 899 * @return the Erasmus code 900 */ 901 public String[] getErasmusCode() 902 { 903 try 904 { 905 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, ERASMUS_CODE); 906 } 907 catch (UndefinedItemPathException e) 908 { 909 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 910 } 911 } 912 913 /** 914 * Get the FORMACODE 915 * @return the FORMACODE 916 */ 917 public String[] getFORMACODE() 918 { 919 try 920 { 921 return getValue(FORMACODE, false, ArrayUtils.EMPTY_STRING_ARRAY); 922 } 923 catch (UndefinedItemPathException e) 924 { 925 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 926 } 927 } 928 929 /** 930 * Get the ROME code 931 * @return the ROME code 932 */ 933 public String[] getRomeCode() 934 { 935 try 936 { 937 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, ROME_CODE); 938 } 939 catch (UndefinedItemPathException e) 940 { 941 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 942 } 943 } 944 945 /** 946 * Get the FAP code 947 * @return the FAP code 948 */ 949 public String[] getFapCode() 950 { 951 try 952 { 953 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, FAP_CODE); 954 } 955 catch (UndefinedItemPathException e) 956 { 957 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 958 } 959 } 960 961 /** 962 * Get the NSF code 963 * @return the NSF code 964 */ 965 public String getNSFCode() 966 { 967 try 968 { 969 return ContentDataHelper.getContentIdFromContentData(this, NSF_CODE); 970 } 971 catch (UndefinedItemPathException e) 972 { 973 return null; // this attribute is not part of model 974 } 975 } 976 977 /** 978 * Get the mention 979 * @return the mention or null 980 */ 981 public String getMention() 982 { 983 try 984 { 985 return ContentDataHelper.getContentIdFromContentData(this, MENTION); 986 } 987 catch (UndefinedItemPathException e) 988 { 989 return null; // this attribute is not part of model 990 } 991 } 992 993 /** 994 * Get the speciality 995 * @return the speciality or null 996 */ 997 public String getSpeciality() 998 { 999 try 1000 { 1001 return getValue(SPECIALITY, false, StringUtils.EMPTY); 1002 } 1003 catch (UndefinedItemPathException e) 1004 { 1005 return null; // this attribute is not part of model 1006 } 1007 } 1008 1009 /** 1010 * Get the org units 1011 * @return the org units 1012 */ 1013 public String[] getJointOrgUnit() 1014 { 1015 try 1016 { 1017 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, JOINT_ORGUNIT); 1018 } 1019 catch (UndefinedItemPathException e) 1020 { 1021 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1022 } 1023 } 1024 1025 /** 1026 * Get the places 1027 * @return the places as an Array of String 1028 */ 1029 public String[] getPlace() 1030 { 1031 try 1032 { 1033 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, PLACE); 1034 } 1035 catch (UndefinedItemPathException e) 1036 { 1037 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1038 } 1039 } 1040 1041 /** 1042 * Get the list of websites 1043 * @return the list of website or an empty list 1044 */ 1045 public Set<WebsiteLink> getWebsiteLinks() 1046 { 1047 Set<WebsiteLink> websites = new HashSet<>(); 1048 1049 try 1050 { 1051 ModelAwareRepeater webSites = getRepeater(PROGRAM_WEBSITE); 1052 if (webSites != null) 1053 { 1054 for (ModelAwareRepeaterEntry entry : webSites.getEntries()) 1055 { 1056 WebsiteLink website = new WebsiteLink(entry.getValue(PROGRAM_WEBSITE_URL, false, StringUtils.EMPTY), entry.getValue(PROGRAM_WEBSITE_LABEL, false, StringUtils.EMPTY)); 1057 websites.add(website); 1058 } 1059 } 1060 } 1061 catch (UndefinedItemPathException e) 1062 { 1063 // this attribute is not part of model 1064 } 1065 1066 return websites; 1067 } 1068 1069 /** 1070 * Get the ECTS credits 1071 * @return the ECTS credits 1072 */ 1073 public String getEcts() 1074 { 1075 try 1076 { 1077 return ContentDataHelper.getContentIdFromContentData(this, ECTS); 1078 } 1079 catch (UndefinedItemPathException e) 1080 { 1081 return null; // this attribute is not part of model 1082 } 1083 } 1084 1085 /** 1086 * Get the kind of education 1087 * @return the kind of education or null 1088 */ 1089 public String getEducationKind() 1090 { 1091 try 1092 { 1093 return ContentDataHelper.getContentIdFromContentData(this, EDUCATION_KIND); 1094 } 1095 catch (UndefinedItemPathException e) 1096 { 1097 return null; // this attribute is not part of model 1098 } 1099 } 1100 1101 /** 1102 * Get the duration 1103 * @return the duration 1104 */ 1105 public String getDuration() 1106 { 1107 try 1108 { 1109 return ContentDataHelper.getContentIdFromContentData(this, DURATION); 1110 } 1111 catch (UndefinedItemPathException e) 1112 { 1113 return null; // this attribute is not part of model 1114 } 1115 } 1116 1117 /** 1118 * Get the education languages 1119 * @return the education languages 1120 */ 1121 public String[] getEducationLanguage() 1122 { 1123 try 1124 { 1125 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, EDUC_LANGUAGE); 1126 } 1127 catch (UndefinedItemPathException e) 1128 { 1129 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1130 } 1131 } 1132 1133 /** 1134 * Get the effectives 1135 * @return the effectives 1136 */ 1137 public RichText getEffectives() 1138 { 1139 try 1140 { 1141 return getValue(NUMBER_OF_STUDENTS); 1142 } 1143 catch (UndefinedItemPathException e) 1144 { 1145 return null; // this attribute is not part of model 1146 } 1147 } 1148 1149 /** 1150 * Get the SuccessRate 1151 * @return the SuccessRate 1152 */ 1153 public String getSuccessRate() 1154 { 1155 try 1156 { 1157 return getValue(SUCCESSRATE, false, StringUtils.EMPTY); 1158 } 1159 catch (UndefinedItemPathException e) 1160 { 1161 return null; // this attribute is not part of model 1162 } 1163 } 1164 1165 /** 1166 * Get the expenses 1167 * @return the expenses 1168 */ 1169 public RichText getExpenses() 1170 { 1171 try 1172 { 1173 return getValue(EXPENSES); 1174 } 1175 catch (UndefinedItemPathException e) 1176 { 1177 return null; // this attribute is not part of model 1178 } 1179 } 1180 1181 /** 1182 * Get the form of teaching organization 1183 * @return the form of teaching organization 1184 */ 1185 public String[] getFormOfTeachingOrgs() 1186 { 1187 try 1188 { 1189 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, FORM_OF_TEACHING_ORG); 1190 } 1191 catch (UndefinedItemPathException e) 1192 { 1193 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1194 } 1195 } 1196 1197 /** 1198 * Get the REORIENTATION 1199 * @return RichText 1200 */ 1201 public RichText getReorientation() 1202 { 1203 try 1204 { 1205 return getValue(REORIENTATION); 1206 } 1207 catch (UndefinedItemPathException e) 1208 { 1209 return null; // this attribute is not part of model 1210 } 1211 } 1212 1213 /** 1214 * Get the distance learning 1215 * @return the distance learning or null 1216 */ 1217 public String getDistanceLearning() 1218 { 1219 try 1220 { 1221 return ContentDataHelper.getContentIdFromContentData(this, DISTANCE_LEARNING); 1222 } 1223 catch (UndefinedItemPathException e) 1224 { 1225 return null; // this attribute is not part of model 1226 } 1227 } 1228 1229 /** 1230 * Get the internship 1231 * @return the internship or null 1232 */ 1233 public String getInternship() 1234 { 1235 try 1236 { 1237 return ContentDataHelper.getContentIdFromContentData(this, INTERNSHIP); 1238 } 1239 catch (UndefinedItemPathException e) 1240 { 1241 return null; // this attribute is not part of model 1242 } 1243 } 1244 1245 /** 1246 * Get the internship duration 1247 * @return the internship duration or null 1248 */ 1249 public String getInternshipDuration() 1250 { 1251 try 1252 { 1253 return getValue(INTERNSHIP_DURATION, false, StringUtils.EMPTY); 1254 } 1255 catch (UndefinedItemPathException e) 1256 { 1257 return null; // this attribute is not part of model 1258 } 1259 } 1260 1261 /** 1262 * Get the internship abroad 1263 * @return the internship abroad or null 1264 */ 1265 public String getInternshipAbroad() 1266 { 1267 try 1268 { 1269 return ContentDataHelper.getContentIdFromContentData(this, INTERNSHIP_ABROAD); 1270 } 1271 catch (UndefinedItemPathException e) 1272 { 1273 return null; // this attribute is not part of model 1274 } 1275 } 1276 1277 /** 1278 * Get the internship abroad duration 1279 * @return the internship abroad duration or null 1280 */ 1281 public String getAbroadInternshipDuration() 1282 { 1283 try 1284 { 1285 return getValue(INTERNSHIP_ABROAD_DURATION, false, StringUtils.EMPTY); 1286 } 1287 catch (UndefinedItemPathException e) 1288 { 1289 return null; // this attribute is not part of model 1290 } 1291 } 1292 1293 /** 1294 * Get the registration start date. 1295 * @return The registration start date, can be null. 1296 */ 1297 public LocalDate getRegistrationStart() 1298 { 1299 try 1300 { 1301 return getValue(REGISTRATION_START); 1302 } 1303 catch (UndefinedItemPathException e) 1304 { 1305 return null; // this attribute is not part of model 1306 } 1307 } 1308 1309 /** 1310 * Get the registration deadline date. 1311 * @return The registration deadline date, can be null. 1312 */ 1313 public LocalDate getRegistrationDeadline() 1314 { 1315 try 1316 { 1317 return getValue(REGISTRATION_DEADLINE); 1318 } 1319 catch (UndefinedItemPathException e) 1320 { 1321 return null; // this attribute is not part of model 1322 } 1323 } 1324 1325 /** 1326 * Get the teaching start date. 1327 * @return The teaching start date, can be null. 1328 */ 1329 public LocalDate getTeachingStart() 1330 { 1331 try 1332 { 1333 return getValue(TEACHING_START); 1334 } 1335 catch (UndefinedItemPathException e) 1336 { 1337 return null; // this attribute is not part of model 1338 } 1339 } 1340 1341 /** 1342 * Get the keywords 1343 * @return the keywords 1344 */ 1345 public String[] getKeywords() 1346 { 1347 try 1348 { 1349 return getValue(KEYWORDS, false, ArrayUtils.EMPTY_STRING_ARRAY); 1350 } 1351 catch (UndefinedItemPathException e) 1352 { 1353 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1354 } 1355 } 1356 1357 /** 1358 * Get the education level entry 1359 * @return the education level entry 1360 */ 1361 public String[] getEducationLevelEntry() 1362 { 1363 try 1364 { 1365 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, EDUCATION_ENTRY_LEVEL); 1366 } 1367 catch (UndefinedItemPathException e) 1368 { 1369 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1370 } 1371 } 1372 1373 /** 1374 * Is the entry level mandatory 1375 * @return <code>true</code> if the entry level is mandatory 1376 */ 1377 public boolean isMandatoryEntryLevel() 1378 { 1379 try 1380 { 1381 return getValue(MANDATORY_ENTRY_LEVEL, false, false); 1382 } 1383 catch (UndefinedItemPathException e) 1384 { 1385 return false; // this attribute is not part of model 1386 } 1387 } 1388 1389 /** 1390 * Get the program fields 1391 * @return the program fields 1392 */ 1393 public String[] getProgramField() 1394 { 1395 try 1396 { 1397 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, PROGRAM_FIELD); 1398 } 1399 catch (UndefinedItemPathException e) 1400 { 1401 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1402 } 1403 } 1404 1405 /** 1406 * Get the available certifications 1407 * @return the available certifications 1408 */ 1409 public String[] getAvailableCertification() 1410 { 1411 try 1412 { 1413 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, AVAILABLE_CERTIFICATION); 1414 } 1415 catch (UndefinedItemPathException e) 1416 { 1417 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1418 } 1419 } 1420 1421 /** 1422 * Get the disciplines 1423 * @return the disciplines 1424 */ 1425 public String[] getDisciplines() 1426 { 1427 try 1428 { 1429 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, DISCIPLINES); 1430 } 1431 catch (UndefinedItemPathException e) 1432 { 1433 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1434 } 1435 } 1436 1437 /** 1438 * Get the required skills 1439 * @return the required skills 1440 */ 1441 public String[] getRequiredSkills() 1442 { 1443 try 1444 { 1445 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, REQUIRED_SKILLS); 1446 } 1447 catch (UndefinedItemPathException e) 1448 { 1449 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1450 } 1451 } 1452 1453 /** 1454 * Get the sectors 1455 * @return the sectors 1456 */ 1457 public String[] getSectors() 1458 { 1459 try 1460 { 1461 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, SECTORS); 1462 } 1463 catch (UndefinedItemPathException e) 1464 { 1465 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1466 } 1467 } 1468 1469 /** 1470 * Is intership open 1471 * @return <code>true</code> if internship is open 1472 */ 1473 public boolean isInternshipOpen() 1474 { 1475 try 1476 { 1477 return getValue(INTERNSHIP_OPEN, false, false); 1478 } 1479 catch (UndefinedItemPathException e) 1480 { 1481 return false; // this attribute is not part of model 1482 } 1483 } 1484 1485 /** 1486 * Is apprenticeship open 1487 * @return <code>true</code> if apprenticeship is open 1488 */ 1489 public boolean isApprenticeshipOpen() 1490 { 1491 try 1492 { 1493 return getValue(APPRENTICESHIP_OPEN, false, false); 1494 } 1495 catch (UndefinedItemPathException e) 1496 { 1497 return false; // this attribute is not part of model 1498 } 1499 } 1500 1501 /** 1502 * Get the apprenticeship period description 1503 * @return the apprenticeship period 1504 */ 1505 public RichText getApprenticeshipPeriod() 1506 { 1507 try 1508 { 1509 return getValue(APPRENTICESHIP_PERIOD); 1510 } 1511 catch (UndefinedItemPathException e) 1512 { 1513 return null; // this attribute is not part of model 1514 } 1515 } 1516 1517 /** 1518 * Get the available apprenticeship contracts 1519 * @return the apprenticeship contracts 1520 */ 1521 public String[] getApprenticeshipContract() 1522 { 1523 try 1524 { 1525 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, APPRENTICESHIP_CONTRACT); 1526 } 1527 catch (UndefinedItemPathException e) 1528 { 1529 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1530 } 1531 } 1532 1533 /** 1534 * Get the international education 1535 * @return the international education 1536 */ 1537 public String[] getInternationalEducation() 1538 { 1539 try 1540 { 1541 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, INTERNATIONAL_EDUCATION); 1542 } 1543 catch (UndefinedItemPathException e) 1544 { 1545 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1546 } 1547 } 1548 1549 /** 1550 * Get the international dimension 1551 * @return the international dimension 1552 */ 1553 public RichText getInternationalDimension() 1554 { 1555 try 1556 { 1557 return getValue(INTERNATIONAL_DIMENSION); 1558 } 1559 catch (UndefinedItemPathException e) 1560 { 1561 return null; // this attribute is not part of model 1562 } 1563 } 1564 1565 /** 1566 * Get the geocode latitude and longitude 1567 * @return the geocode 1568 */ 1569 public Geocode getGeocode() 1570 { 1571 try 1572 { 1573 return getValue(GEOCODE); 1574 } 1575 catch (UndefinedItemPathException e) 1576 { 1577 return null; // this attribute is not part of model 1578 } 1579 } 1580 1581 /** 1582 * Get the other partners 1583 * @return the other partners 1584 */ 1585 public RichText getOtherPartners() 1586 { 1587 try 1588 { 1589 return getValue(OTHER_PARTNERS); 1590 } 1591 catch (UndefinedItemPathException e) 1592 { 1593 return null; // this attribute is not part of model 1594 } 1595 } 1596 1597 /** 1598 * Get the campus 1599 * @return the campus 1600 */ 1601 public String[] getCampus() 1602 { 1603 try 1604 { 1605 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, CAMPUS); 1606 } 1607 catch (UndefinedItemPathException e) 1608 { 1609 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1610 } 1611 } 1612 1613 /** 1614 * Get the foreign places 1615 * @return the foreign places 1616 */ 1617 public String[] getForeignPlace() 1618 { 1619 try 1620 { 1621 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, FOREIGN_PLACE); 1622 } 1623 catch (UndefinedItemPathException e) 1624 { 1625 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1626 } 1627 } 1628 1629 /** 1630 * Get the inscription 1631 * @return the inscription 1632 */ 1633 public RichText getInscription() 1634 { 1635 try 1636 { 1637 return getValue(INSCRIPTION); 1638 } 1639 catch (UndefinedItemPathException e) 1640 { 1641 return null; // this attribute is not part of model 1642 } 1643 } 1644 1645 /** 1646 * Get the further study programs 1647 * @return the further study programs 1648 */ 1649 public String[] getFurtherStudyPrograms() 1650 { 1651 try 1652 { 1653 return ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, FURTHER_STUDY_PROGRAMS); 1654 } 1655 catch (UndefinedItemPathException e) 1656 { 1657 return ArrayUtils.EMPTY_STRING_ARRAY; // this attribute is not part of model 1658 } 1659 } 1660 1661 // --------------------------------------------------------------------------------------// 1662 // Methods of CourseListContainer 1663 // --------------------------------------------------------------------------------------// 1664 @Override 1665 public List<CourseList> getCourseLists() 1666 { 1667 return Arrays.stream(getValue(CHILD_PROGRAM_PARTS, false, new ContentValue[0])) 1668 .map(ContentValue::getContentIfExists) 1669 .filter(Optional::isPresent) 1670 .map(Optional::get) 1671 // This cast is not checked because an exception must be thrown if the retrieved content is not a program part 1672 // TODO: change this behavior to throw our own exception and not a CassCastException 1673 .map(ProgramPart.class::cast) 1674 // Program parts that are not course lists are simply ignored 1675 .filter(CourseList.class::isInstance) 1676 .map(CourseList.class::cast) 1677 .collect(Collectors.toList()); 1678 } 1679 1680 @Override 1681 public boolean containsCourseList(String clId) 1682 { 1683 return ArrayUtils.contains(ContentDataHelper.getContentIdsArrayFromMultipleContentData(this, CHILD_PROGRAM_PARTS), clId); 1684 } 1685 1686 @Override 1687 public boolean hasCourseLists() 1688 { 1689 return !getCourseLists().isEmpty(); 1690 } 1691 1692 // --------------------------------------------------------------------------------------// 1693 // CDMfr 1694 // --------------------------------------------------------------------------------------// 1695 @Override 1696 protected String getCDMType() 1697 { 1698 return "PR"; 1699 } 1700 1701 /** 1702 * Returns the surrounding tag name in the CDM-fr representation. 1703 * @return the surrounding tag name 1704 */ 1705 public abstract String getCDMTagName(); 1706}