Package org.springframework.batch.core.jsr.configuration.xml

Source Code of org.springframework.batch.core.jsr.configuration.xml.ChunkParser

/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed 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.springframework.batch.core.jsr.configuration.xml;

import java.util.List;

import org.springframework.batch.core.configuration.xml.ExceptionElementParser;
import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
import org.springframework.batch.core.step.item.ChunkOrientedTasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* Parser for the <chunk /> element as specified in JSR-352.  The current state
* parses a chunk element into it's related batch artifacts ({@link ChunkOrientedTasklet}, {@link ItemReader},
* {@link ItemProcessor}, and {@link ItemWriter}).
*
* @author Michael Minella
* @author Chris Schaefer
* @since 3.0
*
*/
public class ChunkParser {
  private static final String TIME_LIMIT_ATTRIBUTE = "time-limit";
  private static final String ITEM_COUNT_ATTRIBUTE = "item-count";
  private static final String CHECKPOINT_ALGORITHM_ELEMENT = "checkpoint-algorithm";
  private static final String CLASS_ATTRIBUTE = "class";
  private static final String INCLUDE_ELEMENT = "include";
  private static final String NO_ROLLBACK_EXCEPTION_CLASSES_ELEMENT = "no-rollback-exception-classes";
  private static final String RETRYABLE_EXCEPTION_CLASSES_ELEMENT = "retryable-exception-classes";
  private static final String SKIPPABLE_EXCEPTION_CLASSES_ELEMENT = "skippable-exception-classes";
  private static final String WRITER_ELEMENT = "writer";
  private static final String PROCESSOR_ELEMENT = "processor";
  private static final String READER_ELEMENT = "reader";
  private static final String REF_ATTRIBUTE = "ref";
  private static final String RETRY_LIMIT_ATTRIBUTE = "retry-limit";
  private static final String SKIP_LIMIT_ATTRIBUTE = "skip-limit";
  private static final String CUSTOM_CHECKPOINT_POLICY = "custom";
  private static final String ITEM_CHECKPOINT_POLICY = "item";
  private static final String CHECKPOINT_POLICY_ATTRIBUTE = "checkpoint-policy";

  public void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, String stepName) {
    MutablePropertyValues propertyValues = bd.getPropertyValues();
    bd.setBeanClass(StepFactoryBean.class);
    bd.setAttribute("isNamespaceStep", false);

    propertyValues.addPropertyValue("hasChunkElement", Boolean.TRUE);

    String checkpointPolicy = element.getAttribute(CHECKPOINT_POLICY_ATTRIBUTE);
    if(StringUtils.hasText(checkpointPolicy)) {
      if(checkpointPolicy.equals(ITEM_CHECKPOINT_POLICY)) {
        String itemCount = element.getAttribute(ITEM_COUNT_ATTRIBUTE);
        if (StringUtils.hasText(itemCount)) {
          propertyValues.addPropertyValue("commitInterval", itemCount);
        } else {
          propertyValues.addPropertyValue("commitInterval", "10");
        }

        parseSimpleAttribute(element, propertyValues, TIME_LIMIT_ATTRIBUTE, "timeout");
      } else if(checkpointPolicy.equals(CUSTOM_CHECKPOINT_POLICY)) {
        parseCustomCheckpointAlgorithm(element, parserContext, propertyValues, stepName);
      }
    } else {
      String itemCount = element.getAttribute(ITEM_COUNT_ATTRIBUTE);
      if (StringUtils.hasText(itemCount)) {
        propertyValues.addPropertyValue("commitInterval", itemCount);
      } else {
        propertyValues.addPropertyValue("commitInterval", "10");
      }

      parseSimpleAttribute(element, propertyValues, TIME_LIMIT_ATTRIBUTE, "timeout");
    }

    parseSimpleAttribute(element, propertyValues, SKIP_LIMIT_ATTRIBUTE, "skipLimit");
    parseSimpleAttribute(element, propertyValues, RETRY_LIMIT_ATTRIBUTE, "retryLimit");

    NodeList children = element.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      Node nd = children.item(i);

      parseChildElement(element, parserContext, propertyValues, nd, stepName);
    }
  }

  private void parseSimpleAttribute(Element element,
      MutablePropertyValues propertyValues, String attributeName, String propertyName) {
    String propertyValue = element.getAttribute(attributeName);
    if (StringUtils.hasText(propertyValue)) {
      propertyValues.addPropertyValue(propertyName, propertyValue);
    }
  }

  private void parseChildElement(Element element, ParserContext parserContext,
      MutablePropertyValues propertyValues, Node nd, String stepName) {
    if (nd instanceof Element) {
      Element nestedElement = (Element) nd;
      String name = nestedElement.getLocalName();
      String artifactName = nestedElement.getAttribute(REF_ATTRIBUTE);

      if(name.equals(READER_ELEMENT)) {
        if (StringUtils.hasText(artifactName)) {
          propertyValues.addPropertyValue("stepItemReader", new RuntimeBeanReference(artifactName));
        }

        new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
      } else if(name.equals(PROCESSOR_ELEMENT)) {
        if (StringUtils.hasText(artifactName)) {
          propertyValues.addPropertyValue("stepItemProcessor", new RuntimeBeanReference(artifactName));
        }

        new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
      } else if(name.equals(WRITER_ELEMENT)) {
        if (StringUtils.hasText(artifactName)) {
          propertyValues.addPropertyValue("stepItemWriter", new RuntimeBeanReference(artifactName));
        }

        new PropertyParser(artifactName, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(nestedElement);
      } else if(name.equals(SKIPPABLE_EXCEPTION_CLASSES_ELEMENT)) {
        ManagedMap<TypedStringValue, Boolean> exceptionClasses = new ExceptionElementParser().parse(element, parserContext, SKIPPABLE_EXCEPTION_CLASSES_ELEMENT);
        if(exceptionClasses != null) {
          propertyValues.addPropertyValue("skippableExceptionClasses", exceptionClasses);
        }
      } else if(name.equals(RETRYABLE_EXCEPTION_CLASSES_ELEMENT)) {
        ManagedMap<TypedStringValue, Boolean> exceptionClasses = new ExceptionElementParser().parse(element, parserContext, RETRYABLE_EXCEPTION_CLASSES_ELEMENT);
        if(exceptionClasses != null) {
          propertyValues.addPropertyValue("retryableExceptionClasses", exceptionClasses);
        }
      } else if(name.equals(NO_ROLLBACK_EXCEPTION_CLASSES_ELEMENT)) {
        //TODO: Update to support excludes
        ManagedList<TypedStringValue> list = new ManagedList<TypedStringValue>();

        for (Element child : DomUtils.getChildElementsByTagName(nestedElement, INCLUDE_ELEMENT)) {
          String className = child.getAttribute(CLASS_ATTRIBUTE);
          list.add(new TypedStringValue(className, Class.class));
        }

        propertyValues.addPropertyValue("noRollbackExceptionClasses", list);
      }
    }
  }

  private void parseCustomCheckpointAlgorithm(Element element, ParserContext parserContext, MutablePropertyValues propertyValues, String stepName) {
    List<Element> elements = DomUtils.getChildElementsByTagName(element, CHECKPOINT_ALGORITHM_ELEMENT);

    if(elements.size() == 1) {
      Element checkpointAlgorithmElement = elements.get(0);

      String name = checkpointAlgorithmElement.getAttribute(REF_ATTRIBUTE);
      if(StringUtils.hasText(name)) {
        propertyValues.addPropertyValue("stepChunkCompletionPolicy", new RuntimeBeanReference(name));
      }

      new PropertyParser(name, parserContext, BatchArtifactType.STEP_ARTIFACT, stepName).parseProperties(checkpointAlgorithmElement);
    } else if(elements.size() > 1){
      parserContext.getReaderContext().error(
          "The <checkpoint-algorithm/> element may not appear more than once in a single <"
              + element.getNodeName() + "/>.", element);
    }
  }
}
TOP

Related Classes of org.springframework.batch.core.jsr.configuration.xml.ChunkParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.