| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Flanderra
Revision: 13
Author: pcherkas
Date: 11 Jul 2008 22:17:31
Changes:refactoring of existent model
1. type metainfo separated to class StructureEnv
2. created DTD for structure declaration
3. parsing and formating util is separated from general type information lookup util
4. created interface for parsing and compilation of swf
5. created stub generation and reading interface and default implementations
6. refactored custom structure support
7. a lot of renaming
| ... | ...@@ -0,0 +1,114 @@ | |
| 1 | package com.flanderra.commons.xmlstub; | |
| 2 | ||
| 3 | import java.io.InputStream; | |
| 4 | import java.io.OutputStream; | |
| 5 | import java.util.ArrayList; | |
| 6 | import java.util.HashMap; | |
| 7 | import java.util.List; | |
| 8 | import java.util.Map; | |
| 9 | import java.util.Properties; | |
| 10 | ||
| 11 | import org.apache.commons.beanutils.PropertyUtils; | |
| 12 | import org.junit.Assert; | |
| 13 | ||
| 14 | public class PropertiesStubUtil implements IStubUtil { | |
| 15 | private static PropertiesStubUtil instance; | |
| 16 | private PropertiesStubUtil(){ | |
| 17 | ||
| 18 | } | |
| 19 | ||
| 20 | public static PropertiesStubUtil getInstance(){ | |
| 21 | if(instance==null){ | |
| 22 | instance = new PropertiesStubUtil(); | |
| 23 | } | |
| 24 | return instance; | |
| 25 | } | |
| 26 | ||
| 27 | public Map<String, Object> read(InputStream input) { | |
| 28 | try { | |
| 29 | Properties props = new Properties(); | |
| 30 | props.load(input); | |
| 31 | Map<String, Object> result = new HashMap<String, Object>(); | |
| 32 | List<String> collectionKeys = new ArrayList<String>(); | |
| 33 | for (Object objkey : props.keySet()) { | |
| 34 | String key = (String) objkey; | |
| 35 | String[] parts; | |
| 36 | if (key.contains(".")) { | |
| 37 | parts = key.split("[.]"); | |
| 38 | } else { | |
| 39 | parts = new String[]{key}; | |
| 40 | } | |
| 41 | for (int i = 0; i < parts.length; i++) { | |
| 42 | StringBuffer fullpath = new StringBuffer(""); | |
| 43 | for (int ind = 0; ind <= i; ind++) { | |
| 44 | if (!fullpath.toString().equals("")) { | |
| 45 | fullpath.append("."); | |
| 46 | } | |
| 47 | fullpath.append(parts[ind]); | |
| 48 | } | |
| 49 | String mapKey = fullpath.toString(); | |
| 50 | try { | |
| 51 | Long.parseLong(parts[i]); | |
| 52 | String collectionKey = mapKey.substring(0, mapKey.lastIndexOf('.')); | |
| 53 | if (!collectionKeys.contains(collectionKey)) { | |
| 54 | collectionKeys.add(collectionKey); | |
| 55 | } | |
| 56 | } catch (NumberFormatException e) { | |
| 57 | } | |
| 58 | ||
| 59 | if (i == parts.length - 1) { | |
| 60 | PropertyUtils.setProperty(result, mapKey, props.getProperty(key)); | |
| 61 | } else { | |
| 62 | if (PropertyUtils.getProperty(result, mapKey) == null) { | |
| 63 | PropertyUtils.setProperty(result, mapKey, new HashMap<String, Object>()); | |
| 64 | } | |
| 65 | } | |
| 66 | } | |
| 67 | } | |
| 68 | for (int i = collectionKeys.size() - 1; i >= 0; i--) { | |
| 69 | String collectionKey = collectionKeys.get(i); | |
| 70 | Map<String, Object> tmp = (Map<String, Object>) PropertyUtils.getProperty(result, collectionKey); | |
| 71 | List tmp2 = new ArrayList(); | |
| 72 | for(int j = 0; j < tmp.keySet().size(); j++){ | |
| 73 | tmp2.add(tmp.get(""+j)); | |
| 74 | } | |
| 75 | PropertyUtils.setProperty(result, collectionKey, tmp2); | |
| 76 | } | |
| 77 | return result; | |
| 78 | } catch (Exception e) { | |
| 79 | throw new RuntimeException(); | |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | public void write(Map<String, Object> input, OutputStream output) { | |
| 84 | // TODO implement the storing properties in the same manner | |
| 85 | // if (obj1 instanceof Map) { | |
| 86 | // for (Object key : ((Map<? extends String, ? extends Object>) obj1).keySet()) { | |
| 87 | // if (!ignore.contains(key)) { | |
| 88 | // assertEquals(key.toString(), ((Map<String, Object>) obj1).get(key), ((Map<String, Object>) obj2).get(key), ignore); | |
| 89 | // } | |
| 90 | // } | |
| 91 | // } else if (obj1 instanceof List) { | |
| 92 | // List list1 = (List) obj1; | |
| 93 | // List list2 = (List) obj2; | |
| 94 | // for (int i = 0; i < list2.size(); i++) { | |
| 95 | // if (!ignore.contains(name)) { | |
| 96 | // Object el1 = list1.get(i); | |
| 97 | // Object el2 = list2.get(i); | |
| 98 | // assertEquals(name + "[" + i + "]", el1, el2, ignore); | |
| 99 | // } | |
| 100 | // } | |
| 101 | // } else { | |
| 102 | // if(!ignore.contains(name)){ | |
| 103 | // if(obj1 instanceof Double || obj2 instanceof Double){ | |
| 104 | // Assert.assertEquals(name + " are not equal", Double.parseDouble(String.valueOf(obj1)), Double.parseDouble(String.valueOf(obj2))); | |
| 105 | // } else { | |
| 106 | // Assert.assertEquals(name + " are not equal", String.valueOf(obj1), String.valueOf(obj2)); | |
| 107 | // } | |
| 108 | // | |
| 109 | // } | |
| 110 | // } | |
| 111 | ||
| 112 | } | |
| 113 | ||
| 114 | } |
| ... | ...@@ -0,0 +1,17 @@ | |
| 1 | <!DOCTYPE structures [ | |
| 2 | <!ELEMENT structures (struct+)> | |
| 3 | <!ELEMENT struct (entry+)> | |
| 4 | <!ELEMENT entry> | |
| 5 | <!ATTLIST struct name CDATA #IMPLIED> | |
| 6 | <!ATTLIST struct aligned (true|false) "true"> | |
| 7 | <!ATTLIST struct calcseq CDATA #IMPLIED> | |
| 8 | ||
| 9 | <!ATTLIST entry type CDATA #IMPLIED> | |
| 10 | <!ATTLIST entry autocalculated (true|false) "false"> | |
| 11 | <!ATTLIST entry expression CDATA #IMPLIED> | |
| 12 | <!ATTLIST entry state CDATA #IMPLIED> | |
| 13 | <!ATTLIST entry type CDATA #IMPLIED> | |
| 14 | <!ATTLIST entry type CDATA #IMPLIED> | |
| 15 | <!ATTLIST entry type CDATA #IMPLIED> | |
| 16 | <!ATTLIST entry transmit (true|false) "false"> | |
| 17 | ]> | |
| 0 | 18 | \ No newline at end of file |
| ... | ...@@ -0,0 +1,29 @@ | |
| 1 | package com.flanderra.commons.xmlstub; | |
| 2 | ||
| 3 | import java.io.InputStream; | |
| 4 | import java.io.OutputStream; | |
| 5 | import java.util.Map; | |
| 6 | ||
| 7 | import com.thoughtworks.xstream.XStream; | |
| 8 | ||
| 9 | public class XMLStubUtil implements IStubUtil { | |
| 10 | private static XMLStubUtil instance; | |
| 11 | private XMLStubUtil(){ | |
| 12 | ||
| 13 | } | |
| 14 | ||
| 15 | public static XMLStubUtil getInstance(){ | |
| 16 | if(instance==null){ | |
| 17 | instance = new XMLStubUtil(); | |
| 18 | } | |
| 19 | return instance; | |
| 20 | } | |
| 21 | ||
| 22 | public void write(Map<String, Object> input, OutputStream output){ | |
| 23 | new XStream().toXML(input, output); | |
| 24 | } | |
| 25 | ||
| 26 | public Map<String, Object> read(InputStream input){ | |
| 27 | return (Map<String, Object>) new XStream().fromXML(input); | |
| 28 | } | |
| 29 | } |
| ... | ...@@ -0,0 +1,286 @@ | |
| 1 | package com.flanderra.commons.struct; | |
| 2 | ||
| 3 | import java.net.URL; | |
| 4 | import java.util.ArrayList; | |
| 5 | import java.util.HashMap; | |
| 6 | import java.util.List; | |
| 7 | import java.util.Map; | |
| 8 | ||
| 9 | import org.apache.commons.logging.Log; | |
| 10 | import org.apache.commons.logging.LogFactory; | |
| 11 | import org.dom4j.Document; | |
| 12 | import org.dom4j.Node; | |
| 13 | import org.dom4j.io.SAXReader; | |
| 14 | ||
| 15 | import com.flanderra.commons.struct.custom.CustomStructureFormat; | |
| 16 | ||
| 17 | /** | |
| 18 | * The singleton class, which holds all types configuration. | |
| 19 | * Loads during initialization all state from xml-config files. | |
| 20 | * No runtime reload or event model is implemented at the moment. | |
| 21 | * | |
| 22 | * @author pcherkashin | |
| 23 | */ | |
| 24 | public class StructureEnv { | |
| 25 | private static StructureEnv instance; | |
| 26 | private static Log log = LogFactory.getLog(StructureEnv.class); | |
| 27 | public static String[] typeFiles = new String[] { | |
| 28 | "com/flanderra/commons/utils/types-basic.xml", | |
| 29 | "com/flanderra/commons/utils/types-shapes.xml", | |
| 30 | "com/flanderra/commons/utils/types-gradients.xml", | |
| 31 | "com/flanderra/commons/utils/types-tags-basic.xml", | |
| 32 | "com/flanderra/commons/utils/types-swf.xml" }; | |
| 33 | private Map<String, StructureFormat> types; | |
| 34 | private Map<String, Integer> tagCodes; | |
| 35 | private Map<Integer, String> tagNames; | |
| 36 | ||
| 37 | public static StructureEnv getInstance() { | |
| 38 | if (instance == null) { | |
| 39 | instance = new StructureEnv(); | |
| 40 | instance.init(); | |
| 41 | } | |
| 42 | return instance; | |
| 43 | } | |
| 44 | ||
| 45 | public Map<String, StructureFormat> getTypes() { | |
| 46 | return types; | |
| 47 | } | |
| 48 | ||
| 49 | public void setTypes(Map<String, StructureFormat> types) { | |
| 50 | this.types = types; | |
| 51 | } | |
| 52 | ||
| 53 | public Map<String, Integer> getTagCodes() { | |
| 54 | return tagCodes; | |
| 55 | } | |
| 56 | ||
| 57 | public void setTagCodes(Map<String, Integer> tagCodes) { | |
| 58 | this.tagCodes = tagCodes; | |
| 59 | } | |
| 60 | ||
| 61 | public Map<Integer, String> getTagNames() { | |
| 62 | return tagNames; | |
| 63 | } | |
| 64 | ||
| 65 | public void setTagNames(Map<Integer, String> tagNames) { | |
| 66 | this.tagNames = tagNames; | |
| 67 | } | |
| 68 | ||
| 69 | private StructureEnv() { | |
| 70 | } | |
| 71 | ||
| 72 | private void init() { | |
| 73 | initTagCodes(); | |
| 74 | initStructureFormats(); | |
| 75 | initStructureFormats(); | |
| 76 | } | |
| 77 | ||
| 78 | private void initStructureFormats() { | |
| 79 | try { | |
| 80 | types = new HashMap<String, StructureFormat>(); | |
| 81 | for (String file : typeFiles) { | |
| 82 | URL url = Thread.currentThread().getContextClassLoader() | |
| 83 | .getResource(file); | |
| 84 | SAXReader reader = new SAXReader(); | |
| 85 | Document document = reader.read(url); | |
| 86 | List<Node> typeNodes = document.selectNodes("//types/type"); | |
| 87 | for (Node typeNode : typeNodes) { | |
| 88 | StructureFormat type = new StructureFormat(); | |
| 89 | type.setName(typeNode.selectSingleNode("@name") | |
| 90 | .getStringValue()); | |
| 91 | if (tagCodes.containsKey(type.getName())) { | |
| 92 | type.setTag(true); | |
| 93 | type.setTagCode(tagCodes.get(type.getName()) | |
| 94 | .longValue()); | |
| 95 | } else { | |
| 96 | type.setTag(false); | |
| 97 | } | |
| 98 | if (typeNode.selectSingleNode("@aligned") != null) { | |
| 99 | type.setAligned(typeNode.selectSingleNode("@aligned") | |
| 100 | .getStringValue().trim().equalsIgnoreCase( | |
| 101 | "true")); | |
| 102 | } | |
| 103 | if (typeNode.selectSingleNode("@customStruct") != null) { | |
| 104 | try { | |
| 105 | String className = typeNode.selectSingleNode( | |
| 106 | "@customStruct").getStringValue(); | |
| 107 | CustomStructureFormat customStruct = (CustomStructureFormat) Class | |
| 108 | .forName(className).newInstance(); | |
| 109 | type.setCustomStructureFormat(customStruct); | |
| 110 | continue; | |
| 111 | } catch (Exception e) { | |
| 112 | throw new RuntimeException(e); | |
| 113 | } | |
| 114 | } | |
| 115 | type.setFieldsSeq(new ArrayList<StructureFormatEntry>()); | |
| 116 | List<Node> fieldNodes = typeNode.selectNodes("field"); | |
| 117 | for (Node fieldNode : fieldNodes) { | |
| 118 | StructureFormatEntry field = new StructureFormatEntry(); | |
| 119 | field.setType(fieldNode.selectSingleNode("@type") | |
| 120 | .getStringValue().trim()); | |
| 121 | field.setName(fieldNode.selectSingleNode("@name") | |
| 122 | .getStringValue().trim()); | |
| 123 | if (fieldNode.selectSingleNode("@state") != null) { | |
| 124 | field.setState(fieldNode.selectSingleNode("@state") | |
| 125 | .getStringValue()); | |
| 126 | } | |
| 127 | ||
| 128 | // transmit fields | |
| 129 | if (fieldNode.selectSingleNode("@transmit") != null) { | |
| 130 | String transmitStr = fieldNode.selectSingleNode( | |
| 131 | "@transmit").getStringValue(); | |
| 132 | if (transmitStr != null && !transmitStr.equals("")) { | |
| 133 | List<String> transmitFields = new ArrayList<String>(); | |
| 134 | String[] transmitParts = transmitStr.split(","); | |
| 135 | for (String transmitPart : transmitParts) { | |
| 136 | transmitFields.add(transmitPart.trim()); | |
| 137 | } | |
| 138 | field.setTransmitFields(transmitFields); | |
| 139 | } | |
| 140 | } | |
| 141 | if (StructureFormatUtils.isArrayType(field.getType())) { | |
| 142 | String typeStr = field.getType(); | |
| 143 | String sizeStr = typeStr | |
| 144 | .substring(typeStr.indexOf('[') + 1, | |
| 145 | typeStr.lastIndexOf(']')); | |
| 146 | try { | |
| 147 | Long.parseLong(sizeStr); | |
| 148 | } catch (NumberFormatException e) { | |
| 149 | if (field.getTransmitFields() == null) { | |
| 150 | field | |
| 151 | .setTransmitFields(new ArrayList<String>()); | |
| 152 | } | |
| 153 | if (!field.getTransmitFields() | |
| 154 | .contains(sizeStr)) { | |
| 155 | field.getTransmitFields().add(sizeStr); | |
| 156 | } | |
| 157 | } | |
| 158 | } | |
| 159 | // end transmit fields | |
| 160 | if (fieldNode.selectSingleNode("@autocalculated") != null) { | |
| 161 | field.setAutocalculated(fieldNode.selectSingleNode( | |
| 162 | "@autocalculated").getStringValue().trim() | |
| 163 | .equalsIgnoreCase("true")); | |
| 164 | } | |
| 165 | if (fieldNode.selectSingleNode("@collection") != null) { | |
| 166 | field.setCollection(fieldNode.selectSingleNode( | |
| 167 | "@collection").getStringValue().trim() | |
| 168 | .equalsIgnoreCase("true")); | |
| 169 | } | |
| 170 | if (fieldNode.selectSingleNode("@collectionsize") != null) { | |
| 171 | field.setCollectionsize(fieldNode.selectSingleNode( | |
| 172 | "@collectionsize").getStringValue()); | |
| 173 | } | |
| 174 | ||
| 175 | if (fieldNode.selectSingleNode("@route") != null) { | |
| 176 | field.setRoute(fieldNode.selectSingleNode("@route") | |
| 177 | .getStringValue().trim().equalsIgnoreCase( | |
| 178 | "true")); | |
| 179 | } | |
| 180 | ||
| 181 | if (fieldNode.selectSingleNode("@value") != null) { | |
| 182 | field.setValue(fieldNode.selectSingleNode("@value") | |
| 183 | .getStringValue().trim()); | |
| 184 | } | |
| 185 | type.getFieldsSeq().add(field); | |
| 186 | } | |
| 187 | if (typeNode.selectSingleNode("@calcseq") != null) { | |
| 188 | String calcseqStr = typeNode.selectSingleNode( | |
| 189 | "@calcseq").getStringValue(); | |
| 190 | if (calcseqStr != null && !calcseqStr.equals("")) { | |
| 191 | type.setCalcSeq(new ArrayList<StructureFormatEntry>()); | |
| 192 | String[] calcSeqParts = calcseqStr.split(","); | |
| 193 | for (String calcSeqPart : calcSeqParts) { | |
| 194 | String fldName = calcSeqPart.trim(); | |
| 195 | for (StructureFormatEntry field : type.getFieldsSeq()) { | |
| 196 | if (field.getName().equalsIgnoreCase( | |
| 197 | fldName)) { | |
| 198 | type.getCalcSeq().add(field); | |
| 199 | } | |
| 200 | } | |
| 201 | ||
| 202 | } | |
| 203 | } | |
| 204 | } | |
| 205 | ||
| 206 | types.put(type.getName(), type); | |
| 207 | } | |
| 208 | } | |
| 209 | } catch (Exception e) { | |
| 210 | log.error(e.getMessage(), e); | |
| 211 | throw new RuntimeException("error while loading types", e); | |
| 212 | } | |
| 213 | } | |
| 214 | ||
| 215 | private void initTagCodes() { | |
| 216 | tagCodes = new HashMap<String, Integer>(); | |
| 217 | tagCodes.put("End", 0); | |
| 218 | tagCodes.put("ShowFrame", 1); | |
| 219 | tagCodes.put("DefineShape", 2); | |
| 220 | tagCodes.put("PlaceObject", 4); | |
| 221 | tagCodes.put("RemoveObject", 5); | |
| 222 | tagCodes.put("DefineBits", 6); | |
| 223 | tagCodes.put("DefineButton", 7); | |
| 224 | tagCodes.put("JPEGTables", 8); | |
| 225 | tagCodes.put("SetBackgroundColor", 9); | |
| 226 | tagCodes.put("DefineFont", 10); | |
| 227 | tagCodes.put("DefineText", 11); | |
| 228 | tagCodes.put("DoAction", 12); | |
| 229 | tagCodes.put("DefineFontInfo", 13); | |
| 230 | tagCodes.put("DefineSound", 14); | |
| 231 | tagCodes.put("StartSound", 15); | |
| 232 | tagCodes.put("DefineButtonSound", 17); | |
| 233 | tagCodes.put("SoundStreamHead", 18); | |
| 234 | tagCodes.put("SoundStreamBlock", 19); | |
| 235 | tagCodes.put("DefineBitsLossless", 20); | |
| 236 | tagCodes.put("DefineBitsJPEG2", 21); | |
| 237 | tagCodes.put("DefineShape2", 22); | |
| 238 | tagCodes.put("DefineButtonCxform", 23); | |
| 239 | tagCodes.put("Protect", 24); | |
| 240 | tagCodes.put("PlaceObject2", 26); | |
| 241 | tagCodes.put("RemoveObject2", 28); | |
| 242 | tagCodes.put("DefineShape3", 32); | |
| 243 | tagCodes.put("DefineText2", 33); | |
| 244 | tagCodes.put("DefineButton2", 34); | |
| 245 | tagCodes.put("DefineBitsJPEG3", 35); | |
| 246 | tagCodes.put("DefineBitsLossless2", 36); | |
| 247 | tagCodes.put("DefineEditText", 37); | |
| 248 | tagCodes.put("DefineSprite", 39); | |
| 249 | tagCodes.put("FrameLabel", 43); | |
| 250 | tagCodes.put("SoundStreamHead2", 45); | |
| 251 | tagCodes.put("DefineMorphShape", 46); | |
| 252 | tagCodes.put("DefineFont2", 48); | |
| 253 | tagCodes.put("ExportAssets", 56); | |
| 254 | tagCodes.put("ImportAssets", 57); | |
| 255 | tagCodes.put("EnableDebugger", 58); | |
| 256 | tagCodes.put("DoInitAction", 59); | |
| 257 | tagCodes.put("DefineVideoStream", 60); | |
| 258 | tagCodes.put("VideoFrame", 61); | |
| 259 | tagCodes.put("DefineFontInfo2", 62); | |
| 260 | tagCodes.put("EnableDebugger2", 64); | |
| 261 | tagCodes.put("ScriptLimits", 65); | |
| 262 | tagCodes.put("SetTabIndex", 66); | |
| 263 | tagCodes.put("FileAttributes", 69); | |
| 264 | tagCodes.put("PlaceObject3", 70); | |
| 265 | tagCodes.put("ImportAssets2", 71); | |
| 266 | tagCodes.put("DefineFontAlignZones", 73); | |
| 267 | tagCodes.put("CSMTextSettings", 74); | |
| 268 | tagCodes.put("DefineFont3", 75); | |
| 269 | tagCodes.put("SymbolClass", 76); | |
| 270 | tagCodes.put("Metadata", 77); | |
| 271 | tagCodes.put("DefineScalingGrid", 78); | |
| 272 | tagCodes.put("DoABC", 82); | |
| 273 | tagCodes.put("DefineShape4", 83); | |
| 274 | tagCodes.put("DefineMorphShape2", 84); | |
| 275 | tagCodes.put("DefineSceneAndFrameLabelData", 86); | |
| 276 | tagCodes.put("DefineBinaryData", 87); | |
| 277 | tagCodes.put("DefineFontName", 88); | |
| 278 | tagCodes.put("StartSound2", 89); | |
| 279 | ||
| 280 | tagNames = new HashMap<Integer, String>(); | |
| 281 | for (String key : tagCodes.keySet()) { | |
| 282 | tagNames.put(tagCodes.get(key), key); | |
| 283 | } | |
| 284 | ||
| 285 | } | |
| 286 | } |
| ... | ...@@ -0,0 +1,22 @@ | |
| 1 | package com.flanderra.commons.swfio; | |
| 2 | ||
| 3 | public class SWFIOException extends RuntimeException { | |
| 4 | ||
| 5 | public SWFIOException() { | |
| 6 | super(); | |
| 7 | } | |
| 8 | ||
| 9 | public SWFIOException(String arg0, Throwable arg1) { | |
| 10 | super(arg0, arg1); | |
| 11 | } | |
| 12 | ||
| 13 | public SWFIOException(String arg0) { | |
| 14 | super(arg0); | |
| 15 | } | |
| 16 | ||
| 17 | public SWFIOException(Throwable arg0) { | |
| 18 | super(arg0); | |
| 19 | } | |
| 20 | ||
| 21 | ||
| 22 | } |
| ... | ...@@ -0,0 +1,139 @@ | |
| 1 | package com.flanderra.commons.struct; | |
| 2 | ||
| 3 | import static com.flanderra.commons.utils.TypeUtils.toLong; | |
| 4 | ||
| 5 | import java.text.MessageFormat; | |
| 6 | import java.util.Map; | |
| 7 | ||
| 8 | /** | |
| 9 | * The auxiliary util class. It helps lookup the information about particular entry. | |
| 10 | * <ul> | |
| 11 | * <li>defines whether the entry is array type | |
| 12 | * <li>defines whether the entry is root SWF structure | |
| 13 | * <li>defines whether the entry is bit type (not byte aligned) | |
| 14 | * <li>defines tag meta information for given tag code | |
| 15 | * <li>helps to distinguish number of bits from array notation | |
| 16 | * </ul> | |
| 17 | * | |
| 18 | * | |
| 19 | * @author pcherkashin | |
| 20 | */ | |
| 21 | public class StructureFormatUtils implements StructureConstants { | |
| 22 | /** | |
| 23 | * Helps to distinguish number of bits from array notation | |
| 24 | * for example if entry has type <code>type="SB[nbits]"</code> and <code>nbits</code> | |
| 25 | * is in context, then it will be retrived from context, otherwise the value between square | |
| 26 | * braces will be considered as plain integer value | |
| 27 | * @param type | |
| 28 | * @param prefix the prefix including first square brace i.e. <code>SB[</code> | |
| 29 | * @param context the context map | |
| 30 | * @return retrived or parsed value | |
| 31 | */ | |
| 32 | public static int getBitsNumberForArray(String type, String prefix, Map<String, Object> context) { | |
| 33 | String sizeStr = type.trim().replace(prefix, "").replace("]", ""); | |
| 34 | long numbits; | |
| 35 | try { | |
| 36 | numbits = (int) Long.parseLong(sizeStr); | |
| 37 | } catch (NumberFormatException e) { | |
| 38 | numbits = (int) toLong(context.get(sizeStr)); | |
| 39 | } | |
| 40 | return (int) numbits; | |
| 41 | } | |
| 42 | ||
| 43 | /** | |
| 44 | * defines whether the entry is root SWF structure | |
| 45 | * @param typeName the name of type to check | |
| 46 | * @return <code>true</code> if the checked type is SWF, otherwise <code>false</code> | |
| 47 | */ | |
| 48 | private boolean isSWF(String typeName) { | |
| 49 | return typeName.trim().equalsIgnoreCase("SWF"); | |
| 50 | } | |
| 51 | ||
| 52 | /** | |
| 53 | * defines whether the entry is array type | |
| 54 | * @param typeName the name of type to check | |
| 55 | * @return <code>true</code> if the checked type is array type, otherwise <code>false</code> | |
| 56 | */ | |
| 57 | public static boolean isArrayType(String typeName) { | |
| 58 | return (typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SI8) || | |
| 59 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SI16) || | |
| 60 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI8) || | |
| 61 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI16) || | |
| 62 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI24) || | |
| 63 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI32) || | |
| 64 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI64) || | |
| 65 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UB) || | |
| 66 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SB) || | |
| 67 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_FB) | |
| 68 | ); | |
| 69 | } | |
| 70 | ||
| 71 | /** | |
| 72 | * defines whether the entry is bit type (not byte aligned) | |
| 73 | * @param typeName the name of type to check | |
| 74 | * @return <code>true</code> if the checked type is bit type, otherwise <code>false</code> | |
| 75 | */ | |
| 76 | public boolean isBitType(String typeName) { | |
| 77 | return (typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UB) || | |
| 78 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SB) || | |
| 79 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_FB) | |
| 80 | ); | |
| 81 | } | |
| 82 | ||
| 83 | /** | |
| 84 | * defines tag meta information for given ntag code | |
| 85 | * @param tagCode the tag code | |
| 86 | * @return name of corresponding tag | |
| 87 | */ | |
| 88 | public static String tagNameForCode(int tagCode){ | |
| 89 | return StructureEnv.getInstance().getTagNames().get(tagCode); | |
| 90 | } | |
| 91 | ||
| 92 | /** | |
| 93 | * defines whether the type of given name is elenemtary one(not compound) | |
| 94 | * @param typeName the name of type to check | |
| 95 | * @return <code>true</code> if the checked type is elementary one, otherwise <code>false</code> | |
| 96 | */ | |
| 97 | public static boolean isElementaryType(String typeName) { | |
| 98 | return (typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_UI8) || | |
| 99 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_UI16) || | |
| 100 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_UI24) || | |
| 101 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_UI32) || | |
| 102 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_SI8) || | |
| 103 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_SI16) || | |
| 104 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_SI32) || | |
| 105 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_FIXED16) || | |
| 106 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_FIXED32) || | |
| 107 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_FLOAT16) || | |
| 108 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_FLOAT32) || | |
| 109 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_FLOAT64) || | |
| 110 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_STRING) || | |
| 111 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_NONE) || | |
| 112 | typeName.trim().equalsIgnoreCase(ELEMENTARY_TYPE_ENCODED32) || | |
| 113 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SI8) || | |
| 114 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SI16) || | |
| 115 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI8) || | |
| 116 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI16) || | |
| 117 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI24) || | |
| 118 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI32) || | |
| 119 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UI64) || | |
| 120 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_UB) || | |
| 121 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_SB) || | |
| 122 | typeName.trim().startsWith(ELEMENTARY_TYPE_PREF_FB) | |
| 123 | ); | |
| 124 | } | |
| 125 | /** | |
| 126 | * loads the structure meta information for given name | |
| 127 | * @param name name of structure | |
| 128 | * @return the loaded {@link StructureFormat StructureFormat} in case, when structure were | |
| 129 | * found in ergistry, otherwice it will throw {@link IllegalStateException} | |
| 130 | */ | |
| 131 | public static StructureFormat typeForName(String name) { | |
| 132 | if (StructureEnv.getInstance().getTypes().containsKey(name)) { | |
| 133 | return StructureEnv.getInstance().getTypes().get(name); | |
| 134 | } else { | |
| 135 | throw new IllegalStateException(MessageFormat.format("type \"{0}\" is unknown", name)); | |
| 136 | } | |
| 137 | } | |
| 138 | ||
| 139 | } |
| ... | ...@@ -0,0 +1,52 @@ | |
| 1 | package com.flanderra.commons.swfio; | |
| 2 | ||
| 3 | import java.io.InputStream; | |
| 4 | import java.io.OutputStream; | |
| 5 | import java.util.Map; | |
| 6 | ||
| 7 | ||
| 8 | /** | |
| 9 | * General interface for traversing the SWF document. Supports next use cases: | |
| 10 | * <ul> | |
| 11 | * <li>Parses existent SWF document and returns result as a recursive map | |
| 12 | * of parameters or writes the XML into output stream | |
| 13 | * <li>Compiles the existent map of parameters or incoming xml {@link InputStream} into SWF document | |
| 14 | * <li>I case of failure - throws {@link SWFIOException} | |
| 15 | * </ul> | |
| 16 | * @author pcherkashin | |
| 17 | */ | |
| 18 | public interface SWFIO { | |
| 19 | ||
| 20 | /** | |
| 21 | * Parses the incoming binary SWF stream an returns result as {@link java.util.Map} | |
| 22 | * | |
| 23 | * @param input the binary stream | |
| 24 | * @return {@link Map} object fulfilled with swf structure | |
| 25 | * @throws SWFIOException in case of malformed SWF binary stream | |
| 26 | */ | |
| 27 | public Map<String, Object> parseSWF(InputStream input) throws SWFIOException; | |
| 28 | ||
| 29 | /** | |
| 30 | * Parses the incoming binary SWF stream an writes result into output stream as XML | |
| 31 | * @param input the binary stream | |
| 32 | * @param output the textual XML stream | |
| 33 | * @throws SWFIOException in case of malformed SWF binary stream | |
| 34 | */ | |
| 35 | public void parseSWF(InputStream input, OutputStream output) throws SWFIOException; | |
| 36 | ||
| 37 | /** | |
| 38 | * Compiles the incoming XML into binary SWF | |
| 39 | * @param input the textual stream with XML | |
| 40 | * @param output the result of compilation - binary SWF | |
| 41 | * @throws SWFIOException in case of wrong structure of composed SWF | |
| 42 | */ | |
| 43 | public void compileSWF(InputStream input, OutputStream output) throws SWFIOException; | |
| 44 | ||
| 45 | /** | |
| 46 | * Compiles the incoming XML into binary SWF | |
| 47 | * @param input the map representing document structure | |
| 48 | * @param output the result of compilation - binary SWF | |
| 49 | * @throws SWFIOException in case of wrong structure of composed SWF | |
| 50 | */ | |
| 51 | public void compileSWF(Map<String, Object> input, OutputStream output) throws SWFIOException; | |
| 52 | } |
| ... | ...@@ -0,0 +1,81 @@ | |
| 1 | package com.flanderra.commons.swfio.impl; | |
| 2 | ||
| 3 | import java.io.IOException; | |
| 4 | import java.io.InputStream; | |
| 5 | import java.io.OutputStream; | |
| 6 | import java.util.Map; | |
| 7 | ||
| 8 | import org.apache.commons.logging.Log; | |
| 9 | import org.apache.commons.logging.LogFactory; | |
| 10 | ||
| 11 | import com.flanderra.commons.struct.StructureFormatIOUtils; | |
| 12 | import com.flanderra.commons.swfio.SWFIO; | |
| 13 | import com.flanderra.commons.swfio.SWFIOException; | |
| 14 | import com.flanderra.commons.xmlstub.IStubUtil; | |
| 15 | import com.flanderra.commons.xmlstub.XMLStubUtil; | |
| 16 | ||
| 17 | /** | |
| 18 | * {@inheritDoc} | |
| 19 | */ | |
| 20 | public class SWIFOImpl implements SWFIO { | |
| 21 | private static final IStubUtil stubUtil = XMLStubUtil.getInstance(); | |
| 22 | private static final Log logger = LogFactory.getLog(SWIFOImpl.class); | |
| 23 | ||
| 24 | /** | |
| 25 | * {@inheritDoc} | |
| 26 | */ | |
| 27 | public void compileSWF(InputStream input, OutputStream output) throws SWFIOException { | |
| 28 | try { | |
| 29 | logger.debug("about to read the SWF structure from input stream..."); | |
| 30 | Map<String, Object> parsedSWF = stubUtil.read(input); | |
| 31 | logger.debug("the SWF structure successfully read from input stream"); | |
| 32 | logger.debug("starting compilation..."); | |
| 33 | byte[] bytes = StructureFormatIOUtils.formatSWF(parsedSWF); | |
| 34 | logger.debug("compilation successfully done"); | |
| 35 | logger.debug("starting outing bytes to output..."); | |
| 36 | output.write(bytes); | |
| 37 | logger.debug("all compilled bytes were sent to output"); | |
| 38 | } catch (Throwable e) { | |
| 39 | throw new SWFIOException("compilation failed", e); | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | /** | |
| 44 | * {@inheritDoc} | |
| 45 | */ | |
| 46 | public void compileSWF(Map<String, Object> input, OutputStream output) throws SWFIOException { | |
| 47 | try { | |
| 48 | logger.debug("starting compilation..."); | |
| 49 | byte[] bytes = StructureFormatIOUtils.formatSWF(input); | |
| 50 | logger.debug("compilation successfully done"); | |
| 51 | logger.debug("starting outing bytes to output..."); | |
| 52 | output.write(bytes); | |
| 53 | logger.debug("all compilled bytes were sent to output"); | |
| 54 | } catch (Throwable e) { | |
| 55 | throw new SWFIOException("compilation failed", e); | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | /** | |
| 60 | * {@inheritDoc} | |
| 61 | */ | |
| 62 | public Map<String, Object> parseSWF(InputStream input) throws SWFIOException { | |
| 63 | logger.debug("starting parsing binary SWF..."); | |
| 64 | Map<String, Object> result = StructureFormatIOUtils.parseSWF(input); | |
| 65 | logger.debug("parsing binary SWF done succesfully"); | |
| 66 | return result; | |
| 67 | } | |
| 68 | ||
| 69 | /** | |
| 70 | * {@inheritDoc} | |
| 71 | */ | |
| 72 | public void parseSWF(InputStream input, OutputStream output) throws SWFIOException { | |
| 73 | logger.debug("starting parsing binary SWF..."); | |
| 74 | Map<String, Object> result = StructureFormatIOUtils.parseSWF(input); | |
| 75 | logger.debug("parsing binary SWF done succesfully"); | |
| 76 | logger.debug("starting generation of XML stub..."); | |
| 77 | stubUtil.write(result, output); | |
| 78 | logger.debug("generation of XML stub done succesfully"); | |
| 79 | } | |
| 80 | ||
| 81 | } |
| ... | ...@@ -0,0 +1,10 @@ | |
| 1 | package com.flanderra.commons.xmlstub; | |
| 2 | ||
| 3 | import java.io.InputStream; | |
| 4 | import java.io.OutputStream; | |
| 5 | import java.util.Map; | |
| 6 | ||
| 7 | public interface IStubUtil { | |
| 8 | public void write(Map<String, Object> input, OutputStream output); | |
| 9 | public Map<String, Object> read(InputStream input); | |
| 10 | } |