docs: private void resolveMapping(
          CmsObject cms,
          CmsXmlContent content,
          String valuePath,
          boolean valueIsSimple,
          int valueIndex,
          Locale valueLocale,
          String originalStringValue)
      throws CmsException {
  
          CmsObject rootCms = createRootCms(cms);
          // get the original VFS file from the content
          CmsFile file = content.getFile();
          if (!valueIsSimple) {
              // no mappings for a nested schema are possible
              // note that the sub-elements of the nested schema ARE mapped by the node visitor,
              // it's just the nested schema value itself that does not support mapping
              return;
          }
  
          List<String> mappings = getMappings(valuePath);
          if (mappings.size() == 0) {
              // nothing to do if we have no mappings at all
              return;
          }
          // create OpenCms user context initialized with "/" as site root to read all siblings
          // read all siblings of the file
          List<CmsResource> siblings = rootCms.readSiblings(
              content.getFile().getRootPath(),
              CmsResourceFilter.IGNORE_EXPIRATION);
  
          Set<CmsResource> urlNameMappingResources = new HashSet<CmsResource>();
          boolean mapToUrlName = false;
          urlNameMappingResources.add(content.getFile());
          // since 7.0.2 multiple mappings are possible
  
          // get the string value of the current node
  
          CmsGalleryNameMacroResolver resolver = new CmsGalleryNameMacroResolver(rootCms, content, valueLocale);
          resolver.setKeepEmptyMacros(true);
          String stringValue = resolver.resolveMacros(originalStringValue);
  
          for (String mapping : mappings) {
  
              // for multiple language mappings, we need to ensure
              // a) all siblings are handled
              // b) only the "right" locale is mapped to a sibling
              if (CmsStringUtil.isNotEmpty(mapping)) {
                  for (int i = (siblings.size() - 1); i >= 0; i--) {
                      // get filename
                      String filename = (siblings.get(i)).getRootPath();
                      if (mapping.startsWith(MAPTO_URLNAME)) {
                          // should be written regardless of whether there is a sibling with the correct locale
                          mapToUrlName = true;
                      }
                      Locale locale = OpenCms.getLocaleManager().getDefaultLocale(rootCms, filename);
                      if (!locale.equals(valueLocale)) {
                          // only map property if the locale fits
                          continue;
                      }
  
                      // make sure the file is locked
                      CmsLock lock = rootCms.getLock(filename);
                      if (lock.isUnlocked()) {
                          rootCms.lockResource(filename);
                      } else if (!lock.isDirectlyOwnedInProjectBy(rootCms)) {
                          rootCms.changeLock(filename);
                      }
  
                      if (mapping.startsWith(MAPTO_PERMISSION) && (valueIndex == 0)) {
  
                          // map value to a permission
                          // example of a mapping: mapto="permission:GROUP:+r+v|GROUP.ALL_OTHERS:|GROUP.Projectmanagers:+r+v+w+c"
  
                          // get permission(s) to set
                          String permissionMappings = mapping.substring(MAPTO_PERMISSION.length());
                          String mainMapping = permissionMappings;
                          Map<String, String> permissionsToSet = new HashMap<String, String>();
  
                          // separate permission to set for element value from other permissions to set
                          int sepIndex = permissionMappings.indexOf('|');
                          if (sepIndex != -1) {
                              mainMapping = permissionMappings.substring(0, sepIndex);
                              permissionMappings = permissionMappings.substring(sepIndex + 1);
                              permissionsToSet = CmsStringUtil.splitAsMap(permissionMappings, "|", ":");
                          }
  
                          // determine principal type and permission string to set
                          String principalType = I_CmsPrincipal.PRINCIPAL_GROUP;
                          String permissionString = mainMapping;
                          sepIndex = mainMapping.indexOf(':');
                          if (sepIndex != -1) {
                              principalType = mainMapping.substring(0, sepIndex);
                              permissionString = mainMapping.substring(sepIndex + 1);
                          }
                          if (permissionString.toLowerCase().indexOf('o') == -1) {
                              permissionString += "+o";
                          }
  
                          // remove all existing permissions from the file
                          List<CmsAccessControlEntry> aces = rootCms.getAccessControlEntries(filename, false);
                          for (Iterator<CmsAccessControlEntry> j = aces.iterator(); j.hasNext();) {
                              CmsAccessControlEntry ace = j.next();
                              if (ace.getPrincipal().equals(CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID)) {
                                  // remove the entry "All others", which has to be treated in a special way
                                  rootCms.rmacc(
                                      filename,
                                      CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_NAME,
                                      CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID.toString());
                              } else {
                                  // this is a group or user principal
                                  I_CmsPrincipal principal = CmsPrincipal.readPrincipal(rootCms, ace.getPrincipal());
                                  if (principal.isGroup()) {
                                      rootCms.rmacc(filename, I_CmsPrincipal.PRINCIPAL_GROUP, principal.getName());
                                  } else if (principal.isUser()) {
                                      rootCms.rmacc(filename, I_CmsPrincipal.PRINCIPAL_USER, principal.getName());
                                  }
                              }
                          }
  
                          // set additional permissions that are defined in mapping
                          for (Iterator<Map.Entry<String, String>> j = permissionsToSet.entrySet().iterator(); j.hasNext();) {
                              Map.Entry<String, String> entry = j.next();
                              sepIndex = entry.getKey().indexOf('.');
                              if (sepIndex != -1) {
                                  String type = entry.getKey().substring(0, sepIndex);
                                  String name = entry.getKey().substring(sepIndex + 1);
                                  String permissions = entry.getValue();
                                  if (permissions.toLowerCase().indexOf('o') == -1) {
                                      permissions += "+o";
                                  }
                                  try {
                                      rootCms.chacc(filename, type, name, permissions);
                                  } catch (CmsException e) {
                                      // setting permission did not work
                                      LOG.error(e);
                                  }
                              }
                          }
  
                          // set permission(s) using the element value(s)
                          // the set with all selected principals
                          TreeSet<String> allPrincipals = new TreeSet<String>();
                          String path = CmsXmlUtils.removeXpathIndex(valuePath);
                          List<I_CmsXmlContentValue> values = content.getValues(path, valueLocale);
                          Iterator<I_CmsXmlContentValue> j = values.iterator();
                          while (j.hasNext()) {
                              I_CmsXmlContentValue val = j.next();
                              String principalName = val.getStringValue(rootCms);
                              // the prinicipal name can be a principal list
                              List<String> principalNames = CmsStringUtil.splitAsList(
                                  principalName,
                                  PRINCIPAL_LIST_SEPARATOR);
                              // iterate over the principals
                              Iterator<String> iterPrincipals = principalNames.iterator();
                              while (iterPrincipals.hasNext()) {
                                  // get the next principal
                                  String principal = iterPrincipals.next();
                                  allPrincipals.add(principal);
                              }
                          }
                          // iterate over the set with all principals and set the permissions
                          Iterator<String> iterAllPricinipals = allPrincipals.iterator();
                          while (iterAllPricinipals.hasNext()) {
                              // get the next principal
                              String principal = iterAllPricinipals.next();
                              rootCms.chacc(filename, principalType, principal, permissionString);
                          }
                          // special case: permissions are written only to one sibling, end loop
                          i = 0;
                      } else if (mapping.startsWith(MAPTO_PROPERTY_LIST) && (valueIndex == 0)) {
  
                          boolean mapToShared;
                          int prefixLength;
                          // check which mapping is used (shared or individual)
                          if (mapping.startsWith(MAPTO_PROPERTY_LIST_SHARED)) {
                              mapToShared = true;
                              prefixLength = MAPTO_PROPERTY_LIST_SHARED.length();
                          } else if (mapping.startsWith(MAPTO_PROPERTY_LIST_INDIVIDUAL)) {
                              mapToShared = false;
                              prefixLength = MAPTO_PROPERTY_LIST_INDIVIDUAL.length();
                          } else {
                              mapToShared = false;
                              prefixLength = MAPTO_PROPERTY_LIST.length();
                          }
  
                          // this is a property list mapping
                          String property = mapping.substring(prefixLength);
  
                          String path = CmsXmlUtils.removeXpathIndex(valuePath);
                          List<I_CmsXmlContentValue> values = content.getValues(path, valueLocale);
                          Iterator<I_CmsXmlContentValue> j = values.iterator();
                          StringBuffer result = new StringBuffer(values.size() * 64);
                          while (j.hasNext()) {
                              I_CmsXmlContentValue val = j.next();
                              result.append(val.getStringValue(rootCms));
                              if (j.hasNext()) {
                                  result.append(CmsProperty.VALUE_LIST_DELIMITER);
                              }
                          }
  
                          CmsProperty p;
                          if (mapToShared) {
                              // map to shared value
                              p = new CmsProperty(property, null, result.toString());
                          } else {
                              // map to individual value
                              p = new CmsProperty(property, result.toString(), null);
                          }
                          // write the created list string value in the selected property
                          rootCms.writePropertyObject(filename, p);
                          if (mapToShared) {
                              // special case: shared mappings must be written only to one sibling, end loop
                              i = 0;
                          }
  
                      } else if (mapping.startsWith(MAPTO_PROPERTY)) {
  
                          boolean mapToShared;
                          int prefixLength;
                          // check which mapping is used (shared or individual)
                          if (mapping.startsWith(MAPTO_PROPERTY_SHARED)) {
                              mapToShared = true;
                              prefixLength = MAPTO_PROPERTY_SHARED.length();
                          } else if (mapping.startsWith(MAPTO_PROPERTY_INDIVIDUAL)) {
                              mapToShared = false;
                              prefixLength = MAPTO_PROPERTY_INDIVIDUAL.length();
                          } else {
                              mapToShared = false;
                              prefixLength = MAPTO_PROPERTY.length();
                          }
  
                          // this is a property mapping
                          String property = mapping.substring(prefixLength);
  
                          CmsProperty p;
                          if (mapToShared) {
                              // map to shared value
                              p = new CmsProperty(property, null, stringValue);
                          } else {
                              // map to individual value
                              p = new CmsProperty(property, stringValue, null);
                          }
                          // just store the string value in the selected property
                          rootCms.writePropertyObject(filename, p);
                          if (mapToShared) {
                              // special case: shared mappings must be written only to one sibling, end loop
                              i = 0;
                          }
                      } else if (mapping.startsWith(MAPTO_URLNAME)) {
                          // we write the actual mappings later
                          urlNameMappingResources.add(siblings.get(i));
                      } else if (mapping.startsWith(MAPTO_ATTRIBUTE)) {
  
                          // this is an attribute mapping
                          String attribute = mapping.substring(MAPTO_ATTRIBUTE.length());
                          switch (ATTRIBUTES.indexOf(attribute)) {
                              case 0: // date released
                                  long date = 0;
                                  try {
                                      date = Long.valueOf(stringValue).longValue();
                                  } catch (NumberFormatException e) {
                                      // ignore, value can be a macro
                                  }
                                  if (date == 0) {
                                      date = CmsResource.DATE_RELEASED_DEFAULT;
                                  }
                                  // set the sibling release date
                                  rootCms.setDateReleased(filename, date, false);
                                  // set current file release date
                                  if (filename.equals(rootCms.getSitePath(file))) {
                                      file.setDateReleased(date);
                                  }
                                  break;
                              case 1: // date expired
                                  date = 0;
                                  try {
                                      date = Long.valueOf(stringValue).longValue();
                                  } catch (NumberFormatException e) {
                                      // ignore, value can be a macro
                                  }
                                  if (date == 0) {
                                      date = CmsResource.DATE_EXPIRED_DEFAULT;
                                  }
                                  // set the sibling expired date
                                  rootCms.setDateExpired(filename, date, false);
                                  // set current file expired date
                                  if (filename.equals(rootCms.getSitePath(file))) {
                                      file.setDateExpired(date);
                                  }
                                  break;
                              default:
                                  // ignore invalid / other mappings
                          }
                      }
                  }
              }
          }
          if (mapToUrlName) {
              CmsMappingResolutionContext context = (CmsMappingResolutionContext)(cms.getRequestContext().getAttribute(
                  ATTR_MAPPING_RESOLUTION_CONTEXT));
              for (CmsResource resourceForUrlNameMapping : urlNameMappingResources) {
                  if (!CmsResource.isTemporaryFileName(resourceForUrlNameMapping.getRootPath())) {
                      String mappedName = stringValue;
                      if (!CmsStringUtil.isEmptyOrWhitespaceOnly(mappedName)) {
                          mappedName = mappedName.trim();
                          context.addUrlNameMapping(mappedName, valueLocale, resourceForUrlNameMapping.getStructureId());
                      }
                  }
              }
          }
  
          // make sure the original is locked
          CmsLock lock = rootCms.getLock(file);
          if (lock.isUnlocked()) {
              rootCms.lockResource(file.getRootPath());
          } else if (!lock.isExclusiveOwnedBy(rootCms.getRequestContext().getCurrentUser())) {
              rootCms.changeLock(file.getRootPath());
          }
      }