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