001package com.streamconverter.command.impl.xml;
002
003import com.streamconverter.StreamProcessingException;
004import com.streamconverter.command.AbstractStreamCommand;
005import com.streamconverter.command.rule.IRule;
006import com.streamconverter.path.TreePath;
007import java.io.IOException;
008import java.io.InputStream;
009import java.io.OutputStream;
010import java.util.ArrayList;
011import java.util.List;
012import java.util.Objects;
013import javax.xml.stream.XMLEventFactory;
014import javax.xml.stream.XMLEventReader;
015import javax.xml.stream.XMLEventWriter;
016import javax.xml.stream.XMLInputFactory;
017import javax.xml.stream.XMLOutputFactory;
018import javax.xml.stream.XMLStreamException;
019import javax.xml.stream.events.XMLEvent;
020import org.slf4j.Logger;
021import org.slf4j.LoggerFactory;
022
023/**
024 * XML変換コマンドクラス
025 *
026 * <p>このクラスは、XML形式のデータを変換するためのコマンドを実装します。 ストリームを使用して、XMLデータを読み込み、変換後のデータを出力します。
027 * 変換対象のXPathである箇所を特定したあとに、変換処理を実行することを想定しています。
028 */
029public class ConvertCommand extends AbstractStreamCommand {
030
031  private static final Logger logger = LoggerFactory.getLogger(ConvertCommand.class);
032  private IRule rule;
033  private TreePath treePath;
034
035  /**
036   * デフォルトコンストラクタ
037   *
038   * @param rule 変換ルール
039   * @param treePath 変換対象のTreePath
040   */
041  public ConvertCommand(IRule rule, TreePath treePath) {
042    super();
043    Objects.requireNonNull(rule, "rule must not be null");
044    Objects.requireNonNull(treePath, "treePath must not be null");
045    this.rule = rule;
046    this.treePath = treePath;
047  }
048
049  /**
050   * XML変換コマンドの実行
051   *
052   * @param inputStream 入力ストリーム
053   * @param outputStream 出力ストリーム
054   * @throws IOException 入出力エラーが発生した場合
055   * @throws StreamProcessingException XML処理エラーが発生した場合
056   */
057  @Override
058  protected void executeInternal(InputStream inputStream, OutputStream outputStream)
059      throws IOException {
060    // StaXを使用したXML変換処理を実装する
061    // ここでは、IRuleを使用して変換処理を行うことを想定しています。
062    // 例: XMLを読み込み、IRuleを適用して変換し、出力ストリームに書き込む処理を実装する
063    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
064    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
065
066    try {
067      XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(inputStream);
068      XMLEventWriter xmlEventWriter = xmlOutputFactory.createXMLEventWriter(outputStream);
069
070      try {
071        List<String> currentDirectory = new ArrayList<>();
072        while (xmlEventReader.hasNext()) {
073          XMLEvent event = xmlEventReader.nextEvent();
074          int eventType = event.getEventType();
075          switch (eventType) {
076            // 現在地点を保持するための処理
077            case XMLEvent.START_ELEMENT:
078              // 現在のXpathを保持する
079              currentDirectory.add(event.asStartElement().getName().getLocalPart());
080              break;
081            case XMLEvent.END_ELEMENT:
082              // 現在のXpathを保持する
083              currentDirectory.remove(currentDirectory.size() - 1);
084              break;
085            // 変換対象の箇所なら変換処理を実行する
086            case XMLEvent.CHARACTERS:
087              if (this.treePath.matches(currentDirectory)) {
088                String transformedData = rule.apply(event.asCharacters().getData());
089                event = XMLEventFactory.newDefaultFactory().createCharacters(transformedData);
090              }
091              break;
092            default:
093              // Handle other events if necessary
094              break;
095          }
096          // Write the event to the output stream
097          xmlEventWriter.add(event);
098        }
099      } finally {
100        // リソースのクリーンアップ
101        try {
102          if (xmlEventWriter != null) {
103            xmlEventWriter.close();
104          }
105        } catch (XMLStreamException e) {
106          logger.warn("XMLEventWriterのクローズ中にエラーが発生しました: {}", e.getMessage(), e);
107        }
108        try {
109          if (xmlEventReader != null) {
110            xmlEventReader.close();
111          }
112        } catch (XMLStreamException e) {
113          logger.warn("XMLEventReaderのクローズ中にエラーが発生しました: {}", e.getMessage(), e);
114        }
115      }
116    } catch (XMLStreamException e) {
117      logger.error("XML処理中にエラーが発生しました: {}", e.getMessage(), e);
118      throw new StreamProcessingException("XML変換処理に失敗しました", e);
119    }
120  }
121}