public void save(final int operationType)
      throws AccessDeniedException, ItemExistsException, ConstraintViolationException,
          InvalidItemStateException, VersionException, LockException, NoSuchNodeTypeException,
          RepositoryException {
    if (!isSystem() && getLocale() != null) {
      for (JCRNodeWrapper node : newNodes.values()) {
        for (String s : node.getNodeTypes()) {
          ExtendedPropertyDefinition[] propDefs =
              NodeTypeRegistry.getInstance().getNodeType(s).getPropertyDefinitions();
          for (ExtendedPropertyDefinition propDef : propDefs) {
            if (propDef.isMandatory()
                && propDef.getRequiredType() != PropertyType.WEAKREFERENCE
                && propDef.getRequiredType() != PropertyType.REFERENCE
                && !propDef.isProtected()
                && !node.hasProperty(propDef.getName())) {
              throw new ConstraintViolationException("Mandatory field : " + propDef.getName());
            }
          }
        }
      }
    }
    newNodes.clear();

    JCRObservationManager.doWorkspaceWriteCall(
        this,
        operationType,
        new JCRCallback<Object>() {
          public Object doInJCR(JCRSessionWrapper thisSession) throws RepositoryException {
            for (Session session : sessions.values()) {
              session.save();
            }
            return null;
          }
        });
  }
  @SuppressWarnings("unchecked")
  public List<ChoiceListValue> getChoiceListValues(
      ExtendedPropertyDefinition epd,
      String param,
      List<ChoiceListValue> values,
      Locale locale,
      Map<String, Object> context) {
    final SortedSet<ChoiceListValue> listValues = new TreeSet<ChoiceListValue>();
    if (StringUtils.isEmpty(param)) {
      param = "jmix:editorialContent";
    }
    try {
      String includedTypes = StringUtils.substringBefore(param, ";");

      Set<String> excludedTypes = new HashSet<String>();
      String exclusion = StringUtils.substringAfter(param, ";");
      if (StringUtils.isNotBlank(exclusion)) {
        excludedTypes.addAll(
            CollectionUtils.collect(
                Arrays.asList(StringUtils.substringAfter(param, ";").split(",")),
                new Transformer() {
                  public Object transform(Object input) {
                    return ((String) input).trim();
                  }
                }));
      }

      for (String nodeTypeName : includedTypes.split(",")) {
        nodeTypeName = nodeTypeName.trim();
        ExtendedNodeType nodeType = NodeTypeRegistry.getInstance().getNodeType(nodeTypeName);
        if (!isExcludedType(nodeType, excludedTypes)) {
          listValues.add(new ChoiceListValue(nodeType.getLabel(locale), nodeType.getName()));
        }
        NodeTypeIterator nti = nodeType.getSubtypes();
        while (nti.hasNext()) {
          ExtendedNodeType type = (ExtendedNodeType) nti.next();
          if (!isExcludedType(type, excludedTypes)) {
            listValues.add(new ChoiceListValue(type.getLabel(locale), type.getName()));
          }
        }
      }
    } catch (NoSuchNodeTypeException e) {
      logger.error("Cannot get type", e);
    }

    return new LinkedList<ChoiceListValue>(listValues);
  }