You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2007/12/03 13:19:12 UTC

svn commit: r600505 - in /incubator/sling/trunk/microsling/microsling-core: ./ src/main/java/org/apache/sling/microsling/resource/ src/main/java/org/apache/sling/microsling/scripting/ src/main/java/org/apache/sling/microsling/slingservlets/ src/main/ja...

Author: fmeschbe
Date: Mon Dec  3 04:19:11 2007
New Revision: 600505

URL: http://svn.apache.org/viewvc?rev=600505&view=rev
Log:
SLING-109 Support Resource adapter

Modified:
    incubator/sling/trunk/microsling/microsling-core/pom.xml
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/JcrNodeResource.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/DefaultSlingServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxGetServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxPostServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/StreamServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/DefaultHtmlRendererServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/JsonRendererServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/PlainTextRendererServlet.java
    incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/request/helpers/MicroslingRequestPathInfoTest.java

Modified: incubator/sling/trunk/microsling/microsling-core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/pom.xml?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/pom.xml (original)
+++ incubator/sling/trunk/microsling/microsling-core/pom.xml Mon Dec  3 04:19:11 2007
@@ -159,7 +159,7 @@
           <scanIntervalSeconds>10</scanIntervalSeconds>
           <connectors>
             <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
-              <port>8080</port>
+              <port>9090</port>
               <maxIdleTime>60000</maxIdleTime>
             </connector>
           </connectors>

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/JcrNodeResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/JcrNodeResource.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/JcrNodeResource.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/JcrNodeResource.java Mon Dec  3 04:19:11 2007
@@ -36,17 +36,20 @@
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
-import org.apache.sling.api.resource.StreamProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** A Resource that wraps a JCR Node */
-public class JcrNodeResource implements Resource, NodeProvider, StreamProvider {
+public class JcrNodeResource implements Resource {
+    
+    /** default log */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
     private final Node node;
     private final String path;
     private final String resourceType;
-    private Object object;
     private final ResourceMetadata metadata;
 
     /** JCR Property that defines the resource type of this node */
@@ -76,18 +79,10 @@
         setMetaData(node, metadata);
     }
 
-    public void setObject(Object object) {
-        this.object = object;
-    }
-
     public String toString() {
         return "JcrNodeResource, type=" + resourceType + ", path=" + path;
     }
 
-    public Node getNode() {
-        return node;
-    }
-
     public String getURI() {
         return path;
     }
@@ -96,13 +91,29 @@
         return resourceType;
     }
 
-    // no object mapping yet
-    public Object getObject() {
-        return object;
+    @SuppressWarnings("unchecked")
+    public <Type> Type adaptTo(Class<Type> type) {
+        if (type == Node.class) {
+            return (Type) getNode(); // unchecked cast
+        } else if (type == InputStream.class) {
+            try {
+                return (Type) getInputStream(); // unchecked cast
+            } catch (IOException ioe) {
+                log.error("adaptTo: Error getting input stream for " + this, ioe);
+            }
+        }
+        
+        return null;
     }
-
+    
     public ResourceMetadata getResourceMetadata() {
         return metadata;
+    }
+
+    // --- helpers, public for scripting ----
+    
+    public Node getNode() {
+        return node;
     }
 
     public InputStream getInputStream() throws IOException {

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/resource/MicroslingResourceResolver.java Mon Dec  3 04:19:11 2007
@@ -40,7 +40,6 @@
 
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.SlingException;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.NonExistingResource;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
@@ -141,14 +140,17 @@
             if (path.length() == 0) {
                 // return the base resource
                 return base;
-            } else if (base instanceof NodeProvider) {
+            }
+            
+            Node baseNode = base.adaptTo(Node.class);
+            if (baseNode != null) {
                 try {
-                    Node baseNode = ((NodeProvider) base).getNode();
                     if (baseNode.hasNode(path)) {
                         return new JcrNodeResource(baseNode.getNode(path));
                     }
 
-                    log.error("getResource: There is no node at {} below {}",
+                    log.error(
+                        "getResource: There is no node at {} below {}",
                         path, base.getURI());
                     return null;
                 } catch (RepositoryException re) {
@@ -188,10 +190,11 @@
      */
     public Iterator<Resource> listChildren(final Resource parent)
             throws SlingException {
-        if (parent instanceof NodeProvider) {
+        Node parentNode = parent.adaptTo(Node.class);
+        if (parentNode != null) {
 
             try {
-                final NodeIterator children = ((NodeProvider) parent).getNode().getNodes();
+                final NodeIterator children = parentNode.getNodes();
                 return new Iterator<Resource>() {
 
                     public boolean hasNext() {
@@ -221,8 +224,7 @@
         }
 
         // return an empty iterator if parent has no node
-        List<Resource> empty = Collections.emptyList();
-        return empty.iterator();
+        return Collections.<Resource>emptyList().iterator();
     }
 
     /**

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java Mon Dec  3 04:19:11 2007
@@ -36,8 +36,8 @@
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.scripting.SlingScript;
 import org.apache.sling.api.scripting.SlingScriptEngine;
 import org.apache.sling.api.scripting.SlingScriptResolver;
@@ -263,44 +263,11 @@
             Property property;
             Value value;
 
-            try {
-
-                if (getScriptResource() instanceof NodeProvider) {
-                    // SLING-72: Cannot use primary items due to WebDAV creating
-                    // nt:unstructured as jcr:content node. So we just assume
-                    // nt:file and try to use the well-known data path
-                    Node node = ((NodeProvider) getScriptResource()).getNode();
-                    property = node.getProperty("jcr:content/jcr:data");
-                } else {
-                    throw new IOException("Scriptresource " + getScriptResource() + " must is not JCR Node based");
-                }
-
-                value = null;
-                if (property.getDefinition().isMultiple()) {
-                    // for a multi-valued property, we take the first non-null
-                    // value (null values are possible in multi-valued
-                    // properties)
-                    // TODO: verify this claim ...
-                    Value[] values = property.getValues();
-                    for (Value candidateValue : values) {
-                        if (candidateValue != null) {
-                            value = candidateValue;
-                            break;
-                        }
-                    }
-
-                    // incase we could not find a non-null value, we bail out
-                    if (value == null) {
-                        throw new IOException("Cannot access "
-                            + getScriptResource().getURI());
-                    }
-                } else {
-                    // for single-valued properties, we just take this value
-                    value = property.getValue();
-                }
-            } catch (RepositoryException re) {
-                throw (IOException) new IOException("Cannot get script "
-                    + getScriptResource().getURI()).initCause(re);
+            InputStream stream = getScriptResource().adaptTo(InputStream.class);
+            if (stream == null) {
+                throw new IOException(
+                    "Cannot get a stream to the script resource "
+                        + getScriptResource());
             }
 
             // Now know how to get the input stream, we still have to decide
@@ -308,28 +275,16 @@
             // UTF-8, which is a default in many places in JCR. Secondarily
             // we try to get a jcr:encoding property besides the data property
             // to provide a possible encoding
-            String encoding = "UTF-8";
-            try {
-                Node parent = property.getParent();
-                if (parent.hasNode(JCR_ENCODING)) {
-                    encoding = parent.getProperty(JCR_ENCODING).getString();
-                }
-            } catch (RepositoryException re) {
-                // don't care if we fail for any reason here, just assume
-                // default
+            ResourceMetadata meta = getScriptResource().getResourceMetadata();
+            String encoding = (String) meta.get(ResourceMetadata.CHARACTER_ENCODING);
+            if (encoding == null) {
+                encoding = "UTF-8";
             }
 
             // access the value as a stream and return a buffered reader
             // converting the stream data using UTF-8 encoding, which is
             // the default encoding used
-            try {
-                InputStream input = value.getStream();
-                return new BufferedReader(
-                    new InputStreamReader(input, encoding));
-            } catch (RepositoryException re) {
-                throw (IOException) new IOException("Cannot get script "
-                    + getScriptResource().getURI()).initCause(re);
-            }
+            return new BufferedReader(new InputStreamReader(stream, encoding));
         }
     }
 

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/DefaultSlingServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/DefaultSlingServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/DefaultSlingServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/DefaultSlingServlet.java Mon Dec  3 04:19:11 2007
@@ -24,6 +24,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.jcr.Node;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
@@ -31,7 +32,6 @@
 import org.apache.sling.api.HttpStatusCodeException;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.servlets.HttpConstants;
@@ -98,7 +98,7 @@
                 throw new HttpStatusCodeException(HttpServletResponse.SC_NOT_FOUND,
                         "Resource not found: " + r.getURI());
             }
-        } else if(r instanceof NodeProvider) {
+        } else if(r.adaptTo(Node.class) != null) {
 
             // make sure we have an Item, and render it via one of our renderingServlets
             final String suffix = req.getRequestPathInfo().getSuffix();

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxGetServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxGetServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxGetServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxGetServlet.java Mon Dec  3 04:19:11 2007
@@ -32,7 +32,6 @@
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.commons.json.JSONException;

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxPostServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxPostServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxPostServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/MicrojaxPostServlet.java Mon Dec  3 04:19:11 2007
@@ -34,7 +34,6 @@
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.request.RequestParameter;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.api.wrappers.SlingRequestPaths;
@@ -91,9 +90,7 @@
 
             // select the Resource to process
             Resource currentResource = request.getResource();
-            Node currentNode = (currentResource instanceof NodeProvider)
-                    ? ((NodeProvider) currentResource).getNode()
-                    : null;
+            Node currentNode = currentResource.adaptTo(Node.class);
 
             // need a Node, path and Session
             String currentPath = null;

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/StreamServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/StreamServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/StreamServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/StreamServlet.java Mon Dec  3 04:19:11 2007
@@ -36,7 +36,6 @@
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 import org.apache.sling.microsling.helpers.constants.HttpConstants;
 
@@ -68,7 +67,8 @@
     protected void doGet(SlingHttpServletRequest request,
             SlingHttpServletResponse response) throws ServletException, IOException {
 
-        if (!(request.getResource() instanceof NodeProvider)) {
+        Node node = request.getResource().adaptTo(Node.class);
+        if (node == null) {
             throw new HttpStatusCodeException(HttpServletResponse.SC_NOT_FOUND,
                 "Resource " + request.getResource().getURI()
                     + " must be a Node");
@@ -76,7 +76,6 @@
 
         try {
             // otherwise handle nt:file/nt:resource specially
-            Node node = ((NodeProvider) request.getResource()).getNode();
             if (node.isNodeType("nt:file")) {
                 Node content = node.getNode("jcr:content");
                 if (content.isNodeType("nt:resource")) {

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/DefaultHtmlRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/DefaultHtmlRendererServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/DefaultHtmlRendererServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/DefaultHtmlRendererServlet.java Mon Dec  3 04:19:11 2007
@@ -28,7 +28,6 @@
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 
@@ -49,7 +48,7 @@
     throws ServletException,IOException
     {
         final Resource  r = req.getResource();
-        final Node node = ((NodeProvider) r).getNode();
+        final Node node = r.adaptTo(Node.class);
         resp.setContentType(responseContentType);
         final PrintWriter pw = resp.getWriter();
         try {

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/JsonRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/JsonRendererServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/JsonRendererServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/JsonRendererServlet.java Mon Dec  3 04:19:11 2007
@@ -26,7 +26,6 @@
 import org.apache.sling.api.HttpStatusCodeException;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.NonExistingResource;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
@@ -64,11 +63,11 @@
         if(r instanceof NonExistingResource) {
             throw new HttpStatusCodeException(HttpServletResponse.SC_NOT_FOUND, "No data to dump");
         }
-        if(!(r instanceof NodeProvider)) {
+        final Node n = r.adaptTo(Node.class);
+        if(n == null) {
             throw new HttpStatusCodeException(
                 HttpServletResponse.SC_NOT_IMPLEMENTED, "Can only dump nodes");
         }
-        final Node n = ((NodeProvider) r).getNode();
 
         // how many levels deep?
         int maxRecursionLevels = 0;

Modified: incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/PlainTextRendererServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/PlainTextRendererServlet.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/PlainTextRendererServlet.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/main/java/org/apache/sling/microsling/slingservlets/renderers/PlainTextRendererServlet.java Mon Dec  3 04:19:11 2007
@@ -28,7 +28,6 @@
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.resource.NodeProvider;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
 
@@ -49,7 +48,7 @@
     throws ServletException,IOException
     {
         final Resource  r = req.getResource();
-        final Node node = ((NodeProvider) r).getNode();
+        final Node node = r.adaptTo(Node.class);
         resp.setContentType(responseContentType);
         final PrintWriter pw = resp.getWriter();
         try {

Modified: incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/request/helpers/MicroslingRequestPathInfoTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/request/helpers/MicroslingRequestPathInfoTest.java?rev=600505&r1=600504&r2=600505&view=diff
==============================================================================
--- incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/request/helpers/MicroslingRequestPathInfoTest.java (original)
+++ incubator/sling/trunk/microsling/microsling-core/src/test/java/org/apache/sling/microsling/request/helpers/MicroslingRequestPathInfoTest.java Mon Dec  3 04:19:11 2007
@@ -261,6 +261,10 @@
         public ResourceMetadata getResourceMetadata() {
             return metadata;
         }
+        
+        public <Type> Type adaptTo(Class<Type> type) {
+            return null;
+        }
 
     }