<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.sling.servlets.post.impl.operations;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.version.VersionException;
import javax.servlet.ServletException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.servlets.post.AbstractPostOperation;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.NodeNameGenerator;
import org.apache.sling.servlets.post.PostResponse;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.apache.sling.servlets.post.VersioningConfiguration;
import org.apache.sling.servlets.post.impl.helper.DefaultNodeNameGenerator;
import org.apache.sling.servlets.post.impl.helper.RequestProperty;

abstract class AbstractCreateOperation extends AbstractPostOperation {
    /**
     * The default node name generator
     */
    private NodeNameGenerator defaultNodeNameGenerator;

    /**
     * utility class for generating node names
     */
    private NodeNameGenerator[] extraNodeNameGenerators;

    /**
     * regular expression for parameters to ignore
     */
    private Pattern ignoredParameterNamePattern;

    protected AbstractCreateOperation() {
		this.defaultNodeNameGenerator = new DefaultNodeNameGenerator();
		this.ignoredParameterNamePattern = null;
    }

    public void setDefaultNodeNameGenerator(
            NodeNameGenerator defaultNodeNameGenerator) {
        this.defaultNodeNameGenerator = defaultNodeNameGenerator;
    }

    public void setExtraNodeNameGenerators(
            NodeNameGenerator[] extraNodeNameGenerators) {
        this.extraNodeNameGenerators = extraNodeNameGenerators;
    }

    public void setIgnoredParameterNamePattern(
            final Pattern ignoredParameterNamePattern) {
        this.ignoredParameterNamePattern = ignoredParameterNamePattern;
    }

    /**
     * Create node(s) according to current request
     *
     * @throws RepositoryException if a repository error occurs
     */
    protected void processCreate(final ResourceResolver resolver,
            final Map<String, RequestProperty> reqProperties,
            final PostResponse response,
            final List<Modification> changes,
            final VersioningConfiguration versioningConfiguration)
    throws PersistenceException, RepositoryException {

        final String path = response.getPath();

        if ( resolver.getResource(path) == null ) {

            deepGetOrCreateNode(resolver, path, reqProperties, changes, versioningConfiguration);
            response.setCreateRequest(true);

        } else {
            updateNodeType(resolver, path, reqProperties, changes, versioningConfiguration);
            updateMixins(resolver, path, reqProperties, changes, versioningConfiguration);
        }
    }

    protected void updateNodeType(final ResourceResolver resolver,
                    final String path,
                    final Map<String, RequestProperty> reqProperties,
                    final List<Modification> changes,
                    final VersioningConfiguration versioningConfiguration)
   throws PathNotFoundException,
            RepositoryException, NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException {
        final String nodeType = getPrimaryType(reqProperties, path);
        if (nodeType != null) {
            final Resource rsrc = resolver.getResource(path);
            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
            if ( mvm != null ) {
                final Node node = rsrc.adaptTo(Node.class);
                final boolean wasVersionable = (node == null ? false : isVersionable(node));

                if ( node != null ) {
                    checkoutIfNecessary(node, changes, versioningConfiguration);
                    node.setPrimaryType(nodeType);
                } else {
                    mvm.put("jcr:primaryType", nodeType);
                }

                if ( node != null ) {
                    // this is a bit of a cheat; there isn't a formal checkout, but assigning
                    // the mix:versionable mixin does an implicit checkout
                    if (!wasVersionable &&
                            versioningConfiguration.isCheckinOnNewVersionableNode() &&
                            isVersionable(node)) {
                        changes.add(Modification.onCheckout(path));
                    }
                }
            }
        }
    }

    protected void updateMixins(final ResourceResolver resolver,
                    final String path,
                    final Map<String, RequestProperty> reqProperties,
                    final List<Modification> changes,
                    final VersioningConfiguration versioningConfiguration)
    throws PathNotFoundException,
            RepositoryException, NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException {
        final String[] mixins = getMixinTypes(reqProperties, path);
        if (mixins != null) {

            final Resource rsrc = resolver.getResource(path);
            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
            if ( mvm != null ) {
                final Node node = rsrc.adaptTo(Node.class);

                final Set<String> newMixins = new HashSet<String>();
                newMixins.addAll(Arrays.asList(mixins));

                // clear existing mixins first
                if ( node != null ) {
                    checkoutIfNecessary(node, changes, versioningConfiguration);
                    for (NodeType mixin : node.getMixinNodeTypes()) {
                        String mixinName = mixin.getName();
                        if (!newMixins.remove(mixinName)) {
                            node.removeMixin(mixinName);<commit_msg>Code cleanup : remove unused throws declaration, RepositoryException covers everything<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.sling.servlets.post.impl.operations;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.servlet.ServletException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.servlets.post.AbstractPostOperation;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.NodeNameGenerator;
import org.apache.sling.servlets.post.PostResponse;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.apache.sling.servlets.post.VersioningConfiguration;
import org.apache.sling.servlets.post.impl.helper.DefaultNodeNameGenerator;
import org.apache.sling.servlets.post.impl.helper.RequestProperty;

abstract class AbstractCreateOperation extends AbstractPostOperation {
    /**
     * The default node name generator
     */
    private NodeNameGenerator defaultNodeNameGenerator;

    /**
     * utility class for generating node names
     */
    private NodeNameGenerator[] extraNodeNameGenerators;

    /**
     * regular expression for parameters to ignore
     */
    private Pattern ignoredParameterNamePattern;

    protected AbstractCreateOperation() {
		this.defaultNodeNameGenerator = new DefaultNodeNameGenerator();
		this.ignoredParameterNamePattern = null;
    }

    public void setDefaultNodeNameGenerator(
            NodeNameGenerator defaultNodeNameGenerator) {
        this.defaultNodeNameGenerator = defaultNodeNameGenerator;
    }

    public void setExtraNodeNameGenerators(
            NodeNameGenerator[] extraNodeNameGenerators) {
        this.extraNodeNameGenerators = extraNodeNameGenerators;
    }

    public void setIgnoredParameterNamePattern(
            final Pattern ignoredParameterNamePattern) {
        this.ignoredParameterNamePattern = ignoredParameterNamePattern;
    }

    /**
     * Create node(s) according to current request
     *
     * @throws RepositoryException if a repository error occurs
     */
    protected void processCreate(final ResourceResolver resolver,
            final Map<String, RequestProperty> reqProperties,
            final PostResponse response,
            final List<Modification> changes,
            final VersioningConfiguration versioningConfiguration)
    throws PersistenceException, RepositoryException {

        final String path = response.getPath();

        if ( resolver.getResource(path) == null ) {

            deepGetOrCreateNode(resolver, path, reqProperties, changes, versioningConfiguration);
            response.setCreateRequest(true);

        } else {
            updateNodeType(resolver, path, reqProperties, changes, versioningConfiguration);
            updateMixins(resolver, path, reqProperties, changes, versioningConfiguration);
        }
    }

    protected void updateNodeType(final ResourceResolver resolver,
                    final String path,
                    final Map<String, RequestProperty> reqProperties,
                    final List<Modification> changes,
                    final VersioningConfiguration versioningConfiguration)
    throws RepositoryException {
        final String nodeType = getPrimaryType(reqProperties, path);
        if (nodeType != null) {
            final Resource rsrc = resolver.getResource(path);
            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
            if ( mvm != null ) {
                final Node node = rsrc.adaptTo(Node.class);
                final boolean wasVersionable = (node == null ? false : isVersionable(node));

                if ( node != null ) {
                    checkoutIfNecessary(node, changes, versioningConfiguration);
                    node.setPrimaryType(nodeType);
                } else {
                    mvm.put("jcr:primaryType", nodeType);
                }

                if ( node != null ) {
                    // this is a bit of a cheat; there isn't a formal checkout, but assigning
                    // the mix:versionable mixin does an implicit checkout
                    if (!wasVersionable &&
                            versioningConfiguration.isCheckinOnNewVersionableNode() &&
                            isVersionable(node)) {
                        changes.add(Modification.onCheckout(path));
                    }
                }
            }
        }
    }

    protected void updateMixins(final ResourceResolver resolver,
                    final String path,
                    final Map<String, RequestProperty> reqProperties,
                    final List<Modification> changes,
                    final VersioningConfiguration versioningConfiguration)
    throws RepositoryException {
        final String[] mixins = getMixinTypes(reqProperties, path);
        if (mixins != null) {

            final Resource rsrc = resolver.getResource(path);
            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
            if ( mvm != null ) {
                final Node node = rsrc.adaptTo(Node.class);

                final Set<String> newMixins = new HashSet<String>();
                newMixins.addAll(Arrays.asList(mixins));

                // clear existing mixins first
                if ( node != null ) {
                    checkoutIfNecessary(node, changes, versioningConfiguration);
                    for (NodeType mixin : node.getMixinNodeTypes()) {
                        String mixinName = mixin.getName();
                        if (!newMixins.remove(mixinName)) {
                            node.removeMixin(mixinName);
{'fraction_non_alphanumeric': 0.07539274199080744, 'fraction_numerical': 0.0005488097688138849, 'mean_word_length': 2.721725810569313, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6822270', 'n_tokens_mistral': 3625, 'n_tokens_neox': 3503, 'n_words': 925}