001/* 002 * Copyright 2012 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.plugins.odfweb.repository; 017 018import java.util.Arrays; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.Iterator; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import javax.jcr.Node; 028import javax.jcr.RepositoryException; 029import javax.jcr.Value; 030 031import org.apache.avalon.framework.activity.Initializable; 032import org.apache.avalon.framework.component.Component; 033import org.apache.avalon.framework.logger.AbstractLogEnabled; 034import org.apache.avalon.framework.service.ServiceException; 035import org.apache.avalon.framework.service.ServiceManager; 036import org.apache.avalon.framework.service.Serviceable; 037 038import org.ametys.cms.FilterNameHelper; 039import org.ametys.cms.content.ContentHelper; 040import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 041import org.ametys.cms.contenttype.ContentTypesHelper; 042import org.ametys.cms.contenttype.MetadataDefinition; 043import org.ametys.core.ui.Callable; 044import org.ametys.core.util.I18nUtils; 045import org.ametys.odf.ProgramItem; 046import org.ametys.odf.catalog.CatalogsManager; 047import org.ametys.odf.course.Course; 048import org.ametys.odf.enumeration.OdfReferenceTableHelper; 049import org.ametys.odf.orgunit.RootOrgUnitProvider; 050import org.ametys.odf.program.AbstractProgram; 051import org.ametys.odf.program.Program; 052import org.ametys.odf.tree.OdfClassificationHandler; 053import org.ametys.plugins.odfweb.restrictions.OdfProgramRestriction; 054import org.ametys.plugins.odfweb.restrictions.OdfProgramRestrictionManager; 055import org.ametys.plugins.repository.AmetysObjectIterable; 056import org.ametys.plugins.repository.AmetysObjectResolver; 057import org.ametys.plugins.repository.AmetysRepositoryException; 058import org.ametys.plugins.repository.jcr.JCRAmetysObject; 059import org.ametys.plugins.repository.provider.WorkspaceSelector; 060import org.ametys.plugins.repository.query.expression.Expression; 061import org.ametys.plugins.repository.query.expression.VirtualFactoryExpression; 062import org.ametys.runtime.i18n.I18nizableText; 063import org.ametys.web.repository.page.Page; 064import org.ametys.web.repository.page.PageQueryHelper; 065import org.ametys.web.repository.site.Site; 066import org.ametys.web.repository.sitemap.Sitemap; 067 068import com.google.common.collect.ImmutableList; 069 070/** 071 * Component providing methods to retrieve ODF virtual pages, such as the ODF root, 072 * level 1 and 2 metadata names, and so on. 073 */ 074public class OdfPageHandler extends AbstractLogEnabled implements Component, Initializable, Serviceable 075{ 076 /** The avalon role. */ 077 public static final String ROLE = OdfPageHandler.class.getName(); 078 079 /** First level metadata name. */ 080 public static final String LEVEL1_METADATA_NAME = "firstLevel"; 081 082 /** Second level metadata name. */ 083 public static final String LEVEL2_METADATA_NAME = "secondLevel"; 084 085 /** Catalog metadata name. */ 086 public static final String CATALOG_METADATA_NAME = "odf-root-catalog"; 087 088 /** The default level 1 metadata. */ 089 protected static final String DEFAULT_LEVEL1_METADATA = "degree"; 090 091 /** The default level 2 metadata. */ 092 protected static final String DEFAULT_LEVEL2_METADATA = "domain"; 093 094 /** Content types that are not eligible for first and second level */ 095 // See ODF-1115 Exclude the mentions enumerator from the list : 096 protected static final List<String> NON_ELIGIBLE_CTYPES_FOR_LEVEL = Arrays.asList("org.ametys.plugins.odf.Content.programItem", "odf-enumeration.Mention"); 097 098 /** The ametys object resolver. */ 099 protected AmetysObjectResolver _resolver; 100 101 /** The i18n utils. */ 102 protected I18nUtils _i18nUtils; 103 104 /** The content type extension point. */ 105 protected ContentTypeExtensionPoint _cTypeEP; 106 107 /** The ODF Catalog enumeration */ 108 protected CatalogsManager _catalogsManager; 109 110 /** The workspace selector. */ 111 protected WorkspaceSelector _workspaceSelector; 112 113 /** The ODF root pages, indexed by workspace, site and sitemap name. */ 114 protected Map<String, Map<String, Map<String, Set<String>>>> _odfRootPages; 115 116 /** For each site, indicate if an ODF root is present. */ 117 protected Map<String, Map<String, Boolean>> _hasOdfRoot; 118 119 /** Avalon service manager */ 120 protected ServiceManager _manager; 121 122 /** Restriction manager */ 123 protected OdfProgramRestrictionManager _odfRestrictionsManager; 124 125 /** Content types helper */ 126 protected ContentTypesHelper _contentTypesHelper; 127 128 /** Content helper */ 129 protected ContentHelper _contentHelper; 130 131 /** Odf reference table helper */ 132 protected OdfReferenceTableHelper _odfReferenceTableHelper; 133 134 /** Root orgunit provider */ 135 protected RootOrgUnitProvider _orgUnitProvider; 136 137 /** Root orgunit provider */ 138 protected OdfClassificationHandler _odfClassificationHandler; 139 140 @Override 141 public void service(ServiceManager serviceManager) throws ServiceException 142 { 143 _manager = serviceManager; 144 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 145 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 146 _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 147 _workspaceSelector = (WorkspaceSelector) serviceManager.lookup(WorkspaceSelector.ROLE); 148 _catalogsManager = (CatalogsManager) serviceManager.lookup(CatalogsManager.ROLE); 149 _odfRestrictionsManager = (OdfProgramRestrictionManager) serviceManager.lookup(OdfProgramRestrictionManager.ROLE); 150 _contentTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 151 _contentHelper = (ContentHelper) serviceManager.lookup(ContentHelper.ROLE); 152 _odfReferenceTableHelper = (OdfReferenceTableHelper) serviceManager.lookup(OdfReferenceTableHelper.ROLE); 153 _orgUnitProvider = (RootOrgUnitProvider) serviceManager.lookup(RootOrgUnitProvider.ROLE); 154 _odfClassificationHandler = (OdfClassificationHandler) serviceManager.lookup(OdfClassificationHandler.ROLE); 155 } 156 157 @Override 158 public void initialize() throws Exception 159 { 160 _odfRootPages = new HashMap<>(); 161 _hasOdfRoot = new HashMap<>(); 162 } 163 164 /** 165 * Get the first ODF root page. 166 * @param siteName The site name 167 * @param sitemapName The sitemap's name 168 * @return a ODF root page or null if not found. 169 * @throws AmetysRepositoryException if an error occurs 170 */ 171 public Page getOdfRootPage(String siteName, String sitemapName) throws AmetysRepositoryException 172 { 173 Set<Page> rootPages = getOdfRootPages(siteName, sitemapName); 174 return rootPages.isEmpty() ? null : rootPages.iterator().next(); 175 } 176 177 /** 178 * Get ODF root page of a specific catalog. 179 * @param siteName The site name 180 * @param sitemapName The sitemap name 181 * @param catalogName The catalog name 182 * @return the ODF root page or null if not found. 183 * @throws AmetysRepositoryException if an error occurs 184 */ 185 public Page getOdfRootPage(String siteName, String sitemapName, String catalogName) throws AmetysRepositoryException 186 { 187 String catalogToCompare = catalogName != null ? catalogName : ""; 188 189 for (Page odfRootPage : getOdfRootPages(siteName, sitemapName)) 190 { 191 if (catalogToCompare.equals(getCatalog(odfRootPage))) 192 { 193 return odfRootPage; 194 } 195 } 196 197 return null; 198 } 199 200 /** 201 * Get the id of ODF root pages 202 * @param siteName The site name 203 * @param sitemapName The sitemap name 204 * @return The ids of ODF root pages 205 * @throws AmetysRepositoryException if an error occurs. 206 */ 207 @Callable 208 public List<String> getOdfRootPageIds(String siteName, String sitemapName) throws AmetysRepositoryException 209 { 210 Set<Page> pages = getOdfRootPages(siteName, sitemapName); 211 return pages.stream().map(p -> p.getId()).collect(Collectors.toList()); 212 } 213 214 /** 215 * Get the ODF root pages. 216 * @param siteName the current site. 217 * @param sitemapName the current sitemap/language. 218 * @return the ODF root pages 219 * @throws AmetysRepositoryException if an error occurs. 220 */ 221 public Set<Page> getOdfRootPages(String siteName, String sitemapName) throws AmetysRepositoryException 222 { 223 Set<Page> rootPages = new HashSet<>(); 224 225 String workspace = _workspaceSelector.getWorkspace(); 226 227 Map<String, Map<String, Set<String>>> wspOdfRootPages = null; 228 if (_odfRootPages.containsKey(workspace)) 229 { 230 wspOdfRootPages = _odfRootPages.get(workspace); 231 } 232 else 233 { 234 wspOdfRootPages = new HashMap<>(); 235 _odfRootPages.put(workspace, wspOdfRootPages); 236 } 237 238 Map<String, Set<String>> siteOdfRootPages = null; 239 240 if (wspOdfRootPages.containsKey(siteName)) 241 { 242 siteOdfRootPages = wspOdfRootPages.get(siteName); 243 } 244 else 245 { 246 siteOdfRootPages = new HashMap<>(); 247 wspOdfRootPages.put(siteName, siteOdfRootPages); 248 } 249 250 if (siteOdfRootPages.containsKey(sitemapName)) 251 { 252 Set<String> odfRootPageIds = siteOdfRootPages.get(sitemapName); 253 if (odfRootPageIds != null) 254 { 255 for (String pageId : odfRootPageIds) 256 { 257 rootPages.add((Page) _resolver.resolveById(pageId)); 258 } 259 } 260 } 261 else 262 { 263 rootPages = _getOdfRootPages(siteName, sitemapName); 264 Set<String> odfRootPageIds = new HashSet<>(); 265 for (Page rootPage : rootPages) 266 { 267 odfRootPageIds.add(rootPage.getId()); 268 } 269 siteOdfRootPages.put(sitemapName, odfRootPageIds); 270 } 271 272 return rootPages; 273 } 274 275 /** 276 * Test if the given site has at least one sitemap with an odf root page. 277 * @param site the site to test. 278 * @return true if the site has at least one sitemap with an odf root page, false otherwise. 279 */ 280 public boolean hasOdfRootPage(Site site) 281 { 282 boolean hasOneRoot = false; 283 284 String workspace = _workspaceSelector.getWorkspace(); 285 String siteName = site.getName(); 286 287 Map<String, Boolean> wspHasOneRoot = null; 288 if (_hasOdfRoot.containsKey(workspace)) 289 { 290 wspHasOneRoot = _hasOdfRoot.get(workspace); 291 } 292 else 293 { 294 wspHasOneRoot = new HashMap<>(); 295 _hasOdfRoot.put(workspace, wspHasOneRoot); 296 } 297 298 299 if (wspHasOneRoot.containsKey(siteName)) 300 { 301 hasOneRoot = wspHasOneRoot.get(siteName); 302 } 303 else 304 { 305 Iterator<Sitemap> sitemaps = site.getSitemaps().iterator(); 306 307 while (sitemaps.hasNext() && !hasOneRoot) 308 { 309 String sitemapName = sitemaps.next().getName(); 310 311 if (!getOdfRootPages(site.getName(), sitemapName).isEmpty()) 312 { 313 hasOneRoot = true; 314 } 315 } 316 317 wspHasOneRoot.put(siteName, hasOneRoot); 318 } 319 320 return hasOneRoot; 321 } 322 323 /** 324 * Determines if the program is part of the site restrictions 325 * @param rootPage The ODF root page 326 * @param program The program 327 * @return <code>true</code> the program is part of the site restrictions 328 */ 329 public boolean isValidRestriction(Page rootPage, Program program) 330 { 331 // Check catalog 332 if (!program.getCatalog().equals(getCatalog(rootPage))) 333 { 334 return false; 335 } 336 337 // Check language 338 if (!program.getLanguage().equals(rootPage.getSitemapName())) 339 { 340 return false; 341 } 342 343 // Check site restrictions 344 OdfProgramRestriction restriction = _odfRestrictionsManager.getRestriction(rootPage); 345 if (restriction != null) 346 { 347 return restriction.contains(program); 348 } 349 350 return true; 351 } 352 353 /** 354 * Clear the ODF root page cache. 355 */ 356 public void clearRootCache() 357 { 358 _odfRootPages = new HashMap<>(); 359 _hasOdfRoot = new HashMap<>(); 360 } 361 362 /** 363 * Clear the ODF root page cache for a given site and language. 364 * @param siteName the current site. 365 * @param sitemapName the current sitemap/language. 366 */ 367 public void clearRootCache(String siteName, String sitemapName) 368 { 369 if (_odfRootPages.containsKey(siteName)) 370 { 371 _odfRootPages.get(siteName).remove(sitemapName); 372 } 373 374 _hasOdfRoot.remove(siteName); 375 } 376 377 /** 378 * Determines if the page is a ODF root page 379 * @param page The page to test 380 * @return true if the page is a ODF root page 381 */ 382 public boolean isODFRootPage (Page page) 383 { 384 if (page instanceof JCRAmetysObject) 385 { 386 try 387 { 388 JCRAmetysObject jcrPage = (JCRAmetysObject) page; 389 Node node = jcrPage.getNode(); 390 391 if (node.hasProperty(AmetysObjectResolver.VIRTUAL_PROPERTY)) 392 { 393 Value[] values = node.getProperty(AmetysObjectResolver.VIRTUAL_PROPERTY).getValues(); 394 395 boolean hasValue = false; 396 for (int i = 0; i < values.length && !hasValue; i++) 397 { 398 hasValue = FirstLevelPageFactory.class.getName().equals(values[i].getString()); 399 } 400 401 return hasValue; 402 } 403 else 404 { 405 return false; 406 } 407 } 408 catch (RepositoryException e) 409 { 410 return false; 411 } 412 } 413 414 return false; 415 416 } 417 418 /** 419 * Get the ODF root page. 420 * @param siteName the current site. 421 * @param sitemapName the current sitemap/language. 422 * @return the ODF root page or null if not found. 423 * @throws AmetysRepositoryException if an error occurs. 424 */ 425 protected Page _getOdfRootPage(String siteName, String sitemapName) throws AmetysRepositoryException 426 { 427 Expression expression = new VirtualFactoryExpression(FirstLevelPageFactory.class.getName()); 428 String query = PageQueryHelper.getPageXPathQuery(siteName, sitemapName, null, expression, null); 429 430 AmetysObjectIterable<Page> pages = _resolver.query(query); 431 Page page = pages.stream().findFirst().orElse(null); 432 433 return page; 434 } 435 436 /** 437 * Get the ODF root page. 438 * @param siteName the current site. 439 * @param sitemapName the current sitemap/language. 440 * @return the ODF root page or null if not found. 441 * @throws AmetysRepositoryException if an error occurs. 442 */ 443 protected Set<Page> _getOdfRootPages(String siteName, String sitemapName) throws AmetysRepositoryException 444 { 445 Expression expression = new VirtualFactoryExpression(FirstLevelPageFactory.class.getName()); 446 String query = PageQueryHelper.getPageXPathQuery(siteName, sitemapName, null, expression, null); 447 448 return _resolver.<Page>query(query).stream().collect(Collectors.toSet()); 449 } 450 451 /** 452 * Get the catalog value of the ODF root page 453 * @param rootPage The ODF root page 454 * @return the catalog value 455 */ 456 public String getCatalog (Page rootPage) 457 { 458 return rootPage.getMetadataHolder().getString(CATALOG_METADATA_NAME, ""); 459 } 460 461 /** 462 * Get the first level metadata name. 463 * @param siteName the site name. 464 * @param sitemapName the sitemap name. 465 * @param catalog the current selected catalog. 466 * @return the first level metadata name. 467 */ 468 public String getLevel1Metadata(String siteName, String sitemapName, String catalog) 469 { 470 Page rootPage = getOdfRootPage(siteName, sitemapName, catalog); 471 472 return getLevel1Metadata(rootPage); 473 } 474 475 /** 476 * Get the first level metadata name. 477 * @param rootPage the ODF root page. 478 * @return the first level metadata name. 479 */ 480 public String getLevel1Metadata(Page rootPage) 481 { 482 return rootPage.getMetadataHolder().getString(LEVEL1_METADATA_NAME, DEFAULT_LEVEL1_METADATA); 483 } 484 485 /** 486 * Get the second level metadata name. 487 * @param siteName the site name. 488 * @param sitemapName the sitemap name. 489 * @param catalog the current selected catalog. 490 * @return the second level metadata name. 491 */ 492 public String getLevel2Metadata(String siteName, String sitemapName, String catalog) 493 { 494 Page rootPage = getOdfRootPage(siteName, sitemapName, catalog); 495 496 return getLevel2Metadata(rootPage); 497 } 498 499 /** 500 * Get the second level metadata name. 501 * @param rootPage the ODF root page. 502 * @return the second level metadata name. 503 */ 504 public String getLevel2Metadata(Page rootPage) 505 { 506 return rootPage.getMetadataHolder().getString(LEVEL2_METADATA_NAME, DEFAULT_LEVEL2_METADATA); 507 } 508 509 /** 510 * Get the first level metadata values (with translated label). 511 * @param siteName the site name. 512 * @param sitemapName the sitemap name. 513 * @param catalog the current selected catalog. 514 * @return the first level metadata values. 515 */ 516 public Map<String, String> getLevel1Values(String siteName, String sitemapName, String catalog) 517 { 518 Page rootPage = getOdfRootPage(siteName, sitemapName, catalog); 519 520 return getLevel1Values(rootPage); 521 } 522 523 /** 524 * Get the level value of a program by extracting and transforming the raw program value at the desired metadata path 525 * @param program The program 526 * @param levelMetaPath The desired metadata path that represent a level 527 * @return The final level value 528 */ 529 public String getProgramLevelValue(Program program, String levelMetaPath) 530 { 531 List<String> programLevelValue = _odfClassificationHandler.getProgramLevelValues(program, levelMetaPath); 532 return programLevelValue.isEmpty() ? null : programLevelValue.get(0); 533 } 534 535 /** 536 * Get the first level value of a program by extracting and transforming the raw program value 537 * @param rootPage The root page 538 * @param program The program 539 * @return The final level value or <code>null</code> if not found 540 */ 541 public String getProgramLevel1Value(Page rootPage, Program program) 542 { 543 List<String> programLevelValue = _odfClassificationHandler.getProgramLevelValues(program, getLevel1Metadata(rootPage)); 544 return programLevelValue.isEmpty() ? null : programLevelValue.get(0); 545 } 546 547 /** 548 * Get the second level value of a program by extracting and transforming the raw program value 549 * @param rootPage The root page 550 * @param program The program 551 * @return The final level value or <code>null</code> if not found 552 */ 553 public String getProgramLevel2Value(Page rootPage, Program program) 554 { 555 List<String> programLevelValue = _odfClassificationHandler.getProgramLevelValues(program, getLevel2Metadata(rootPage)); 556 return programLevelValue.isEmpty() ? null : programLevelValue.get(0); 557 } 558 559 /** 560 * Get the name of the page of first level for a given program 561 * @param rootPage The ODF root page 562 * @param program The program 563 * @return The page's name 564 */ 565 public String getLevel1PageName(Page rootPage, Program program) 566 { 567 String value = getProgramLevel1Value(rootPage, program); 568 return value != null ? FilterNameHelper.filterName(value) + "-" + encodeLevelValue(value) : ""; 569 } 570 571 /** 572 * Get the name of the page of second level for a given program 573 * @param rootPage The ODF root page 574 * @param program The program 575 * @return The page's name 576 */ 577 public String getLevel2PageName(Page rootPage, Program program) 578 { 579 String value = getProgramLevel2Value(rootPage, program); 580 return value != null ? FilterNameHelper.filterName(value) + "-" + encodeLevelValue(value) : ""; 581 } 582 583 /** 584 * Get the orgunit identifier given an uai code 585 * @param rootPage Odf root page 586 * @param uaiCode The uai code 587 * @return The orgunit id or null if not found 588 */ 589 public String getOrgunitIdFromUaiCode(Page rootPage, String uaiCode) 590 { 591 return _odfClassificationHandler.getOrgunitIdFromUaiCode(rootPage.getSitemapName(), uaiCode); 592 } 593 594 /** 595 * Get the programs available for a ODF root page, taking account the site's restrictions 596 * @param rootPage The ODF root page 597 * @param level1 filters results with a level1 value. Can be null. 598 * @param level2 filters results with a level2 value. Can be null. 599 * 600 * @param programName expected program name. Can be null. 601 * @return an iterator over resulting programs 602 */ 603 public AmetysObjectIterable<Program> getProgramsWithRestrictions(Page rootPage, String level1, String level2, String programName) 604 { 605 return getProgramsWithRestrictions(rootPage, getLevel1Metadata(rootPage), level1, getLevel2Metadata(rootPage), level2, programName); 606 } 607 608 /** 609 * Get the programs available for a ODF root page, taking account the site's restrictions 610 * @param rootPage The ODF root page 611 * @param level1Metadata metadata name for first level 612 * @param level1 filters results with a level1 value. Can be null. 613 * @param level2Metadata metadata name for second level 614 * @param level2 filters results with a level2 value. Can be null. 615 * 616 * @param programName expected program name. Can be null. 617 * @return an iterator over resulting programs 618 */ 619 public AmetysObjectIterable<Program> getProgramsWithRestrictions(Page rootPage, String level1Metadata, String level1, String level2Metadata, String level2, String programName) 620 { 621 OdfProgramRestriction restriction = _odfRestrictionsManager.getRestriction(rootPage); 622 return _odfClassificationHandler.getPrograms(getCatalog(rootPage), rootPage.getSitemapName(), level1Metadata, level1, level2Metadata, level2, programName, restriction == null ? null : ImmutableList.of(restriction.getExpression())); 623 } 624 625 /** 626 * Get the first level metadata values (with translated label). 627 * @param rootPage the ODF root page. 628 * @return the first level metadata values. 629 */ 630 public Map<String, String> getLevel1Values(Page rootPage) 631 { 632 return _odfClassificationHandler.getLevelValues(getLevel1Metadata(rootPage), rootPage.getSitemapName()); 633 } 634 635 /** 636 * Get the second level metadata values (with translated label). 637 * @param siteName the site name. 638 * @param sitemapName the sitemap name. 639 * @param catalog the current selected catalog. 640 * @return the second level metadata values. 641 */ 642 public Map<String, String> getLevel2Values(String siteName, String sitemapName, String catalog) 643 { 644 Page rootPage = getOdfRootPage(siteName, sitemapName, catalog); 645 646 return getLevel2Values(rootPage); 647 } 648 649 /** 650 * Get the second level metadata values (with translated label). 651 * @param rootPage the ODF root page. 652 * @return the second level metadata values. 653 */ 654 public Map<String, String> getLevel2Values(Page rootPage) 655 { 656 return _odfClassificationHandler.getLevelValues(getLevel2Metadata(rootPage), rootPage.getSitemapName()); 657 } 658 659 /** 660 * Encode level value to be use into a URI. 661 * Double-encode characters ':', '-' and '/'. 662 * @param value The raw value 663 * @return the encoded value 664 */ 665 public String encodeLevelValue (String value) 666 { 667 return _odfClassificationHandler.encodeLevelValue(value); 668 } 669 670 /** 671 * Decode level value used in a URI 672 * @param value The encoded value 673 * @return the decoded value 674 */ 675 public String decodeLevelValue (String value) 676 { 677 return _odfClassificationHandler.decodeLevelValue(value); 678 } 679 680 /** 681 * Returns the page's name of a {@link ProgramItem}. 682 * Only {@link AbstractProgram} and {@link Course} can have a page. 683 * @param item The program item 684 * @return The page's name 685 * @throws IllegalArgumentException if the program item is not a {@link AbstractProgram} nor a {@link Course}. 686 */ 687 public String getPageName (ProgramItem item) 688 { 689 if (item instanceof AbstractProgram) 690 { 691 // E.g: licence-lea-anglais-allemand-program-fruai3182988abcde07 692 return FilterNameHelper.filterName(((AbstractProgram) item).getTitle()) + "-" + item.getName(); 693 } 694 else if (item instanceof Course) 695 { 696 // E.g: langue-anglaise-1-fruai3182988acoh6yp1p98 697 return FilterNameHelper.filterName(((Course) item).getTitle()) + "-" + item.getCode(); 698 } 699 else 700 { 701 throw new IllegalArgumentException("Illegal program item : no page can be associated for a program item of type " + item.getClass().getName()); 702 } 703 } 704 705 /** 706 * Get the eligible enumerated metadata for ODF page level 707 * @return the eligible metadata definition 708 */ 709 public Map<String, MetadataDefinition> getEligibleMetadataForLevel() 710 { 711 return _odfClassificationHandler.getEligibleMetadataForLevel(); 712 } 713 714 /** 715 * Get the ODF catalogs 716 * @return the ODF catalogs 717 */ 718 public Map<String, I18nizableText> getCatalogs() 719 { 720 return _odfClassificationHandler.getCatalogs(); 721 } 722 723 /** 724 * Get the enumerated metadata definition for the given content type. 725 * Metadata with enumerator or content metadata are considered as enumrated 726 * @param programContentTypeId The content type's id 727 * @param allowMultiple <code>true</code> true to allow multiple metadata 728 * @return The definition of enumerated metadata 729 */ 730 public Map<String, MetadataDefinition> getEnumeratedMetadata(String programContentTypeId, boolean allowMultiple) 731 { 732 return _odfClassificationHandler.getEnumeratedMetadata(programContentTypeId, allowMultiple); 733 } 734}