001/* 002 * Copyright 2011 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.enumeration; 017 018import java.util.HashMap; 019import java.util.HashSet; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024import java.util.stream.Collectors; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang3.StringUtils; 033import org.xml.sax.ContentHandler; 034import org.xml.sax.SAXException; 035 036import org.ametys.cms.contenttype.AbstractMetadataSetElement; 037import org.ametys.cms.contenttype.ContentConstants; 038import org.ametys.cms.contenttype.ContentType; 039import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 040import org.ametys.cms.contenttype.ContentTypesHelper; 041import org.ametys.cms.contenttype.MetadataDefinition; 042import org.ametys.cms.contenttype.MetadataDefinitionHolder; 043import org.ametys.cms.contenttype.MetadataDefinitionReference; 044import org.ametys.cms.contenttype.MetadataSet; 045import org.ametys.cms.contenttype.MetadataType; 046import org.ametys.cms.contenttype.RepeaterDefinition; 047import org.ametys.cms.repository.Content; 048import org.ametys.cms.repository.ContentQueryHelper; 049import org.ametys.cms.repository.ContentTypeExpression; 050import org.ametys.core.ui.Callable; 051import org.ametys.plugins.repository.AmetysObjectIterable; 052import org.ametys.plugins.repository.AmetysObjectIterator; 053import org.ametys.plugins.repository.AmetysObjectResolver; 054import org.ametys.plugins.repository.UnknownAmetysObjectException; 055import org.ametys.plugins.repository.query.expression.AndExpression; 056import org.ametys.plugins.repository.query.expression.Expression.Operator; 057import org.ametys.plugins.repository.query.expression.StringExpression; 058import org.ametys.runtime.config.Config; 059import org.ametys.runtime.plugin.component.AbstractLogEnabled; 060 061/** 062 * This component handles ODF reference tables 063 * 064 */ 065public class OdfReferenceTableHelper extends AbstractLogEnabled implements Component, Serviceable 066{ 067 /** Avalon Role */ 068 public static final String ROLE = OdfReferenceTableHelper.class.getName(); 069 070 /** Abstract table ref */ 071 public static final String ABSTRACT_TABLE_REF = "odf-enumeration.AbstractTableRef"; 072 /** Domain */ 073 public static final String DOMAIN = "odf-enumeration.Domain"; 074 /** Degree */ 075 public static final String DEGREE = "odf-enumeration.Degree"; 076 /** Level */ 077 public static final String LEVEL = "odf-enumeration.Level"; 078 /** Program type. */ 079 public static final String PROGRAM_TYPE = "odf-enumeration.ProgramType"; 080 /** Form of teaching */ 081 public static final String FORMOFTEACHING_METHOD = "odf-enumeration.FormofteachingMethod"; 082 /** Orgnization of teaching */ 083 public static final String FORMOFTEACHING_ORG = "odf-enumeration.FormofteachingOrg"; 084 /** Teaching method */ 085 public static final String TEACHING_ACTIVITY = "odf-enumeration.TeachingActivity"; 086 /** Type of training course */ 087 public static final String INTERNSHIP = "odf-enumeration.Internship"; 088 /** Distance learning modalities */ 089 public static final String DISTANCE_LEARNING_MODALITIES = "odf-enumeration.DistanceLearningModalities"; 090 /** Place */ 091 public static final String PLACE = "odf-enumeration.Place"; 092 /** Teaching term. */ 093 public static final String TEACHING_TERM = "odf-enumeration.TeachingTerm"; 094 /** Time slot */ 095 public static final String TIME_SLOT = "odf-enumeration.TimeSlot"; 096 /** Code ROME */ 097 public static final String CODE_ROME = "odf-enumeration.CodeRome"; 098 /** Code ERASMUS */ 099 public static final String CODE_ERASMUS = "odf-enumeration.CodeErasmus"; 100 /** Code DGESIP */ 101 public static final String CODE_DGESIP = "odf-enumeration.CodeDgesip"; 102 /** Code SISE */ 103 public static final String CODE_SISE = "odf-enumeration.CodeSise"; 104 /** Code Cite97 */ 105 public static final String CODE_CITE97 = "odf-enumeration.CodeCite97"; 106 /** Code FAP */ 107 public static final String CODE_FAP = "odf-enumeration.CodeFap"; 108 /** Code NSF */ 109 public static final String CODE_NSF = "odf-enumeration.CodeNsf"; 110 /** RNCP level */ 111 public static final String RNCP_LEVEL = "odf-enumeration.RncpLevel"; 112 /** Join orgunit*/ 113 public static final String JOIN_ORGUNIT = "odf-enumeration.JoinOrgunit"; 114 /** Mention licence */ 115 public static final String ABSTRACT_MENTION = "odf-enumeration.Mention"; 116 /** Mention licence */ 117 public static final String MENTION_LICENCE = "odf-enumeration.MentionLicence"; 118 /** Mention licence pro */ 119 public static final String MENTION_LICENCEPRO = "odf-enumeration.MentionLicencepro"; 120 /** Mention master */ 121 public static final String MENTION_MASTER = "odf-enumeration.MentionMaster"; 122 /** Abstract table ref for category */ 123 public static final String ABSTRACT_TABLE_REF_CATEGORY = "odf-enumeration.AbstractTableRefCategory"; 124 /** Apprenticeship contract */ 125 public static final String APPRENTICESHIP_CONTRACT = "odf-enumeration.ApprenticeshipContract"; 126 /** Available certification */ 127 public static final String AVAILABLE_CERTIFICATION = "odf-enumeration.AvailableCertification"; 128 /** Campus */ 129 public static final String CAMPUS = "odf-enumeration.Campus"; 130 /** Category for code Erasmus */ 131 public static final String CODE_ERASMUS_CATEGORY = "odf-enumeration.CodeErasmusCategory"; 132 /** Category for code FAP */ 133 public static final String CODE_FAP_CATEGORY = "odf-enumeration.CodeFapCategory"; 134 /** Nature of container */ 135 public static final String CONTAINER_NATURE = "odf-enumeration.ContainerNature"; 136 /** Nature of course */ 137 public static final String COURSE_NATURE = "odf-enumeration.CourseNature"; 138 /** Discipline */ 139 public static final String DISCIPLINE = "odf-enumeration.Discipline"; 140 /** Duration */ 141 public static final String DURATION = "odf-enumeration.Duration"; 142 /** ECTS */ 143 public static final String ECTS = "odf-enumeration.Ects"; 144 /** Foreign place */ 145 public static final String FOREIGN_PLACE = "odf-enumeration.ForeignPlace"; 146 /** International education */ 147 public static final String INTERNATIONAL_EDUCATION = "odf-enumeration.InternationalEducation"; 148 /** Language */ 149 public static final String LANGUAGE = "odf-enumeration.Language"; 150 /** OrgUnit type */ 151 public static final String ORGUNIT_TYPE = "odf-enumeration.OrgUnitType"; 152 /** Period */ 153 public static final String PERIOD = "odf-enumeration.Period"; 154 /** Person role */ 155 public static final String PERSON_ROLE = "odf-enumeration.PersonRole"; 156 /** Program field */ 157 public static final String PROGRAM_FIELD = "odf-enumeration.ProgramField"; 158 /** Sectors */ 159 public static final String SECTORS = "odf-enumeration.Sectors"; 160 /** Nature of course part */ 161 public static final String ENSEIGNEMENT_NATURE = "odf-enumeration.EnseignementNature"; 162 /** Category of nature of course part */ 163 public static final String ENSEIGNEMENT_NATURE_CATEGORY = "odf-enumeration.EnseignementNatureCategory"; 164 /** Skill */ 165 public static final String SKILL = "odf-enumeration.Skill"; 166 /** Skill set */ 167 public static final String SKILL_SET = "odf-enumeration.SkillSet"; 168 169 private AmetysObjectResolver _resolver; 170 171 private ContentTypeExtensionPoint _cTypeEP; 172 173 private ContentTypesHelper _cTypeHelper; 174 175 @Override 176 public void service(ServiceManager manager) throws ServiceException 177 { 178 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 179 _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 180 _cTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 181 } 182 183 /** 184 * Determines if the content type is a ODF table reference 185 * @param cTypeId The id of content type 186 * @return true if the content type is a ODF table reference 187 */ 188 public boolean isTableReference(String cTypeId) 189 { 190 return _cTypeHelper.getAncestors(cTypeId).contains(ABSTRACT_TABLE_REF); 191 } 192 193 /** 194 * Determines if the content is an entry of a ODF table reference 195 * @param content The content 196 * @return <code>true</code> if the content is an entry of a ODF table reference 197 */ 198 public boolean isTableReferenceEntry(Content content) 199 { 200 String[] cTypeIds = content.getTypes(); 201 for (String cTypeId : cTypeIds) 202 { 203 if (isTableReference(cTypeId)) 204 { 205 return true; 206 } 207 } 208 return false; 209 } 210 211 /** 212 * Get the id of table references 213 * @return The content type's id 214 */ 215 public Set<String> getTableReferenceIds() 216 { 217 Set<String> tableRefIds = new HashSet<>(); 218 219 for (String cTypeId : _cTypeEP.getExtensionsIds()) 220 { 221 if (_cTypeHelper.getAncestors(cTypeId).contains(ABSTRACT_TABLE_REF)) 222 { 223 tableRefIds.add(cTypeId); 224 } 225 } 226 return tableRefIds; 227 } 228 229 /** 230 * Get the metadata definitions for table references for a given content type 231 * @param cTypeId The id of content type 232 * @return The metadata definitions for table references 233 */ 234 public Map<String, MetadataDefinition> getTableRefMetadataDefinition(String cTypeId) 235 { 236 ContentType cType = _cTypeEP.getExtension(cTypeId); 237 return _getTableRefMetadata(cType, ""); 238 } 239 240 /** 241 * Get the metadata definitions for table references for a given content type and a metadata set 242 * @param cTypeId The id of content type 243 * @param medatataSetName the name of the metadata set. Cannot be null. 244 * @param isEditionMetadataSet true if the metadata set is for edition. 245 * @return The metadata definitions for table references 246 */ 247 public Map<String, MetadataDefinition> getTableRefMetadataDefinition(String cTypeId, String medatataSetName, boolean isEditionMetadataSet) 248 { 249 ContentType cType = _cTypeEP.getExtension(cTypeId); 250 251 MetadataSet metadataSet = isEditionMetadataSet ? cType.getMetadataSetForEdition(medatataSetName) : cType.getMetadataSetForView(medatataSetName); 252 return _getTableRefMetadata(metadataSet, cType, ""); 253 } 254 255 private Map<String, MetadataDefinition> _getTableRefMetadata(MetadataDefinitionHolder parentMetaDef, String prefix) 256 { 257 Map<String, MetadataDefinition> tableRefMetadata = new LinkedHashMap<>(); 258 259 Set<String> metadataNames = parentMetaDef.getMetadataNames(); 260 for (String metadataName : metadataNames) 261 { 262 MetadataDefinition metaDef = parentMetaDef.getMetadataDefinition(metadataName); 263 MetadataType type = metaDef.getType(); 264 265 switch (type) 266 { 267 case COMPOSITE: 268 if (!(metaDef instanceof RepeaterDefinition)) 269 { 270 // enumerated metadata in repeaters are not supported 271 tableRefMetadata.putAll(_getTableRefMetadata(metaDef, prefix + metadataName + ContentConstants.METADATA_PATH_SEPARATOR)); 272 } 273 break; 274 275 case CONTENT: 276 if (isTableReference(metaDef.getContentType())) 277 { 278 tableRefMetadata.put(prefix + metadataName, metaDef); 279 } 280 break; 281 282 default: 283 break; 284 } 285 } 286 287 return tableRefMetadata; 288 } 289 290 private Map<String, MetadataDefinition> _getTableRefMetadata (AbstractMetadataSetElement element, MetadataDefinitionHolder parentMetaDef, String prefix) 291 { 292 Map<String, MetadataDefinition> tableRefMetadata = new LinkedHashMap<>(); 293 294 for (AbstractMetadataSetElement subElement : element.getElements()) 295 { 296 if (subElement instanceof MetadataDefinitionReference) 297 { 298 MetadataDefinitionReference metadataDefRef = (MetadataDefinitionReference) subElement; 299 String metadataName = metadataDefRef.getMetadataName(); 300 MetadataDefinition metaDef = parentMetaDef.getMetadataDefinition(metadataName); 301 302 MetadataType type = metaDef.getType(); 303 304 switch (type) 305 { 306 case COMPOSITE: 307 if (!(metaDef instanceof RepeaterDefinition)) 308 { 309 // table ref metadata in repeaters are not supported 310 tableRefMetadata.putAll(_getTableRefMetadata(subElement, metaDef, prefix + metadataName + ContentConstants.METADATA_PATH_SEPARATOR)); 311 } 312 break; 313 314 case CONTENT: 315 if (isTableReference(metaDef.getContentType())) 316 { 317 tableRefMetadata.put(prefix + metadataName, metaDef); 318 } 319 break; 320 321 default: 322 break; 323 } 324 } 325 } 326 return tableRefMetadata; 327 } 328 329 /** 330 * Get the content type for mention for this degree 331 * @param degreeIds The ids of degrees 332 * @return A map with the id of content type or null if there is no mention for this degree 333 */ 334 @Callable 335 public Map<String, String> getMentionContentTypes(List<String> degreeIds) 336 { 337 Map<String, String> mentionTypes = new HashMap<>(); 338 for (String degreeId : degreeIds) 339 { 340 mentionTypes.put(degreeId, getMentionForDegree(degreeId)); 341 } 342 return mentionTypes; 343 } 344 345 /** 346 * Get the mention for a given degree. 347 * @param degreeId The degree ID 348 * @return The associated mention reference table, null if there isn't 349 */ 350 public String getMentionForDegree(String degreeId) 351 { 352 try 353 { 354 Content content = _resolver.resolveById(degreeId); 355 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(content); 356 357 String degreeCode = entry.getCode(); 358 359 if (degreeCode.equals(Config.getInstance().getValue("odf.programs.degree.license"))) 360 { 361 return OdfReferenceTableHelper.MENTION_LICENCE; 362 } 363 else if (degreeCode.equals(Config.getInstance().getValue("odf.programs.degree.licensepro"))) 364 { 365 return OdfReferenceTableHelper.MENTION_LICENCEPRO; 366 } 367 else if (degreeCode.equals(Config.getInstance().getValue("odf.programs.degree.master"))) 368 { 369 return OdfReferenceTableHelper.MENTION_MASTER; 370 } 371 } 372 catch (UnknownAmetysObjectException e) 373 { 374 // Nothing to do 375 } 376 return null; 377 } 378 379 /** 380 * Get the CDM-fr value associated with the given code 381 * @param tableRefId The id of content type 382 * @param code The code 383 * @return The CDM-fr value or empty string if not found 384 */ 385 public String getCDMfrValue (String tableRefId, String code) 386 { 387 ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, tableRefId); 388 StringExpression codeExpr = new StringExpression(OdfReferenceTableEntry.METADATA_CODE, Operator.EQ, code); 389 390 String xpathQuery = ContentQueryHelper.getContentXPathQuery(new AndExpression(cTypeExpr, codeExpr)); 391 AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery); 392 AmetysObjectIterator<Content> it = contents.iterator(); 393 394 if (it.hasNext()) 395 { 396 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(it.next()); 397 return entry.getCdmValue(); 398 } 399 400 return ""; 401 } 402 403 /** 404 * Get all items of an enumeration and their label 405 * @param tableRefId The id of content type 406 * @return items of enumeration 407 */ 408 public List<OdfReferenceTableEntry> getItems (String tableRefId) 409 { 410 ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, tableRefId); 411 412 String xpathQuery = ContentQueryHelper.getContentXPathQuery(cTypeExpr); 413 AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery); 414 415 return contents.stream().map(c -> new OdfReferenceTableEntry(c)).collect(Collectors.toList()); 416 } 417 418 /** 419 * Returns the label of an reference table entry 420 * @param contentId The content id 421 * @param lang The requested language of label 422 * @return the item label or <code>null</code> if not found 423 */ 424 public String getItemLabel(String contentId, String lang) 425 { 426 try 427 { 428 Content content = _resolver.resolveById(contentId); 429 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(content); 430 return entry.getLabel(lang); 431 } 432 catch (UnknownAmetysObjectException e) 433 { 434 return null; 435 } 436 } 437 438 /** 439 * Returns the label of an reference table entry 440 * @param tableRefId The id of content type (useless) 441 * @param contentId The content id 442 * @param lang The requested language of label 443 * @return the item label or <code>null</code> if not found 444 * @deprecated Use {@link #getItemLabel(String, String)} instead 445 */ 446 @Deprecated 447 public String getItemLabel (String tableRefId, String contentId, String lang) 448 { 449 return getItemLabel(contentId, lang); 450 } 451 452 /** 453 * Returns the CMD value of an reference table entry 454 * @param contentId The content id 455 * @param returnCodeIfEmpty <code>true</code> to return the code if CDM-fr value is empty 456 * @return the CDM-fr value or empty value if not found 457 */ 458 public String getItemCDMfrValue(String contentId, boolean returnCodeIfEmpty) 459 { 460 if (StringUtils.isEmpty(contentId)) 461 { 462 return ""; 463 } 464 465 Content content = _resolver.resolveById(contentId); 466 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(content); 467 468 String cdmValue = entry.getCdmValue(); 469 470 if (StringUtils.isEmpty(cdmValue) && returnCodeIfEmpty) 471 { 472 return entry.getCode(); 473 } 474 return cdmValue; 475 } 476 477 /** 478 * Returns the CMD value of an reference table entry 479 * @param tableRefId The id of content type (useless) 480 * @param contentId The content id 481 * @param returnCodeIfEmpty <code>true</code> to return the code if CDM-fr value is empty 482 * @return the CDM-fr value or empty value if not found 483 * @deprecated Use {@link #getItemCDMfrValue(String, boolean)} instead 484 */ 485 @Deprecated 486 public String getItemCDMfrValue (String tableRefId, String contentId, boolean returnCodeIfEmpty) 487 { 488 return getItemCDMfrValue(contentId, returnCodeIfEmpty); 489 } 490 491 /** 492 * Returns the code of an reference table entry from its CDM value 493 * @param contentId The id of content 494 * @return the code or empty value if not found 495 */ 496 public String getItemCode(String contentId) 497 { 498 if (StringUtils.isEmpty(contentId)) 499 { 500 return ""; 501 } 502 503 try 504 { 505 Content content = _resolver.resolveById(contentId); 506 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(content); 507 return entry.getCode(); 508 } 509 catch (UnknownAmetysObjectException e) 510 { 511 return ""; 512 } 513 } 514 515 /** 516 * Returns the code of an reference table entry from its CDM value 517 * @param tableRefId The id of content type (useless) 518 * @param contentId The id of content 519 * @return the code or empty value if not found 520 * @deprecated Use {@link #getItemCode(String)} instead 521 */ 522 @Deprecated 523 public String getItemCode (String tableRefId, String contentId) 524 { 525 return getItemCode(contentId); 526 } 527 528 /** 529 * Returns the code of an reference table entry from its CDM value 530 * @param tableRefId The id of content type 531 * @param cdmValue The CDM-fr value 532 * @return the code or <code>null</code> if not found 533 */ 534 public String getItemCodeFromCDM (String tableRefId, String cdmValue) 535 { 536 ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, tableRefId); 537 StringExpression codeExpr = new StringExpression(OdfReferenceTableEntry.METADATA_CDM_VALUE, Operator.EQ, cdmValue); 538 539 String xpathQuery = ContentQueryHelper.getContentXPathQuery(new AndExpression(cTypeExpr, codeExpr)); 540 AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery); 541 AmetysObjectIterator<Content> it = contents.iterator(); 542 543 if (it.hasNext()) 544 { 545 OdfReferenceTableEntry entry = new OdfReferenceTableEntry(it.next()); 546 return entry.getCode(); 547 } 548 return null; 549 } 550 551 /** 552 * Returns the entry of an reference table entry from its cdmValue 553 * @param tableRefId The id of content type 554 * @param cdmValue The CDM-fr value 555 * @return the entry or <code>null</code> if not found 556 */ 557 public OdfReferenceTableEntry getItemFromCDM(String tableRefId, String cdmValue) 558 { 559 ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, tableRefId); 560 StringExpression codeExpr = new StringExpression(OdfReferenceTableEntry.METADATA_CDM_VALUE, Operator.EQ, cdmValue); 561 562 String xpathQuery = ContentQueryHelper.getContentXPathQuery(new AndExpression(cTypeExpr, codeExpr)); 563 564 return _resolver.<Content>query(xpathQuery).stream() 565 .findFirst() 566 .map(OdfReferenceTableEntry::new) 567 .orElse(null); 568 } 569 570 /** 571 * Returns the entry of an reference table entry from its code 572 * @param tableRefId The id of content type 573 * @param code The code 574 * @return the entry or <code>null</code> if not found 575 */ 576 public OdfReferenceTableEntry getItemFromCode(String tableRefId, String code) 577 { 578 ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, tableRefId); 579 StringExpression codeExpr = new StringExpression(OdfReferenceTableEntry.METADATA_CODE, Operator.EQ, code); 580 581 String xpathQuery = ContentQueryHelper.getContentXPathQuery(new AndExpression(cTypeExpr, codeExpr)); 582 583 return _resolver.<Content>query(xpathQuery).stream() 584 .findFirst() 585 .map(OdfReferenceTableEntry::new) 586 .orElse(null); 587 } 588 589 /** 590 * SAX items of a reference table 591 * @param contentHandler The content handler to sax into 592 * @param tableRefId The id of reference table 593 * @throws SAXException if an error occurred while saxing 594 */ 595 public void saxItems (ContentHandler contentHandler, String tableRefId) throws SAXException 596 { 597 _saxItems(contentHandler, new AttributesImpl(), tableRefId); 598 } 599 600 /** 601 * SAX items of a reference table 602 * @param contentHandler the content handler to sax into 603 * @param metaDef the metadata definition 604 * @throws SAXException if an error occurs while saxing 605 */ 606 public void saxItems (ContentHandler contentHandler, MetadataDefinition metaDef) throws SAXException 607 { 608 if (metaDef.getType() == MetadataType.CONTENT) 609 { 610 String cTypeId = metaDef.getContentType(); 611 if (cTypeId.startsWith("odf-enumeration.")) 612 { 613 AttributesImpl attrs = new AttributesImpl(); 614 attrs.addCDATAAttribute("metadataName", metaDef.getName()); 615 attrs.addCDATAAttribute("metadataPath", metaDef.getId()); 616 617 _saxItems(contentHandler, attrs, cTypeId); 618 } 619 } 620 } 621 622 private void _saxItems (ContentHandler contentHandler, AttributesImpl rootAttrs, String tableRefId) throws SAXException 623 { 624 rootAttrs.addCDATAAttribute("contentTypeId", tableRefId); 625 XMLUtils.startElement(contentHandler, "items", rootAttrs); 626 627 List<OdfReferenceTableEntry> entries = getItems(tableRefId); 628 for (OdfReferenceTableEntry entry : entries) 629 { 630 AttributesImpl valueAttrs = new AttributesImpl(); 631 valueAttrs.addCDATAAttribute("id", entry.getId()); 632 valueAttrs.addCDATAAttribute("code", entry.getCode()); 633 valueAttrs.addCDATAAttribute("cdmValue", entry.getCdmValue()); 634 635 String lang = Config.getInstance().getValue("odf.programs.lang"); 636 XMLUtils.createElement(contentHandler, "item", valueAttrs, entry.getLabel(lang)); 637 } 638 639 XMLUtils.endElement(contentHandler, "items"); 640 } 641}