axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From chinth...@apache.org
Subject svn commit: r312932 - in /webservices/axis2/trunk/java/modules/codegen: src/org/apache/axis2/databinding/ src/org/apache/axis2/databinding/utils/ test/org/apache/axis2/databinding/utils/
Date Tue, 11 Oct 2005 18:26:35 GMT
Author: chinthaka
Date: Tue Oct 11 11:26:15 2005
New Revision: 312932

URL: http://svn.apache.org/viewcvs?rev=312932&view=rev
Log:
Adding a StAX interface for the objects that will be generated by Axis2 data binding implementation.
This seems ok for now. But I need to test this a bit more for cases where you have more depth
in the list. 
Please note that ADB = Axis2 Data Binding

Added:
    webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/
    webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/ADBPullParserTest.java
    webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/DummyADBBean.java
Modified:
    webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/ADBNameValuePair.java
    webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/utils/ADBPullParser.java

Modified: webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/ADBNameValuePair.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/ADBNameValuePair.java?rev=312932&r1=312931&r2=312932&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/ADBNameValuePair.java
(original)
+++ webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/ADBNameValuePair.java
Tue Oct 11 11:26:15 2005
@@ -26,6 +26,11 @@
     private String name;
     private String value;
 
+    public ADBNameValuePair(String name, String value) {
+        this.name = name;
+        this.value = value;
+    }
+
     public String getName() {
         return name;
     }

Modified: webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/utils/ADBPullParser.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/utils/ADBPullParser.java?rev=312932&r1=312931&r2=312932&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/utils/ADBPullParser.java
(original)
+++ webservices/axis2/trunk/java/modules/codegen/src/org/apache/axis2/databinding/utils/ADBPullParser.java
Tue Oct 11 11:26:15 2005
@@ -33,8 +33,22 @@
     private QName elementQName;
 
     private ADBPullParser childPullParser;
+
     private boolean accessingChildPullParser = false;
 
+    // ===== To be used this ADBBean =============
+    private boolean isEndElementFinished = false;
+
+    // ===== To be used with ADBNameValuePair ====
+    private boolean processingADBNameValuePair = false;
+    private boolean nameValuePairStartElementProcessed = false;
+    private boolean nameValuePairTextProcessed = false;
+    private boolean nameValuePairEndElementProcessed = false;
+    private ParserInformation tempParserInfo;
+    // ==============================================
+
+    private ParserInformation parserInformation;
+
     private int currentIndex = 0;
 
 
@@ -48,10 +62,41 @@
     }
 
     public boolean isCompleted() {
-        return currentIndex >= propertyList.size() + 2;
+        return isEndElementFinished;
     }
 
 
+    public class ParserInformation {
+        String text;
+        QName name;
+
+        public ParserInformation(QName name, String text) {
+            this.text = text;
+            this.name = name;
+        }
+
+        public ParserInformation(QName name) {
+            this.name = name;
+        }
+
+
+        public String getText() {
+            return text;
+        }
+
+        public void setText(String text) {
+            this.text = text;
+        }
+
+        public QName getName() {
+            return name;
+        }
+
+        public void setName(QName name) {
+            this.name = name;
+        }
+    }
+
     // ----------- XMLStreamReader Methods -------------------------------------------//
     public Object getProperty(String string) throws IllegalArgumentException {
         return null;  //To change body of implemented methods use File | Settings | File
Templates.
@@ -63,19 +108,35 @@
             throw new XMLStreamException("End of elements has already been reached. Can not
go beyond that");
         }
 
-        if (accessingChildPullParser && !childPullParser.isCompleted()) {
-            return childPullParser.next();
+        if (accessingChildPullParser) {
+            if (!childPullParser.isCompleted()) {
+                return childPullParser.next();
+            } else {
+                accessingChildPullParser = false;
+                currentIndex++;
+            }
+        }
+
+        if(processingADBNameValuePair && nameValuePairEndElementProcessed){
+            processingADBNameValuePair = false;
+            currentIndex++;
+            parserInformation = tempParserInfo;
         }
 
         if (currentIndex == 0) {
             // then this is just the start element
             currentIndex++;
+            parserInformation = new ParserInformation(this.elementQName);
             return XMLStreamConstants.START_ELEMENT;
         } else if (propertyList.size() + 1 == currentIndex) {
             // this is the end of this element
             currentIndex++;
+            isEndElementFinished = true;
             return XMLStreamConstants.END_ELEMENT;
         } else {
+            if (processingADBNameValuePair) {
+                return processADBNameValuePair(null);
+            }
             Object o = propertyList.get(currentIndex - 1);
             if (o instanceof ADBBean) {
                 ADBBean adbBean = (ADBBean) o;
@@ -84,182 +145,225 @@
                 return this.next();
             } else if (o instanceof ADBNameValuePair) {
                 ADBNameValuePair adbNameValuePair = (ADBNameValuePair) o;
+                processingADBNameValuePair = true;
+                return processADBNameValuePair(adbNameValuePair);
             }
         }
 
         return event;
     }
 
-    public void require(int i, String string, String string1) throws XMLStreamException {
-        //To change body of implemented methods use File | Settings | File Templates.
+    private int processADBNameValuePair(ADBNameValuePair nameValuePair) {
+        int event = 0;
+        if (nameValuePair != null) {
+            event = XMLStreamConstants.START_ELEMENT;
+            tempParserInfo = parserInformation;
+            parserInformation = new ParserInformation(new QName(nameValuePair.getName()),
nameValuePair.getValue());
+            nameValuePairStartElementProcessed = true;
+            nameValuePairEndElementProcessed = false;
+        } else if (nameValuePairStartElementProcessed && !nameValuePairTextProcessed)
{
+            event = XMLStreamConstants.CHARACTERS;
+            nameValuePairTextProcessed = true;
+        } else if (nameValuePairTextProcessed) {
+            event = XMLStreamConstants.END_ELEMENT;
+            nameValuePairEndElementProcessed = true;
+            nameValuePairStartElementProcessed = false;
+            nameValuePairTextProcessed = false;
+        }
+
+        return event;
+    }
+
+    public ParserInformation getParserInformation() {
+        return parserInformation;
+    }
+
+    public boolean hasNext() throws XMLStreamException {
+        return !isEndElementFinished;
+    }
+
+    private ADBPullParser.ParserInformation getCorrectParserInformation() {
+        return accessingChildPullParser ? childPullParser.getParserInformation() : this.parserInformation;
     }
 
     public String getElementText() throws XMLStreamException {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null ? parserInfo.getText() : "";
     }
 
-    public int nextTag() throws XMLStreamException {
+
+    public int getAttributeCount() {
         return 0;  //To change body of implemented methods use File | Settings | File Templates.
     }
 
-    public boolean hasNext() throws XMLStreamException {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+    public int getNamespaceCount() {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public String getText() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null ? parserInfo.getText() : "";
+    }
+
+    public boolean hasText() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null && parserInfo.getText() != null && !"".equals(parserInformation.getText());
+    }
+
+    public QName getName() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null ? parserInfo.getName() : null;
+    }
+
+    public String getLocalName() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null ? parserInfo.getName().getLocalPart() : null;
+    }
+
+    public boolean hasName() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null && parserInfo.getName() != null;
+    }
+
+    public String getNamespaceURI() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null && parserInfo.getName() != null ? parserInfo.getName().getNamespaceURI()
: "";
+    }
+
+    public String getPrefix() {
+        ParserInformation parserInfo = getCorrectParserInformation();
+        return parserInfo != null ? parserInfo.getName().getPrefix() : null;
+    }
+
+
+    // -------- un-implemented methods ----------
+    public void require(int i, String string, String string1) throws XMLStreamException {
+        throw new UnsupportedOperationException("Yet to be implemented !!");
+    }
+
+    public int nextTag() throws XMLStreamException {
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public void close() throws XMLStreamException {
-        //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getNamespaceURI(String string) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isStartElement() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isEndElement() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isCharacters() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isWhiteSpace() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributeValue(String string, String string1) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public int getAttributeCount() {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public QName getAttributeName(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributeNamespace(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributeLocalName(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributePrefix(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributeType(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getAttributeValue(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isAttributeSpecified(int i) {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public int getNamespaceCount() {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getNamespacePrefix(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getNamespaceURI(int i) {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public NamespaceContext getNamespaceContext() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public int getEventType() {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    public String getText() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public char[] getTextCharacters() {
-        return new char[0];  //To change body of implemented methods use File | Settings
| File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException
{
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public int getTextStart() {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
+
     }
 
     public int getTextLength() {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getEncoding() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public boolean hasText() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public Location getLocation() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public QName getName() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public String getLocalName() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public boolean hasName() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public String getNamespaceURI() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
-    }
-
-    public String getPrefix() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getVersion() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean isStandalone() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public boolean standaloneSet() {
-        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getCharacterEncodingScheme() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getPITarget() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     public String getPIData() {
-        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+        throw new UnsupportedOperationException("Yet to be implemented !!");
     }
 
     // --------------------------------------------------------------------------------------------------//

Added: webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/ADBPullParserTest.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/ADBPullParserTest.java?rev=312932&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/ADBPullParserTest.java
(added)
+++ webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/ADBPullParserTest.java
Tue Oct 11 11:26:15 2005
@@ -0,0 +1,161 @@
+package org.apache.axis2.databinding.utils;
+
+import junit.framework.TestCase;
+import org.apache.axis2.databinding.ADBBean;
+import org.apache.axis2.databinding.ADBNameValuePair;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import java.util.ArrayList;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @author : Eran Chinthaka (chinthaka@apache.org)
+ */
+
+public class ADBPullParserTest extends TestCase {
+
+    protected Log log = LogFactory.getLog(getClass());
+
+
+    protected void setUp() throws Exception {
+
+    }
+
+    public void testSimpleArrayList() {
+        try {
+
+            String exptectedXML = "<Project><Name>Axis2</Name><Releases><FirstRelease>0.90</FirstRelease>"
+
+                    "<SecondRelease>0.91</SecondRelease><ThirdRelease>0.92</ThirdRelease></Releases>"
+
+                    "<Releases><FirstRelease>0.90</FirstRelease><SecondRelease>0.91</SecondRelease>"
+
+                    "<ThirdRelease>0.92</ThirdRelease></Releases><Organization>Apache</Organization>"
+
+                    "</Project>";
+
+            ADBNameValuePair adbNameValuePair;
+            ArrayList propertyList = new ArrayList();
+            propertyList.add(new ADBNameValuePair("Name", "Axis2"));
+            propertyList.add(new DummyADBBean());
+            propertyList.add(new DummyADBBean());
+            propertyList.add(new ADBNameValuePair("Organization", "Apache"));
+
+            QName projectQName = new QName("Project");
+            XMLStreamReader pullParser = ADBPullParser.createPullParser(propertyList, projectQName);
+//            while (pullParser.hasNext()) {
+//                int eventCode = pullParser.next();
+//                System.out.println(eventCode + ":" + getEventString(eventCode));
+//            }
+
+            StringBuffer buff = new StringBuffer();
+            while (pullParser.hasNext()) {
+                int eventCode = pullParser.next();
+
+                switch (eventCode) {
+                    case XMLStreamConstants.START_ELEMENT :
+                        buff.append("<");
+                        buff.append(pullParser.getLocalName());
+                        buff.append(">");
+                        break;
+                    case XMLStreamConstants.CHARACTERS :
+                        buff.append(pullParser.getText());
+                        break;
+                    case XMLStreamConstants.END_ELEMENT :
+                        buff.append("</");
+                        buff.append(pullParser.getLocalName());
+                        buff.append(">");
+                        break;
+                    default:
+                        System.out.println("No Other event can be trown here");
+                }
+            }
+
+            assertEquals(exptectedXML, buff.toString());
+        } catch (XMLStreamException e) {
+            log.error("Parser Error " + e);
+        }
+
+    }
+
+    private String getEventString(int eventCode) {
+        String event = "";
+
+        switch (eventCode) {
+            case 1 :
+                event = "START_ELEMENT";
+                break;
+            case 2 :
+                event = "END_ELEMENT";
+                break;
+            case 3 :
+                event = "PROCESSING_INSTRUCTION";
+                break;
+            case 4 :
+                event = "CHARACTERS";
+                break;
+            case 5 :
+                event = "COMMENT";
+                break;
+            case 6 :
+                event = "SPACE";
+                break;
+            case 7 :
+                event = "START_DOCUMENT";
+                break;
+            case 8 :
+                event = "END_DOCUMENT";
+                break;
+            case 9 :
+                event = "ENTITY_REFERENCE";
+                break;
+            case 10 :
+                event = "ATTRIBUTE";
+                break;
+            case 11 :
+                event = "DTD";
+                break;
+            case 12 :
+                event = "CDATA";
+                break;
+            case 13 :
+                event = "NAMESPACE";
+                break;
+            case 14 :
+                event = "NOTATION_DECLARATION";
+                break;
+            case 15 :
+                event = "ENTITY_DECLARATION";
+                break;
+        }
+        return event;
+    }
+
+    public class DummyADBBean implements ADBBean {
+
+        public XMLStreamReader getPullParser() {
+            ADBNameValuePair adbNameValuePair;
+            ArrayList propertyList = new ArrayList();
+            propertyList.add(new ADBNameValuePair("FirstRelease", "0.90"));
+            propertyList.add(new ADBNameValuePair("SecondRelease", "0.91"));
+            propertyList.add(new ADBNameValuePair("ThirdRelease", "0.92"));
+
+            QName releasesQName = new QName("Releases");
+            return ADBPullParser.createPullParser(propertyList, releasesQName);
+        }
+    }
+}

Added: webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/DummyADBBean.java
URL: http://svn.apache.org/viewcvs/webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/DummyADBBean.java?rev=312932&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/DummyADBBean.java
(added)
+++ webservices/axis2/trunk/java/modules/codegen/test/org/apache/axis2/databinding/utils/DummyADBBean.java
Tue Oct 11 11:26:15 2005
@@ -0,0 +1,40 @@
+package org.apache.axis2.databinding.utils;
+
+import org.apache.axis2.databinding.ADBBean;
+import org.apache.axis2.databinding.ADBNameValuePair;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import java.util.ArrayList;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @author : Eran Chinthaka (chinthaka@apache.org)
+ */
+
+public class DummyADBBean implements ADBBean {
+
+    public XMLStreamReader getPullParser() {
+        ADBNameValuePair adbNameValuePair;
+        ArrayList propertyList = new ArrayList();
+        propertyList.add(new ADBNameValuePair("FirstRelease", "0.90"));
+        propertyList.add(new ADBNameValuePair("SecondRelease", "0.91"));
+        propertyList.add(new ADBNameValuePair("ThirdRelease", "0.92"));
+
+        QName releasesQName = new QName("Releases");
+        return ADBPullParser.createPullParser(propertyList, releasesQName);
+    }
+}



Mime
View raw message