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}