Example usage for org.dom4j Node getText

List of usage examples for org.dom4j Node getText

Introduction

In this page you can find the example usage for org.dom4j Node getText.

Prototype

String getText();

Source Link

Document

Returns the text of this node.

Usage

From source file:net.form105.rm.server.ant.container.InboundConfiguration.java

License:Apache License

public void readXml(Node xmlNode) {

    List<Node> nodes;
    XPath xPath;// w ww .  ja v a2  s. c o  m

    inboundType = xmlNode.valueOf("@type");

    xPath = DocumentHelper.createXPath("//inbound/parameters/parameter");
    nodes = (List<Node>) xPath.selectNodes(xmlNode);

    for (Node node : nodes) {
        logger.info(node);
        paramMap.addParameter(new ConfigParameter(node.valueOf("@key"), node.valueOf("@value")));
    }

    xPath = DocumentHelper.createXPath("//inbound/validators/validator");
    nodes = (List<Node>) xPath.selectNodes(xmlNode);
    for (Node node : nodes) {

        IInboundValidator validator = (IInboundValidator) Agent.getComponentById(node.getText());
        validatorList.add(validator);
    }

    xPath = DocumentHelper.createXPath("//inbound/listeners/listener");
    nodes = (List<Node>) xPath.selectNodes(xmlNode);
    for (Node node : nodes) {
        IInboundListener inboundListener = (IInboundListener) Agent.getComponentById(node.getText());
        listenerList.add(inboundListener);
    }

    xPath = DocumentHelper.createXPath("//inbound/executor");
    logger.info(xPath.selectSingleNode(xmlNode).getText());

    command = (AbstractCallbackCommand) Agent.getComponentById(xPath.selectSingleNode(xmlNode).getText());
}

From source file:nl.architolk.ldt.processors.RDF4JProcessor.java

License:Open Source License

public void generateData(PipelineContext context, ContentHandler contentHandler) throws SAXException {

    Document configDocument = readInputAsDOM4J(context, INPUT_CONFIG);
    Node configNode = configDocument.selectSingleNode("//config");

    contentHandler.startDocument();//w w w.j a v  a  2  s  . com
    contentHandler.startElement("", "response", "response", new AttributesImpl());

    String action = configNode.valueOf("action"); // The action to perform
    String cgraph = configNode.valueOf("cgraph"); // Container graph, the main graph
    String tgraph = configNode.valueOf("tgraph"); // The target graph
    String pgraph = configNode.valueOf("pgraph"); // The parent graph, for version information
    String postQuery = configNode.valueOf("postquery"); // Some post query, optional
    String uriPrefix = configNode.valueOf("uriprefix"); // The uri prefix for relative uri's

    String errorMsg = "";

    db = RDF4JProperties.createRepository();
    if (db == null) {
        errorMsg = "Unknown database. \n";
    } else {
        conn = db.getConnection();

        try {
            if (!(conn instanceof SPARQLConnection)) {
                conn.begin(IsolationLevels.NONE);
            }

            // Clear target graph, partially (all triples in original container) or completely
            if (action.equals("replace")) {
                String msg = "Target graph <" + tgraph + "> cleared";
                try {
                    IRI tgraphResource = db.getValueFactory().createIRI(tgraph);
                    conn.clear(tgraphResource);
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            } else if (action.equals("part")) {
                String msg = "Target graph <" + tgraph + "> partially cleared";
                try {
                    conn.prepareUpdate(
                            "delete { graph <" + tgraph + "> {?s?p?o}} using <" + cgraph + "> where {?s?p?o}")
                            .execute();
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Clear container, except when action = insert
            if (!action.equals("insert")) {
                String msg = "Container <" + cgraph + "> cleared";
                try {
                    IRI cgraphResource = db.getValueFactory().createIRI(cgraph);
                    conn.clear(cgraphResource);
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Insert documents into container graph
            Document dataDocument = readInputAsDOM4J(context, INPUT_DATA);
            List filelist = dataDocument.selectNodes("//filelist//file");
            Iterator<?> elit = filelist.listIterator();
            while (elit.hasNext()) {
                Node child = (Node) elit.next();
                String msg = "file uploaded: " + child.valueOf("@name");
                try {
                    uploadFile(child.valueOf("@name"), child.getText(), cgraph, uriPrefix);
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = "[" + child.valueOf("@name") + "] " + e.getMessage();
                    errorMsg += e.getMessage();
                    if (e.getCause() != null) {
                        msg += " (" + e.getCause().getMessage() + ")";
                        errorMsg += " (" + e.getCause().getMessage() + ")";
                    }
                    errorMsg += ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Remove existing properties in case of action = update
            if (action.equals("update")) {
                String msg = "Target graph cleared for update";
                try {
                    conn.prepareUpdate("delete {graph <" + tgraph + "> {?s?x?y}} using <" + cgraph + "> using <"
                            + tgraph + "> where {graph <" + tgraph + "> {?s?x?y} graph <" + cgraph
                            + "> {?s?p?o}}").execute();
                    // Remove orphant blank nodes (to third degree, beter option could be to count the number of deleted nodes and repeat when not equal to zero)
                    conn.prepareUpdate("delete {graph <" + tgraph + "> {?bs?bp?bo}} using <" + tgraph
                            + "> where {?bs?bp?bo FILTER(isblank(?bs)) FILTER NOT EXISTS {?s?p?bs}}").execute();
                    conn.prepareUpdate("delete {graph <" + tgraph + "> {?bs?bp?bo}} using <" + tgraph
                            + "> where {?bs?bp?bo FILTER(isblank(?bs)) FILTER NOT EXISTS {?s?p?bs}}").execute();
                    conn.prepareUpdate("delete {graph <" + tgraph + "> {?bs?bp?bo}} using <" + tgraph
                            + "> where {?bs?bp?bo FILTER(isblank(?bs)) FILTER NOT EXISTS {?s?p?bs}}").execute();
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Populate target graph with content of the container-graph
            if (action.equals("part") || action.equals("replace") || action.equals("update")) {
                String msg = "Target graph <" + tgraph + "> populated from container <" + cgraph + ">";
                try {
                    conn.prepareUpdate(
                            "insert { graph <" + tgraph + "> {?s?p?o}} using <" + cgraph + "> where {?s?p?o}")
                            .execute();
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Insert version-info into parent graph, if applicable
            if (!(cgraph.equals(pgraph) || pgraph.isEmpty())) {
                String msg = "Version metadata inserted into parent graph";
                try {
                    conn.prepareUpdate("insert data {graph <" + pgraph + "> {<" + pgraph
                            + "> <http://purl.org/dc/terms/hasVersion> <" + cgraph + ">}}").execute();
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }

            // Execute post query
            if (!postQuery.isEmpty()) {
                String msg = "Post query executed";
                try {
                    conn.prepareUpdate(postQuery).execute();
                } catch (Exception e) {
                    // In case of an error, put the errormessage in the result, but don't throw the exception
                    msg = e.toString();
                    errorMsg += e.getMessage() + ". \n";
                }
                contentHandler.startElement("", "scene", "scene", new AttributesImpl());
                contentHandler.characters(msg.toCharArray(), 0, msg.length());
                contentHandler.endElement("", "scene", "scene");
            }
            if (!(conn instanceof SPARQLConnection)) {
                conn.commit();
            }

        } finally {
            conn.close();
        }

    }

    if (!errorMsg.isEmpty()) {
        contentHandler.startElement("", "error", "error", new AttributesImpl());
        contentHandler.characters(errorMsg.toCharArray(), 0, errorMsg.length());
        contentHandler.endElement("", "error", "error");
    }
    contentHandler.endElement("", "response", "response");
    contentHandler.endDocument();
}

From source file:nl.knaw.dans.common.lang.xml.Dom4jReader.java

License:Apache License

public String getString(String xpath) throws DocumentException {
    Node node = getNode(xpath);
    return node.getText();
}

From source file:nl.knaw.dans.common.lang.xml.Dom4jReader.java

License:Apache License

@SuppressWarnings("unchecked")
public List<String> getList(String xpath) {
    List<String> textList = new ArrayList<String>();
    List<Node> nodes = document.selectNodes(xpath);
    for (Node n : nodes) {
        textList.add(n.getText());
    }/*from w w w.ja  v a 2 s .  com*/
    return textList;
}

From source file:nl.knaw.dans.dccd.application.services.DccdSearchService.java

License:Apache License

/**
 * Search the repository using the Solr indexer
 * Use offset and limit for paging the results
 *
 * Note: FedoraRepositoryService.getSearchResultAsXMLString()
 * searches Fedora and does not using Solr!
 *
 * @param query The query to search for (Solr)
 * @param offset Zero base index ofsset//  w w  w .ja  v  a 2  s  . c om
 * @param limit maximum number of resulting items to return
 * @return
 * @throws SearchServiceException
 */
public List<String> simpleSearch(String query, int offset, int limit) throws SearchServiceException {
    // max results should be bigger than 0
    if (limit < 1)
        throw new IllegalArgumentException("limit must be 1 or bigger");
    if (offset < 0)
        throw new IllegalArgumentException("offset must be 0 or bigger");

    List<String> result = new ArrayList<String>(); // empty list

    Properties settings = DccdConfigurationService.getService().getSettings();
    final String protocol = settings.getProperty("solr.protocol");
    final String host = settings.getProperty("solr.host");
    final int port = Integer.parseInt(settings.getProperty("solr.port"));
    final String context = settings.getProperty("solr.context");

    // use Solr to find project with the given query
    // the REST interface?
    //final int limit = 100;

    //String protocol = "http";
    //String host = "localhost";//"dendro01.dans.knaw.nl";
    //int port = 8082;//80;
    //String context = "solr-example/select";
    String baseURLString = protocol + "://" + host + ":" + port + "/" + context;

    String responseString = "";

    URL solrSearch;
    //BufferedReader in = null;
    Scanner in = null;
    StringBuilder response = new StringBuilder();
    try {
        // Note: the query string should be url encoded?
        String requestUrlString = baseURLString + "/?q=" + query + "&version=2.2&start=" + offset + "&rows="
                + limit + "&indent=on";

        logger.info("Solr search request: " + requestUrlString);
        solrSearch = new URL(requestUrlString);
        URLConnection fs = solrSearch.openConnection();
        in = new Scanner(fs.getInputStream());
        while (in.hasNextLine()) {
            response.append(in.nextLine());
            response.append("\n");
        }
    } catch (MalformedURLException e) {
        // this really should not happen, the url is coded
        throw new RuntimeException(e);
    } catch (IOException e) {
        //throw e;
        throw new SearchServiceException(e);
    }
    if (in != null)
        in.close();

    responseString = response.toString();
    // show response
    //logger.info("Response: \n" + response.toString());

    // parse the xml string
    // make this into separate function
    Document domDoc;
    try {
        domDoc = DocumentHelper.parseText(responseString);
        Element xmlResponse = domDoc.getRootElement();
        // get result element
        Element xmlResult = xmlResponse.element("result");
        // for all doc elements
        for (Iterator<?> i = xmlResult.elementIterator("doc"); i.hasNext();) {
            Element docElement = (Element) i.next();
            // get str element with attribute name="PID"
            //Node node = docElement.selectSingleNode( "str[@name='PID']" );
            // tridas objects instead of projects;
            // using another ID and not the fedora object PID
            Node node = docElement.selectSingleNode("str[@name='ID']");
            logger.info("Found: " + node.getText());
            result.add(node.getText());
        }
    } catch (DocumentException e) {
        //throw e;
        throw new SearchServiceException(e);
    }

    return result;
}

From source file:nl.knaw.dans.dccd.application.services.DccdSearchService.java

License:Apache License

public DccdSearchResult search(String query, int offset, int limit) throws SearchServiceException {
    DccdSearchResult result = new DccdSearchResult();

    // max results should be bigger than 0
    if (limit < 1)
        throw new IllegalArgumentException("limit must be 1 or bigger");
    if (offset < 0)
        throw new IllegalArgumentException("offset must be 0 or bigger");

    List<String> resultIds = new ArrayList<String>(); // empty list

    Properties settings = DccdConfigurationService.getService().getSettings();
    final String protocol = settings.getProperty("solr.protocol");
    final String host = settings.getProperty("solr.host");
    final int port = Integer.parseInt(settings.getProperty("solr.port"));
    final String context = settings.getProperty("solr.context");

    // use Solr to find project with the given query
    // the REST interface?
    //final int limit = 100;

    //String protocol = "http";
    //String host = "localhost";//"dendro01.dans.knaw.nl";
    //int port = 8082;//80;
    //String context = "solr-example/select";
    String baseURLString = protocol + "://" + host + ":" + port + "/" + context;

    String responseString = "";

    URL solrSearch;/*from   ww  w . j ava  2s . c o  m*/
    //BufferedReader in = null;
    Scanner in = null;
    StringBuilder response = new StringBuilder();
    URLConnection fs = null;
    try {
        // Note: the query string should be url encoded?
        String requestUrlString = baseURLString + "/?q=" + query + "&version=2.2&start=" + offset + "&rows="
                + limit + "&indent=on" + "&debugQuery=true"; // debugging on TODO: remove in production!

        //"/?q=" + query + "&q.op=AND&version=2.2&start=" + offset + "&rows=" + limit + "&indent=on";

        // TODO:
        // What can we expect; HTTP response code: 400?
        // - why does this give an IO exception on openConnection
        logger.info("Solr search request: " + requestUrlString);
        solrSearch = new URL(requestUrlString);
        fs = solrSearch.openConnection();
        in = new Scanner(fs.getInputStream());
        while (in.hasNextLine()) {
            response.append(in.nextLine());
            response.append("\n");
        }
    } catch (MalformedURLException e) {
        // this really should not happen, the url is coded
        logger.debug("Malformed URL Exception while requesting Solr search");
        throw new RuntimeException(e);
    } catch (IOException e) {
        // Try to get an idea of what happened here...
        // HTTP response (errors can give indication about what went wrong)

        // get the error stream...
        if ((fs instanceof HttpURLConnection)) {
            try {
                String responseMsg = ((HttpURLConnection) fs).getResponseMessage();
                response.append(responseMsg);
                // set this as the result
                //result.setResponseString(response.toString());
            } catch (IOException e1) {
                // ignore
                logger.debug("Unable to get response message about IO exception");
                //e1.printStackTrace();
            }

            /* html page with the response
            InputStream err = ((HttpURLConnection)fs).getErrorStream();
            if (err != null) {
               in = new Scanner(err);
                 while (in.hasNextLine()) {
            response.append(in.nextLine());
            response.append("\n");
                 }
            }
            */
        }
        logger.debug("IO exception while reading Solr response: " + response);

        throw new SearchServiceException(response.toString(), e);
    }
    if (in != null)
        in.close();

    responseString = response.toString();
    // show response
    //logger.info("Response: \n" + responseString);

    // keep response for testing/debugging purposes
    result.setResponseString(responseString);

    // parse the xml string
    // note: maybe make this into separate function
    int numFound = 0;
    Document domDoc;
    try {
        domDoc = DocumentHelper.parseText(responseString);
        Element xmlResponse = domDoc.getRootElement();
        // get result element
        Element xmlResult = xmlResponse.element("result");

        //numFound
        //<result name="response" numFound="3" start="0">
        numFound = Integer.parseInt(xmlResult.attribute("numFound").getText(), 10);
        logger.info("Total hits: " + numFound);

        // for all doc elements
        for (Iterator<?> i = xmlResult.elementIterator("doc"); i.hasNext();) {
            Element docElement = (Element) i.next();
            // get str element with attribute name="PID"
            //Node node = docElement.selectSingleNode( "str[@name='PID']" );
            // tridas objects instead of projects;
            // using another ID and not the fedora object PID
            Node node = docElement.selectSingleNode("str[@name='ID']");
            if (node == null) {
                logger.warn("Found doc element without <str name=\"ID\" > subelement");
            } else {
                logger.info("Found: " + node.getText());
                resultIds.add(node.getText());
            }
        }
    } catch (DocumentException e) {
        //throw e;
        logger.debug("Document Exception while parsing xml response from Solr: " + responseString);
        throw new SearchServiceException(e);
    }

    // update results
    result.setResultItemIds(resultIds);
    result.setNumFound(numFound);

    return result;
}

From source file:nl.ru.cmbi.pisa.wrapper.PisaCachedWebDao.java

License:Apache License

/**
 * Gets the 3D rotation-translation biomolecule matrices from PISA.
 * <p>//  ww w . ja  va  2s. c o  m
 * These matrices detail how chains in the specified PDB entry should be manipulated to obtain desired the PISA
 * assembly.
 * 
 * @param rawPdbId
 *            the 4-letter PDB code we want the assembly of (e.g. "1crn")
 * @param setNr
 *            the PISA assembly set. "1" is most stable in solution, higher numbers increasingly unstable.
 * @param assemblyNr
 *            the substructure within an assembly. Note that structurally identical substructures get the
 *            same assemblyNr. This DAO ignores all but the first substructure. Ignored chains (those chains not
 *            needed to make this assembly) are listed in the {@link MatricesResult#ignoredChains} property of the
 *            returned result.
 * @return A compound result of the transformation matrices to apply and the ignored chains (I.E. those
 *         chains whose transformation lead to an identical substructure to the one returned). This result may be
 *         empty.
 * @throws IOException
 *             when web-fetching fails.
 */
@SuppressWarnings("unchecked")
public MatricesResult getMatrices(final String rawPdbId, final int setNr, final int assemblyNr)
        throws IOException {

    final String pdbId = rawPdbId.trim().toLowerCase();
    Document mmrInfo;
    try {
        mmrInfo = parseDocumentOf(getRawMultimerInfoSingle(pdbId));
    } catch (final DocumentException docex) {
        log.error("Problem parsing Pisa raw multimer info for {}, see debug level for details", pdbId);
        log.debug("Exception: ", docex);
        throw new IOException("Problem parsing multimer XML document", docex);
    }

    final List<ChainTransform> output = new ArrayList<ChainTransform>();
    final Set<String> ignoredChainIds = new HashSet<String>();

    try {
        // Unfortunately, multiple assemblies share the same <ID> subnode if they are structurally identical
        // So, we need indexing ("[1]") to get only the first of an identical set of assemblies
        // ('identical' meaning "structurally identical except for ChainIDs")
        // Sigh... reusing IDs for different things!
        final String matricesXpath = String.format(
                "(/pisa_multimers/pdb_entry[ pdb_code='%s' ]/asm_set[ ser_no=%d ]/assembly[ id=%d ])[1]/molecule",
                pdbId, setNr, assemblyNr);

        final List<Node> matrices = mmrInfo.selectNodes(matricesXpath);

        for (final Node node : matrices) {
            final ChainTransform ct = new ChainTransform(node.valueOf("chain_id"),
                    // X-row
                    (Double) node.numberValueOf("rxx"), (Double) node.numberValueOf("rxy"),
                    (Double) node.numberValueOf("rxz"), (Double) node.numberValueOf("tx"),
                    // Y-row
                    (Double) node.numberValueOf("ryx"), (Double) node.numberValueOf("ryy"),
                    (Double) node.numberValueOf("ryz"), (Double) node.numberValueOf("ty"),
                    // Z-row
                    (Double) node.numberValueOf("rzx"), (Double) node.numberValueOf("rzy"),
                    (Double) node.numberValueOf("rzz"), (Double) node.numberValueOf("tz"));
            if (ct.isUnity() && ct.isStationary()) {
                ct.setDuplication(false);
            } else {
                ct.setDuplication(true);
            }

            output.add(ct);
        }

        final String ignoredMatricesXpath = String.format(
                "(/pisa_multimers/pdb_entry[ pdb_code='%s' ]/asm_set[ ser_no=%d ]/assembly[ id=%d ])[position() > 1]/molecule/chain_id",
                pdbId, setNr, assemblyNr);
        final List<Node> ignoredChains = mmrInfo.selectNodes(ignoredMatricesXpath);

        for (final Node ignoredChain : ignoredChains) {
            ignoredChainIds.add(ignoredChain.getText());
        }

    } catch (final ClassCastException ccex) {
        log.error(
                "malformed XML response from PISA when getting matrices for assembly {}:{}.{}: expected list of matrix nodes, but obtained something else",
                new Object[] { pdbId, setNr, assemblyNr });
        throw new IOException("malformed XML response from PISA when getting matrices for assembly of " + pdbId
                + ": expected list of matrix nodes, but obtained something else", ccex);
    }

    return new MatricesResult(output, ignoredChainIds);
}

From source file:nl.tue.gale.ae.processor.xmlmodule.CreoleTextHandler.java

License:Open Source License

@SuppressWarnings("unchecked")
private void traverse(Element textElement) {
    boolean flat = ("true".equals(textElement.attributeValue("flat")));
    List<Element> elements = ImmutableList.copyOf((List<Element>) textElement.elements());
    for (Element element : elements) {
        textElement.content().add(textElement.content().indexOf(element),
                DocumentFactory.getInstance().createText("(% " + GaleUtil.serializeXML(element) + " %)"));
        textElement.remove(element);//w w w  .j  av  a 2  s  .  c  o m
    }
    textElement.normalize();
    List<Node> content = ImmutableList.copyOf((List<Node>) textElement.content());
    for (Node node : content)
        if (node.getNodeType() == Node.TEXT_NODE) {
            textElement.content().addAll(textElement.content().indexOf(node), parse(node.getText(), flat));
            textElement.content().remove(node);
        }
}

From source file:no.met.jtimeseries.parser.OceanForecastParseScheme.java

License:Open Source License

public void xmlTreeWalk(Element element) throws ParseException {
    for (int i = 0, size = element.nodeCount(); i < size; i++) {
        Node node = element.node(i);
        if (node instanceof Element) {
            if (((Element) node).getName().equals("begin")) {
                timeFrom = dateFormat.parse(node.getText());
            }// ww  w. j ava2  s .  co  m
            // read phenomena if it is inside forecast-period
            else if (forecastPeriod.inside(timeFrom))
                readPhenomenen((Element) node);
            xmlTreeWalk((Element) node);
        }
    }
}

From source file:nz.govt.natlib.ndha.common.dublincore.DublinCore.java

License:Open Source License

private String getXPathValue(String xPath) {
    Node node = m_document.selectSingleNode(xPath);
    if (node != null) {
        return node.getText();
    } else {/*from   w w w.  j  a va  2  s .c  om*/

        return null;
    }
}