private static void addMaintenanceDocumentCollectionPathToSecurityMappings(
     Map<String, AttributeSecurity> mappings,
     String propertyPathPrefix,
     MaintainableCollectionDefinition collectionDefinition) {
   propertyPathPrefix = propertyPathPrefix + collectionDefinition.getName() + ".";
   String boClassName = collectionDefinition.getBusinessObjectClass().getName();
   for (MaintainableFieldDefinition field : collectionDefinition.getMaintainableFields()) {
     AttributeSecurity attributeSecurity =
         getDataDictionaryService().getAttributeSecurity(boClassName, field.getName());
     if (attributeSecurity != null) {
       mappings.put(propertyPathPrefix + field.getName(), attributeSecurity);
     }
   }
   for (MaintainableCollectionDefinition nestedCollection :
       collectionDefinition.getMaintainableCollections()) {
     addMaintenanceDocumentCollectionPathToSecurityMappings(
         mappings, propertyPathPrefix, nestedCollection);
   }
 }
  public static Map<String, AttributeSecurity> retrievePropertyPathToAttributeSecurityMappings(
      String docTypeName) {
    Map<String, AttributeSecurity> results = new HashMap<String, AttributeSecurity>();
    MaintenanceDocumentEntry entry =
        getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
    String className = entry.getDataObjectClass().getName();

    for (MaintainableSectionDefinition section : entry.getMaintainableSections()) {
      for (MaintainableItemDefinition item : section.getMaintainableItems()) {
        if (item instanceof MaintainableFieldDefinition) {
          MaintainableFieldDefinition field = (MaintainableFieldDefinition) item;
          AttributeSecurity attributeSecurity =
              getDataDictionaryService().getAttributeSecurity(className, field.getName());
          if (attributeSecurity != null) {
            results.put(field.getName(), attributeSecurity);
          }
        } else if (item instanceof MaintainableCollectionDefinition) {
          addMaintenanceDocumentCollectionPathToSecurityMappings(
              results, "", (MaintainableCollectionDefinition) item);
        }
      }
    }
    return results;
  }
  /**
   * Returns the field templates defined in the maint dictionary xml files. Field templates are used
   * in multiple value lookups. When doing a MV lookup on a collection, the returned BOs are not
   * necessarily of the same type as the elements of the collection. Therefore, a means of mapping
   * between the fields for the 2 BOs are necessary. The template attribute of
   * &lt;maintainableField&gt;s contained within &lt;maintainableCollection&gt;s tells us this
   * mapping. Example: a &lt;maintainableField name="collectionAttrib" template="lookupBOAttrib"&gt;
   * definition means that when a list of BOs are returned, the lookupBOAttrib value of the looked
   * up BO will be placed into the collectionAttrib value of the BO added to the collection
   *
   * @param sections the sections of a document
   * @param collectionName the name of a collection. May be a nested collection with indices (e.g.
   *     collA[1].collB)
   * @return
   */
  public static Map<String, String> generateMultipleValueLookupBOTemplate(
      List<MaintainableSectionDefinition> sections, String collectionName) {
    MaintainableCollectionDefinition definition =
        findMaintainableCollectionDefinition(sections, collectionName);
    if (definition == null) {
      return null;
    }
    Map<String, String> template = null;

    for (MaintainableFieldDefinition maintainableField : definition.getMaintainableFields()) {
      String templateString = maintainableField.getTemplate();
      if (StringUtils.isNotBlank(templateString)) {
        if (template == null) {
          template = new HashMap<String, String>();
        }
        template.put(maintainableField.getName(), templateString);
      }
    }
    return template;
  }