/*
 * 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.nifi.controller.serialization;

import org.apache.nifi.connectable.Size;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.encrypt.EncryptionException;
import org.apache.nifi.encrypt.PropertyEncryptor;
import org.apache.nifi.groups.RemoteProcessGroupPortDescriptor;
import org.apache.nifi.parameter.ExpressionLanguageAwareParameterParser;
import org.apache.nifi.parameter.ParameterParser;
import org.apache.nifi.parameter.ParameterTokenList;
import org.apache.nifi.remote.StandardRemoteProcessGroupPortDescriptor;
import org.apache.nifi.scheduling.ExecutionNode;
import org.apache.nifi.scheduling.SchedulingStrategy;
import org.apache.nifi.util.DomUtils;
import org.apache.nifi.web.api.dto.BundleDTO;
import org.apache.nifi.web.api.dto.ConnectableDTO;
import org.apache.nifi.web.api.dto.ConnectionDTO;
import org.apache.nifi.web.api.dto.ControllerServiceDTO;
import org.apache.nifi.web.api.dto.FlowSnippetDTO;
import org.apache.nifi.web.api.dto.FunnelDTO;
import org.apache.nifi.web.api.dto.LabelDTO;
import org.apache.nifi.web.api.dto.ParameterContextDTO;
import org.apache.nifi.web.api.dto.ParameterDTO;
import org.apache.nifi.web.api.dto.PortDTO;
import org.apache.nifi.web.api.dto.PositionDTO;
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
import org.apache.nifi.web.api.dto.ProcessorDTO;
import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
import org.apache.nifi.web.api.dto.ReportingTaskDTO;
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity;
import org.apache.nifi.web.api.entity.ParameterEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class FlowFromDOMFactory {
    private static final Logger logger = LoggerFactory.getLogger(FlowFromDOMFactory.class);

    public static BundleDTO getBundle(final Element bundleElement) {
        if (bundleElement == null) {
            return null;
        }

        final Element groupElement = DomUtils.getChild(bundleElement, "group");
        final Element artifactElement = DomUtils.getChild(bundleElement, "artifact");
        final Element versionElement = DomUtils.getChild(bundleElement, "version");

        return new BundleDTO(groupElement.getTextContent(), artifactElement.getTextContent(), versionElement.getTextContent());
    }

    public static PositionDTO getPosition(final Element positionElement) {
        if (positionElement == null) {
            throw new IllegalArgumentException("Invalid Flow: Found no 'position' element");
        }
        return new PositionDTO(Double.parseDouble(positionElement.getAttribute("x")), Double.parseDouble(positionElement.getAttribute("y")));
    }

    public static Size getSize(final Element sizeElement) {
        if (sizeElement == null) {
            throw new IllegalArgumentException("Invalid Flow: Found no 'size' element");
        }

        return new Size(Double.parseDouble(sizeElement.getAttribute("width")), Double.parseDouble(sizeElement.getAttribute("height")));
    }

    public static Map<String, String> getStyle(final Element stylesElement) {
        final Map<String, String> styles = new HashMap<>();
        if (stylesElement == null) {
            return styles;
        }

        for (final Element styleElement : getChildrenByTagName(stylesElement, "style")) {
            final String styleName = styleElement.getAttribute("name");
            final String styleValue = styleElement.getTextContent();
            styles.put(styleName, styleValue);
        }

        return styles;
    }

    public static ControllerServiceDTO getControllerService(final Element element, final PropertyEncryptor encryptor, final FlowEncodingVersion flowEncodingVersion) {
        final ControllerServiceDTO dto = new ControllerServiceDTO();

        dto.setId(getString(element, "id"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setName(getString(element, "name"));
        dto.setComments(getString(element, "comment"));
        dto.setType(getString(element, "class"));
        dto.setBundle(getBundle(DomUtils.getChild(element, "bundle")));

        final boolean enabled = getBoolean(element, "enabled");
        dto.setState(enabled ? ControllerServiceState.ENABLED.name() : ControllerServiceState.DISABLED.name());

        dto.setProperties(getProperties(element, encryptor, flowEncodingVersion));
        dto.setAnnotationData(getString(element, "annotationData"));

        return dto;
    }

    public static ReportingTaskDTO getReportingTask(final Element element, final PropertyEncryptor encryptor, final FlowEncodingVersion flowEncodingVersion) {
        final ReportingTaskDTO dto = new ReportingTaskDTO();

        dto.setId(getString(element, "id"));
        dto.setName(getString(element, "name"));
        dto.setComments(getString(element, "comment"));
        dto.setType(getString(element, "class"));
        dto.setBundle(getBundle(DomUtils.getChild(element, "bundle")));
        dto.setSchedulingPeriod(getString(element, "schedulingPeriod"));
        dto.setState(getString(element, "scheduledState"));
        dto.setSchedulingStrategy(getString(element, "schedulingStrategy"));

        dto.setProperties(getProperties(element, encryptor, flowEncodingVersion));
        dto.setAnnotationData(getString(element, "annotationData"));

        return dto;
    }

    public static ParameterContextDTO getParameterContext(final Element element, final PropertyEncryptor encryptor) {
        final ParameterContextDTO dto = new ParameterContextDTO();

        dto.setId(getString(element, "id"));
        dto.setName(getString(element, "name"));
        dto.setDescription(getString(element, "description"));

        final Set<ParameterEntity> parameterDtos = new LinkedHashSet<>();
        final List<Element> parameterElements = FlowFromDOMFactory.getChildrenByTagName(element, "parameter");
        for (final Element parameterElement : parameterElements) {
            final ParameterDTO parameterDto = new ParameterDTO();

            parameterDto.setName(getString(parameterElement, "name"));
            parameterDto.setDescription(getString(parameterElement, "description"));
            parameterDto.setSensitive(getBoolean(parameterElement, "sensitive"));

            final String value = decrypt(getString(parameterElement, "value"), encryptor);
            parameterDto.setValue(value);

            final ParameterEntity parameterEntity = new ParameterEntity();
            parameterEntity.setParameter(parameterDto);
            parameterDtos.add(parameterEntity);
        }

        dto.setParameters(parameterDtos);

        return dto;
    }

    public static ProcessGroupDTO getProcessGroup(final String parentId, final Element element, final PropertyEncryptor encryptor, final FlowEncodingVersion encodingVersion) {
        final ProcessGroupDTO dto = new ProcessGroupDTO();
        final String groupId = getString(element, "id");
        dto.setId(groupId);
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setParentGroupId(parentId);
        dto.setName(getString(element, "name"));
        dto.setPosition(getPosition(DomUtils.getChild(element, "position")));
        dto.setComments(getString(element, "comment"));
        dto.setFlowfileConcurrency(getString(element, "flowfileConcurrency"));
        dto.setFlowfileOutboundPolicy(getString(element, "flowfileOutboundPolicy"));

        final Map<String, String> variables = new HashMap<>();
        final NodeList variableList = DomUtils.getChildNodesByTagName(element, "variable");
        for (int i = 0; i < variableList.getLength(); i++) {
            final Element variableElement = (Element) variableList.item(i);
            final String name = variableElement.getAttribute("name");
            final String value = variableElement.getAttribute("value");
            variables.put(name, value);
        }
        dto.setVariables(variables);

        final Element versionControlInfoElement = DomUtils.getChild(element, "versionControlInformation");
        dto.setVersionControlInformation(getVersionControlInformation(versionControlInfoElement));

        final String parameterContextId = getString(element, "parameterContextId");
        final ParameterContextReferenceEntity parameterContextReference = new ParameterContextReferenceEntity();
        parameterContextReference.setId(parameterContextId);
        dto.setParameterContext(parameterContextReference);

        final Set<ProcessorDTO> processors = new HashSet<>();
        final Set<ConnectionDTO> connections = new HashSet<>();
        final Set<FunnelDTO> funnels = new HashSet<>();
        final Set<PortDTO> inputPorts = new HashSet<>();
        final Set<PortDTO> outputPorts = new HashSet<>();
        final Set<LabelDTO> labels = new HashSet<>();
        final Set<ProcessGroupDTO> processGroups = new HashSet<>();
        final Set<RemoteProcessGroupDTO> remoteProcessGroups = new HashSet<>();

        NodeList nodeList = DomUtils.getChildNodesByTagName(element, "processor");
        for (int i = 0; i < nodeList.getLength(); i++) {
            processors.add(getProcessor((Element) nodeList.item(i), encryptor, encodingVersion));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "funnel");
        for (int i = 0; i < nodeList.getLength(); i++) {
            funnels.add(getFunnel((Element) nodeList.item(i)));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "inputPort");
        for (int i = 0; i < nodeList.getLength(); i++) {
            inputPorts.add(getPort((Element) nodeList.item(i)));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "outputPort");
        for (int i = 0; i < nodeList.getLength(); i++) {
            outputPorts.add(getPort((Element) nodeList.item(i)));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "label");
        for (int i = 0; i < nodeList.getLength(); i++) {
            labels.add(getLabel((Element) nodeList.item(i)));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "processGroup");
        for (int i = 0; i < nodeList.getLength(); i++) {
            processGroups.add(getProcessGroup(groupId, (Element) nodeList.item(i), encryptor, encodingVersion));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "remoteProcessGroup");
        for (int i = 0; i < nodeList.getLength(); i++) {
            remoteProcessGroups.add(getRemoteProcessGroup((Element) nodeList.item(i), encryptor));
        }

        nodeList = DomUtils.getChildNodesByTagName(element, "connection");
        for (int i = 0; i < nodeList.getLength(); i++) {
            connections.add(getConnection((Element) nodeList.item(i)));
        }

        final FlowSnippetDTO groupContents = new FlowSnippetDTO();
        groupContents.setConnections(connections);
        groupContents.setFunnels(funnels);
        groupContents.setInputPorts(inputPorts);
        groupContents.setLabels(labels);
        groupContents.setOutputPorts(outputPorts);
        groupContents.setProcessGroups(processGroups);
        groupContents.setProcessors(processors);
        groupContents.setRemoteProcessGroups(remoteProcessGroups);

        dto.setContents(groupContents);
        return dto;
    }

    private static VersionControlInformationDTO getVersionControlInformation(final Element versionControlInfoElement) {
        if (versionControlInfoElement == null) {
            return null;
        }

        final VersionControlInformationDTO dto = new VersionControlInformationDTO();
        dto.setRegistryId(getString(versionControlInfoElement, "registryId"));
        dto.setBucketId(getString(versionControlInfoElement, "bucketId"));
        dto.setBucketName(getString(versionControlInfoElement, "bucketName"));
        dto.setFlowId(getString(versionControlInfoElement, "flowId"));
        dto.setFlowName(getString(versionControlInfoElement, "flowName"));
        dto.setFlowDescription(getString(versionControlInfoElement, "flowDescription"));
        dto.setVersion(getInt(versionControlInfoElement, "version"));
        return dto;
    }

    public static ConnectionDTO getConnection(final Element element) {
        final ConnectionDTO dto = new ConnectionDTO();
        dto.setId(getString(element, "id"));
        dto.setName(getString(element, "name"));
        dto.setLabelIndex(getOptionalInt(element, "labelIndex"));
        dto.setzIndex(getOptionalLong(element, "zIndex"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));

        final List<PositionDTO> bends = new ArrayList<>();
        final Element bendPointsElement = DomUtils.getChild(element, "bendPoints");
        if (bendPointsElement != null) {
            for (final Element bendPointElement : getChildrenByTagName(bendPointsElement, "bendPoint")) {
                final PositionDTO bend = getPosition(bendPointElement);
                bends.add(bend);
            }
        }
        dto.setBends(bends);

        final ConnectableDTO sourceConnectable = new ConnectableDTO();
        dto.setSource(sourceConnectable);
        sourceConnectable.setId(getString(element, "sourceId"));
        sourceConnectable.setGroupId(getString(element, "sourceGroupId"));
        sourceConnectable.setType(getString(element, "sourceType"));

        final ConnectableDTO destConnectable = new ConnectableDTO();
        dto.setDestination(destConnectable);
        destConnectable.setId(getString(element, "destinationId"));
        destConnectable.setGroupId(getString(element, "destinationGroupId"));
        destConnectable.setType(getString(element, "destinationType"));

        final Set<String> relationships = new HashSet<>();
        final List<Element> relationshipNodeList = getChildrenByTagName(element, "relationship");
        for (final Element relationshipElem : relationshipNodeList) {
            relationships.add(relationshipElem.getTextContent());
        }
        dto.setSelectedRelationships(relationships);

        dto.setBackPressureObjectThreshold(getLong(element, "maxWorkQueueSize"));

        final String maxDataSize = getString(element, "maxWorkQueueDataSize");
        if (maxDataSize != null && !maxDataSize.trim().isEmpty()) {
            dto.setBackPressureDataSizeThreshold(maxDataSize);
        }

        String expiration = getString(element, "flowFileExpiration");
        if (expiration == null) {
            expiration = "0 sec";
        }
        dto.setFlowFileExpiration(expiration);

        final List<String> prioritizerClasses = new ArrayList<>();
        final List<Element> prioritizerNodeList = getChildrenByTagName(element, "queuePrioritizerClass");
        for (final Element prioritizerElement : prioritizerNodeList) {
            prioritizerClasses.add(prioritizerElement.getTextContent().trim());
        }
        dto.setPrioritizers(prioritizerClasses);

        dto.setLoadBalanceStrategy(getString(element, "loadBalanceStrategy"));
        dto.setLoadBalancePartitionAttribute(getString(element, "partitioningAttribute"));
        dto.setLoadBalanceCompression(getString(element, "loadBalanceCompression"));

        return dto;
    }

    public static RemoteProcessGroupDTO getRemoteProcessGroup(final Element element, final PropertyEncryptor encryptor) {
        final RemoteProcessGroupDTO dto = new RemoteProcessGroupDTO();
        dto.setId(getString(element, "id"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setName(getString(element, "name"));
        dto.setTargetUri(getString(element, "url"));
        dto.setTargetUris(getString(element, "urls"));
        dto.setTransmitting(getBoolean(element, "transmitting"));
        dto.setPosition(getPosition(DomUtils.getChild(element, "position")));
        dto.setCommunicationsTimeout(getString(element, "timeout"));
        dto.setComments(getString(element, "comment"));
        dto.setYieldDuration(getString(element, "yieldPeriod"));
        dto.setTransportProtocol(getString(element, "transportProtocol"));
        dto.setProxyHost(getString(element, "proxyHost"));
        dto.setProxyPort(getOptionalInt(element, "proxyPort"));
        dto.setProxyUser(getString(element, "proxyUser"));
        dto.setLocalNetworkInterface(getString(element, "networkInterface"));

        final String rawPassword = getString(element, "proxyPassword");
        final String proxyPassword = encryptor == null ? rawPassword : decrypt(rawPassword, encryptor);
        dto.setProxyPassword(proxyPassword);

        return dto;
    }

    public static LabelDTO getLabel(final Element element) {
        final LabelDTO dto = new LabelDTO();
        dto.setId(getString(element, "id"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setLabel(getString(element, "value"));
        dto.setPosition(getPosition(DomUtils.getChild(element, "position")));
        final Size size = getSize(DomUtils.getChild(element, "size"));
        dto.setWidth(size.getWidth());
        dto.setHeight(size.getHeight());
        dto.setStyle(getStyle(DomUtils.getChild(element, "styles")));

        return dto;
    }

    public static FunnelDTO getFunnel(final Element element) {
        final FunnelDTO dto = new FunnelDTO();
        dto.setId(getString(element, "id"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setPosition(getPosition(DomUtils.getChild(element, "position")));

        return dto;
    }

    public static PortDTO getPort(final Element element) {
        final PortDTO portDTO = new PortDTO();
        portDTO.setId(getString(element, "id"));
        portDTO.setVersionedComponentId(getString(element, "versionedComponentId"));
        portDTO.setPosition(getPosition(DomUtils.getChild(element, "position")));
        portDTO.setName(getString(element, "name"));
        portDTO.setComments(getString(element, "comments"));
        portDTO.setAllowRemoteAccess(getBoolean(element, "allowRemoteAccess"));
        final ScheduledState scheduledState = getScheduledState(element);
        portDTO.setState(scheduledState.toString());

        final List<Element> maxTasksElements = getChildrenByTagName(element, "maxConcurrentTasks");
        if (!maxTasksElements.isEmpty()) {
            portDTO.setConcurrentlySchedulableTaskCount(Integer.parseInt(maxTasksElements.get(0).getTextContent()));
        }

        final List<Element> userAccessControls = getChildrenByTagName(element, "userAccessControl");
        if (userAccessControls != null && !userAccessControls.isEmpty()) {
            final Set<String> users = new HashSet<>();
            portDTO.setUserAccessControl(users);
            for (final Element userElement : userAccessControls) {
                users.add(userElement.getTextContent());
            }
        }

        final List<Element> groupAccessControls = getChildrenByTagName(element, "groupAccessControl");
        if (groupAccessControls != null && !groupAccessControls.isEmpty()) {
            final Set<String> groups = new HashSet<>();
            portDTO.setGroupAccessControl(groups);
            for (final Element groupElement : groupAccessControls) {
                groups.add(groupElement.getTextContent());
            }
        }

        return portDTO;
    }

    public static RemoteProcessGroupPortDescriptor getRemoteProcessGroupPort(final Element element) {
        final StandardRemoteProcessGroupPortDescriptor descriptor = new StandardRemoteProcessGroupPortDescriptor();

        // What we have serialized is the ID of the Remote Process Group, followed by a dash ('-'), followed by
        // the actual ID of the port; we want to get rid of the remote process group id.
        String id = getString(element, "id");
        if (id.length() > 37) {
            id = id.substring(37);
        }

        descriptor.setId(id);

        final String targetId = getString(element, "targetId");
        descriptor.setTargetId(targetId == null ? id : targetId);

        descriptor.setVersionedComponentId(getString(element, "versionedComponentId"));
        descriptor.setName(getString(element, "name"));
        descriptor.setComments(getString(element, "comments"));
        descriptor.setConcurrentlySchedulableTaskCount(getInt(element, "maxConcurrentTasks"));
        descriptor.setUseCompression(getBoolean(element, "useCompression"));
        descriptor.setBatchCount(getOptionalInt(element, "batchCount"));
        descriptor.setBatchSize(getString(element, "batchSize"));
        descriptor.setBatchDuration(getString(element, "batchDuration"));
        descriptor.setTransmitting("RUNNING".equalsIgnoreCase(getString(element, "scheduledState")));

        return descriptor;
    }

    public static ProcessorDTO getProcessor(final Element element, final PropertyEncryptor encryptor, final FlowEncodingVersion flowEncodingVersion) {
        final ProcessorDTO dto = new ProcessorDTO();

        dto.setId(getString(element, "id"));
        dto.setVersionedComponentId(getString(element, "versionedComponentId"));
        dto.setName(getString(element, "name"));
        dto.setType(getString(element, "class"));
        dto.setBundle(getBundle(DomUtils.getChild(element, "bundle")));
        dto.setPosition(getPosition(DomUtils.getChild(element, "position")));
        dto.setStyle(getStyle(DomUtils.getChild(element, "styles")));

        final ProcessorConfigDTO configDto = new ProcessorConfigDTO();
        dto.setConfig(configDto);
        configDto.setComments(getString(element, "comment"));
        configDto.setConcurrentlySchedulableTaskCount(getInt(element, "maxConcurrentTasks"));
        final String schedulingPeriod = getString(element, "schedulingPeriod");
        configDto.setSchedulingPeriod(schedulingPeriod);
        configDto.setPenaltyDuration(getString(element, "penalizationPeriod"));
        configDto.setYieldDuration(getString(element, "yieldPeriod"));
        configDto.setBulletinLevel(getString(element, "bulletinLevel"));
        configDto.setLossTolerant(getBoolean(element, "lossTolerant"));
        final ScheduledState scheduledState = getScheduledState(element);
        dto.setState(scheduledState.toString());

        // handle scheduling strategy
        final String schedulingStrategyName = getString(element, "schedulingStrategy");
        if (schedulingStrategyName == null || schedulingStrategyName.trim().isEmpty()) {
            configDto.setSchedulingStrategy(SchedulingStrategy.TIMER_DRIVEN.name());
        } else {
            configDto.setSchedulingStrategy(schedulingStrategyName.trim());
        }

        // handle execution node
        final String executionNode = getString(element, "executionNode");
        if (executionNode == null || executionNode.trim().isEmpty()) {
            configDto.setExecutionNode(ExecutionNode.ALL.name());
        } else {
            configDto.setExecutionNode(executionNode.trim());
        }

        final Long runDurationNanos = getOptionalLong(element, "runDurationNanos");
        if (runDurationNanos != null) {
            configDto.setRunDurationMillis(TimeUnit.NANOSECONDS.toMillis(runDurationNanos));
        }

        configDto.setProperties(getProperties(element, encryptor, flowEncodingVersion));
        configDto.setAnnotationData(getString(element, "annotationData"));

        final Set<String> autoTerminatedRelationships = new HashSet<>();
        final List<Element> autoTerminateList = getChildrenByTagName(element, "autoTerminatedRelationship");
        for (final Element autoTerminateElement : autoTerminateList) {
            autoTerminatedRelationships.add(autoTerminateElement.getTextContent());
        }
        configDto.setAutoTerminatedRelationships(autoTerminatedRelationships);

        return dto;
    }

    private static LinkedHashMap<String, String> getProperties(final Element element, final PropertyEncryptor encryptor, final FlowEncodingVersion flowEncodingVersion) {
        final LinkedHashMap<String, String> properties = new LinkedHashMap<>();
        final List<Element> propertyNodeList = getChildrenByTagName(element, "property");

        final ParameterParser parameterParser = new ExpressionLanguageAwareParameterParser();

        for (final Element propertyElement : propertyNodeList) {
            final String name = getString(propertyElement, "name");

            final String rawPropertyValue = getString(propertyElement, "value");
            final String value = encryptor == null ? rawPropertyValue : decrypt(rawPropertyValue, encryptor);

            if (flowEncodingVersion == null || (flowEncodingVersion.getMajorVersion() <= 1 && flowEncodingVersion.getMinorVersion() < 4)) {
                // Version 1.4 introduced the #{paramName} syntax for referencing parameters. If the version is less than 1.4, we must escpae any
                // #{...} reference that we find.
                final ParameterTokenList parameterTokenList = parameterParser.parseTokens(value);
                final String escaped = parameterTokenList.escape();
                properties.put(name, escaped);
            } else {
                properties.put(name, value);
            }
        }

        return properties;
    }

    private static String getString(final Element element, final String childElementName) {
        final List<Element> nodeList = getChildrenByTagName(element, childElementName);
        if (nodeList == null || nodeList.isEmpty()) {
            return null;
        }
        final Element childElement = nodeList.get(0);
        return childElement.getTextContent();
    }

    private static Integer getOptionalInt(final Element element, final String childElementName) {
        final List<Element> nodeList = getChildrenByTagName(element, childElementName);
        if (nodeList == null || nodeList.isEmpty()) {
            return null;
        }
        final Element childElement = nodeList.get(0);
        final String val = childElement.getTextContent();
        if (val == null) {
            return null;
        }
        return Integer.parseInt(val);
    }

    private static Long getOptionalLong(final Element element, final String childElementName) {
        final List<Element> nodeList = getChildrenByTagName(element, childElementName);
        if (nodeList == null || nodeList.isEmpty()) {
            return null;
        }
        final Element childElement = nodeList.get(0);
        final String val = childElement.getTextContent();
        if (val == null) {
            return null;
        }
        return Long.parseLong(val);
    }

    private static int getInt(final Element element, final String childElementName) {
        return Integer.parseInt(getString(element, childElementName));
    }

    private static long getLong(final Element element, final String childElementName) {
        return Long.parseLong(getString(element, childElementName));
    }

    private static boolean getBoolean(final Element element, final String childElementName) {
        return Boolean.parseBoolean(getString(element, childElementName));
    }

    private static ScheduledState getScheduledState(final Element element) {
        return ScheduledState.valueOf(getString(element, "scheduledState"));
    }

    private static List<Element> getChildrenByTagName(final Element element, final String childElementName) {
        return DomUtils.getChildElementsByTagName(element, childElementName);
    }

    private static String decrypt(final String value, final PropertyEncryptor encryptor) {
        if (value != null && value.startsWith(FlowSerializer.ENC_PREFIX) && value.endsWith(FlowSerializer.ENC_SUFFIX)) {
            try {
                return encryptor.decrypt(value.substring(FlowSerializer.ENC_PREFIX.length(), value.length() - FlowSerializer.ENC_SUFFIX.length()));
            } catch (EncryptionException e) {
                final String moreDescriptiveMessage = "There was a problem decrypting a sensitive flow configuration value. " +
                        "Check that the nifi.sensitive.props.key value in nifi.properties matches the value used to encrypt the flow.xml.gz file";
                logger.error(moreDescriptiveMessage, e);
                throw new EncryptionException(moreDescriptiveMessage, e);
            }
        } else {
            return value;
        }
    }
}
