private void updateNode()

in shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommand.java [183:315]


    private void updateNode(Node node, ResourceProxy resource) throws RepositoryException, IOException {

        if (node.getPath().equals(getPath()) && fileInfo != null) {
            updateFileLikeNodeTypes(node);
        }

        Set<String> propertiesToRemove = new HashSet<>();
        PropertyIterator properties = node.getProperties();
        while (properties.hasNext()) {
            Property property = properties.nextProperty();
            if (property.getDefinition().isProtected()
                    || property.getDefinition().isAutoCreated()
                    || property.getDefinition().getRequiredType() == PropertyType.BINARY) {
                continue;
            }
            propertiesToRemove.add(property.getName());
        }

        propertiesToRemove.removeAll(resource.getProperties().keySet());

        Session session = node.getSession();

        // update the mixin types ahead of type as contraints are enforced before
        // the session is committed
        Object mixinTypes = resource.getProperties().get(JcrConstants.JCR_MIXINTYPES);
        if (mixinTypes != null) {
            updateMixins(node, mixinTypes);
        }

        // remove old properties first
        // this supports the scenario where the node type is changed to a less permissive one
        for (String propertyToRemove : propertiesToRemove) {
            node.getProperty(propertyToRemove).remove();
            getLogger().trace("Removed property {0} from node at {1}", propertyToRemove, node.getPath());
        }
        
        String primaryType = (String) resource.getProperties().get(JcrConstants.JCR_PRIMARYTYPE);
        if (primaryType != null && !node.getPrimaryNodeType().getName().equals(primaryType) && node.getDepth() != 0) {
            node.setPrimaryType(primaryType);
            session.save();
            getLogger().trace("Set new primary type {0} for node at {1}", primaryType, node.getPath());
        }

        // TODO - review for completeness and filevault compatibility
        for (Map.Entry<String, Object> entry : resource.getProperties().entrySet()) {

            String propertyName = entry.getKey();
            Object propertyValue = entry.getValue();
            Property property = null;
            
            // it is possible that the property definition for 'jcr:mixinTypes' to not yet exist
            // so make sure that it does not get processed like a regular property
            if ( JcrConstants.JCR_MIXINTYPES.equals(propertyName) ) {
                continue;
            }

            if (node.hasProperty(propertyName)) {
                property = node.getProperty(propertyName);
            }

            if (property != null && property.getDefinition().isProtected()) {
                continue;
            }

            ValueFactory valueFactory = session.getValueFactory();
            Value value = null;
            Value[] values = null;

            if (propertyValue instanceof String) {
                value = valueFactory.createValue((String) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.STRING, false);
            } else if (propertyValue instanceof String[]) {
                values = toValueArray((String[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.STRING, true);
            } else if (propertyValue instanceof Boolean) {
                value = valueFactory.createValue((Boolean) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.BOOLEAN, false);
            } else if (propertyValue instanceof Boolean[]) {
                values = toValueArray((Boolean[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.BOOLEAN, true);
            } else if (propertyValue instanceof Calendar) {
                value = valueFactory.createValue((Calendar) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.DATE, false);
            } else if (propertyValue instanceof Calendar[]) {
                values = toValueArray((Calendar[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.DATE, true);
            } else if (propertyValue instanceof Double) {
                value = valueFactory.createValue((Double) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.DOUBLE, false);
            } else if (propertyValue instanceof Double[]) {
                values = toValueArray((Double[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.DOUBLE, true);
            } else if (propertyValue instanceof BigDecimal) {
                value = valueFactory.createValue((BigDecimal) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.DECIMAL, false);
            } else if (propertyValue instanceof BigDecimal[]) {
                values = toValueArray((BigDecimal[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.DECIMAL, true);
            } else if (propertyValue instanceof Long) {
                value = valueFactory.createValue((Long) propertyValue);
                ensurePropertyDefinitionMatchers(property, PropertyType.LONG, false);
            } else if (propertyValue instanceof Long[]) {
                values = toValueArray((Long[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.LONG, true);
                // TODO - distinguish between weak vs strong references
            } else if (propertyValue instanceof UUID) {
                Node reference = session.getNodeByIdentifier(((UUID) propertyValue).toString());
                value = valueFactory.createValue(reference);
                ensurePropertyDefinitionMatchers(property, PropertyType.REFERENCE, false);
            } else if (propertyValue instanceof UUID[]) {
                values = toValueArray((UUID[]) propertyValue, session);
                ensurePropertyDefinitionMatchers(property, PropertyType.REFERENCE, true);
            } else {
                throw new IllegalArgumentException("Unable to handle value '" + propertyValue + "' for property '"
                        + propertyName + "'");
            }

            if (value != null) {
                Object[] arguments = { propertyName, value, propertyValue, node.getPath() };
                getLogger().trace("Setting property {0} with value {1} (raw =  {2}) on node at {3}", arguments);
                node.setProperty(propertyName, value);
                getLogger().trace("Set property {0} with value {1} (raw =  {2}) on node at {3}", arguments);
            } else if (values != null) {
                Object[] arguments = { propertyName, values, propertyValue, node.getPath() };
                getLogger().trace("Setting property {0} with values {1} (raw =  {2}) on node at {3}", arguments);
                node.setProperty(propertyName, values);
                getLogger().trace("Set property {0} with values {1} (raw =  {2}) on node at {3}", arguments);
            } else {
                throw new IllegalArgumentException("Unable to extract a value or a value array for property '"
                        + propertyName + "' with value '" + propertyValue + "'");
            }
        }
    }