001package arcommon.xml; 002 003import java.io.IOException; 004import java.io.ObjectOutputStream; 005import java.util.ArrayList; 006 007import arcommon.ReflectionUtil; 008import arcommon.StringUtil; 009import arcommon.xml.XmlSerializer.FieldData; 010 011public class XmlObjectOutputStream extends ObjectOutputStream { 012 private XmlSerializer xmlSerializer; 013 private Object object; 014 private Class<? extends Object> clazz; 015 private ArrayList<FieldData> fields; 016 private int level; 017 private boolean tagClosed; 018 private Class<?> specialHandlingClass; 019 private boolean specialHandlingAdded; 020 021 private boolean fieldsWritten; 022 private String dataIndent; 023 024 protected XmlObjectOutputStream(XmlSerializer pxmlSerializer, Object pobject, Class<? extends Object> pclazz, ArrayList<FieldData> pfields, int plevel, boolean ptagClosed, Class<?> pspecialHandlingClass) throws IOException, SecurityException { 025 xmlSerializer = pxmlSerializer; 026 object = pobject; 027 clazz = pclazz; 028 fields = pfields; 029 level = plevel; 030 tagClosed = ptagClosed; 031 specialHandlingClass = pspecialHandlingClass; 032 } 033 034 private String getCloseTagString() { 035 String result = ""; 036 if (!tagClosed) { 037 tagClosed = true; 038 result += ">\n"; 039 } 040 041 if (!specialHandlingAdded) { 042 specialHandlingAdded = true; 043 String indent = StringUtil.stringWithNumberOfChar((level + 1) * 4, ' '); 044 result += indent + "<" + XmlSerializerHelperUtil.TAG_SPECIAL_HANDLING; 045 result += " " + XmlSerializerHelperUtil.ATTRIBUTE_CLASS + "=\""; 046 result += ReflectionUtil.classToClassNameInJavaSyntax(specialHandlingClass); 047 result += "\">\n"; 048 } 049 050 return result; 051 } 052 053 public String completeOutput() { 054 if (!tagClosed) { 055 return null; 056 } 057 058 if (specialHandlingAdded) { 059 String indent = StringUtil.stringWithNumberOfChar((level + 1) * 4, ' '); 060 return indent + "</" + XmlSerializerHelperUtil.TAG_SPECIAL_HANDLING + ">\n"; 061 } 062 063 return null; 064 } 065 066 public void defaultWriteObject() throws IOException { 067 if (fieldsWritten) { 068 throw new RuntimeException("Fields have already been written"); 069 } 070 fieldsWritten = true; 071 String closeTagString = getCloseTagString(); 072 try { 073 tagClosed = xmlSerializer.addFieldsToOutput(object, clazz, fields, level + 1, closeTagString.length() == 0, closeTagString); 074 if (!tagClosed) { 075 specialHandlingAdded = false; 076 } 077 } catch (IllegalArgumentException e) { 078 throw new RuntimeException(e); 079 } catch (SecurityException e) { 080 throw new RuntimeException(e); 081 } catch (IllegalAccessException e) { 082 throw new RuntimeException(e); 083 } 084 } 085 086 private void writeData(Class<?> c, Object value) { 087 boolean reference = false; 088 if (c != null && XmlSerializerHelperUtil.shouldClassHaveAnId(c)) { 089 if (xmlSerializer.objectMapContains(value)) { 090 reference = true; 091 } else { 092 xmlSerializer.giveIdsToObject(c, value); 093 } 094 } 095 if (dataIndent == null) { 096 dataIndent = StringUtil.stringWithNumberOfChar((level + 2) * 4, ' '); 097 } 098 xmlSerializer.addToOutput(getCloseTagString()); 099 xmlSerializer.addToOutput(dataIndent + "<" + XmlSerializerHelperUtil.TAG_DATA); 100 if (value == null) { 101 xmlSerializer.addToOutput(" "); 102 xmlSerializer.addToOutput(XmlSerializerHelperUtil.ATTRIBUTE_DATA_OBJECT_IS_NULL); 103 xmlSerializer.addToOutput("=\""); 104 xmlSerializer.addToOutput(XmlSerializerHelperUtil.ATTRIBUTE_VALUE_TRUE); 105 xmlSerializer.addToOutput("\" />\n"); 106 } else if (reference) { 107 xmlSerializer.addToOutput(" "); 108 xmlSerializer.addToOutput(XmlSerializerHelperUtil.ATTRIBUTE_REFERENCE); 109 xmlSerializer.addToOutput("=\""); 110 int id = xmlSerializer.objectMapGetId(value); 111 xmlSerializer.addToOutput("" + id); 112 xmlSerializer.addToOutput("\" />\n"); 113 } else if (XmlSerializerHelperUtil.isSimpleClass(c)) { 114 xmlSerializer.addClassLengthValueAndId(c, value); 115 xmlSerializer.addToOutput(" />\n"); 116 } else { 117 xmlSerializer.addToOutput(">\n"); 118 try { 119 xmlSerializer.addObjectToOutput(value, level + 3); 120 xmlSerializer.addToOutput(dataIndent + "</" + XmlSerializerHelperUtil.TAG_DATA + ">\n"); 121 } catch (Exception e) { 122 throw new RuntimeException(e); 123 } 124 } 125 } 126 127 public void write(byte[] bytes) throws IOException { 128 writeData(byte[].class, bytes); 129 } 130 131 public void write(byte[] b, int offset, int length) throws IOException { 132 byte[] bytes = new byte[length]; 133 System.arraycopy(b, offset, bytes, 0, length); 134 writeData(byte[].class, bytes); 135 } 136 137 public void write(int b) throws IOException { 138 writeData(byte.class, b); 139 } 140 141 public void writeInt(int i) throws IOException { 142 writeData(int.class, i); 143 } 144 145 public void writeChar(int c) throws IOException { 146 writeData(char.class, (char)c); 147 } 148 149 public void writeBytes(String p0) throws IOException { 150 throw new RuntimeException("Not implemented"); 151 } 152 153 public void writeByte(int b) throws IOException { 154 writeData(byte.class, b); 155 } 156 157 public void writeLong(long l) throws IOException { 158 writeData(long.class, l); 159 } 160 161 public void writeShort(int s) throws IOException { 162 writeData(short.class, s); 163 } 164 165 public void writeUTF(String s) throws IOException { 166 writeData(String.class, s); 167 } 168 169 public void writeFloat(float f) throws IOException { 170 writeData(float.class, f); 171 } 172 173 public void writeBoolean(boolean b) throws IOException { 174 writeData(boolean.class, b); 175 } 176 177 public void writeChars(String s) throws IOException { 178 writeData(String.class, s); 179 } 180 181 public void writeDouble(double d) throws IOException { 182 writeData(double.class, d); 183 } 184 185 public void writeFields() throws IOException { 186 throw new RuntimeException("Not implemented"); 187 } 188 189 public PutField putFields() throws IOException { 190 throw new RuntimeException("Not implemented"); 191 } 192 193 public void close() throws IOException { 194 throw new RuntimeException("Not implemented"); 195 } 196 197 public void flush() throws IOException { 198 throw new RuntimeException("Not implemented"); 199 } 200 201 public void useProtocolVersion(int p0) throws IOException { 202 throw new RuntimeException("Not implemented"); 203 } 204 205 public void reset() throws IOException { 206 throw new RuntimeException("Not implemented"); 207 } 208 209 public void writeUnshared(Object p0) throws IOException { 210 throw new RuntimeException("Not implemented"); 211 } 212 213 @Override 214 protected void writeObjectOverride(Object o) throws IOException { 215 if (o == null) { 216 writeData(null, null); 217 } else { 218 writeData(o.getClass(), o); 219 } 220 } 221}