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