Example usage for org.apache.pdfbox.pdmodel PDDocument load

List of usage examples for org.apache.pdfbox.pdmodel PDDocument load

Introduction

In this page you can find the example usage for org.apache.pdfbox.pdmodel PDDocument load.

Prototype

public static PDDocument load(byte[] input) throws IOException 

Source Link

Document

Parses a PDF.

Usage

From source file:cx.fbn.nevernote.gui.PDFPreview.java

License:Open Source License

public boolean setupPreview(String filePath, String appl, int pageNumber) {
    // Fix stupid Windows file separation characters
    String whichOS = System.getProperty("os.name");
    if (whichOS.contains("Windows")) {
        filePath = filePath.replace("\\", "/");
    }//from   ww w.  ja  va2  s.c o m
    if (appl.equals("pdf")) {

        PDDocument document = null;
        try {
            document = PDDocument.load(filePath);
            if (document.getNumberOfPages() <= pageNumber)
                return false;
            if (document.getDocumentCatalog().getAllPages().size() <= pageNumber)
                return false;
            PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(pageNumber);
            BufferedImage bi = page.convertToImage();

            File outputfile;
            outputfile = new File(filePath + ".png");
            ImageIO.write(bi, "png", outputfile);
            return true;

        } catch (IOException e1) {
            return false;
        }
    }
    return false;

}

From source file:cz.fi.muni.xkremser.editor.server.fedora.KrameriusImageSupport.java

License:Open Source License

/**
 * Read image.//from   www  . ja  v  a  2 s  .c o  m
 * 
 * @param url
 *        the url
 * @param type
 *        the type
 * @param page
 *        the page
 * @return the image
 * @throws IOException
 *         Signals that an I/O exception has occurred.
 */
public static Image readImage(URL url, ImageMimeType type, int page) throws IOException {
    if (type.javaNativeSupport()) {
        return ImageIO.read(url.openStream());
    } else if ((type.equals(ImageMimeType.DJVU)) || (type.equals(ImageMimeType.VNDDJVU))
            || (type.equals(ImageMimeType.XDJVU))) {
        com.lizardtech.djvu.Document doc = new com.lizardtech.djvu.Document(url);
        doc.setAsync(false);
        DjVuPage[] p = new DjVuPage[1];
        // read page from the document - index 0, priority 1, favorFast true
        int size = doc.size();
        if ((page != 0) && (page >= size)) {
            page = 0;
        }
        p[0] = doc.getPage(page, 1, true);
        p[0].setAsync(false);
        DjVuImage djvuImage = new DjVuImage(p, true);
        Rectangle pageBounds = djvuImage.getPageBounds(0);
        Image[] images = djvuImage.getImage(new JPanel(), new Rectangle(pageBounds.width, pageBounds.height));
        if (images.length == 1) {
            Image img = images[0];
            return img;
        } else
            return null;
    } else if (type.equals(ImageMimeType.PDF)) {
        PDDocument document = null;
        try {
            document = PDDocument.load(url.openStream());
            int resolution = 96;
            List<?> pages = document.getDocumentCatalog().getAllPages();
            PDPage pdPage = (PDPage) pages.get(page);
            BufferedImage image = pdPage.convertToImage(BufferedImage.TYPE_INT_RGB, resolution);
            return image;
        } finally {
            if (document != null) {
                document.close();
            }
        }
    } else
        throw new IllegalArgumentException("unsupported mimetype '" + type.getValue() + "'");
}

From source file:cz.mzk.editor.server.fedora.KrameriusImageSupport.java

License:Open Source License

/**
 * Read image.//from w  w  w . j  a  va 2 s  . com
 *
 * @param url
 *        the url
 * @param type
 *        the type
 * @param page
 *        the page
 * @return the image
 * @throws IOException
 *         Signals that an I/O exception has occurred.
 */
public static Image readImage(URL url, ImageMimeType type, int page) throws IOException {
    if (type.javaNativeSupport()) {
        return ImageIO.read(url.openStream());
    } else if ((type.equals(ImageMimeType.DJVU)) || (type.equals(ImageMimeType.VNDDJVU))
            || (type.equals(ImageMimeType.XDJVU))) {
        com.lizardtech.djvu.Document doc = new com.lizardtech.djvu.Document(url);
        doc.setAsync(false);
        DjVuPage[] p = new DjVuPage[1];
        // read page from the document - index 0, priority 1, favorFast true
        int size = doc.size();
        if ((page != 0) && (page >= size)) {
            page = 0;
        }
        p[0] = doc.getPage(page, 1, true);
        p[0].setAsync(false);
        DjVuImage djvuImage = new DjVuImage(p, true);
        Rectangle pageBounds = djvuImage.getPageBounds(0);
        Image[] images = djvuImage.getImage(new JPanel(), new Rectangle(pageBounds.width, pageBounds.height));
        if (images.length == 1) {
            Image img = images[0];
            return img;
        } else
            return null;
    } else if (type.equals(ImageMimeType.PDF)) {
        try (PDDocument document = PDDocument.load(url.openStream());) {

            PDFRenderer pdfRenderer = new PDFRenderer(document);
            int resolution = 96;
            BufferedImage image = pdfRenderer.renderImageWithDPI(page, resolution, ImageType.RGB);
            return image;
        }
    } else
        throw new IllegalArgumentException("unsupported mimetype '" + type.getValue() + "'");
}

From source file:cz.mzk.editor.server.newObject.CreateObject.java

License:Open Source License

/**
 * Insert foxml./*  www. jav  a 2 s.com*/
 *
 * @param node    the node
 * @param mods    the mods
 * @param dc      the dc
 * @param attempt the attempt
 * @return the string
 * @throws CreateObjectException the create object exception
 */
private String insertFOXML(NewDigitalObject node, Document mods, Document dc, int attempt)
        throws CreateObjectException {
    if (attempt == 0) {
        throw new CreateObjectException("max number of attempts has been reached");
    }

    boolean isPdf = node.getModel().getTopLevelType() != null
            && (node.getChildren() == null || node.getChildren().size() == 0) && node.getPath() != null;

    if (isPdf && attempt == Constants.MAX_NUMBER_OF_INGEST_ATTEMPTS) {
        PDDocument document = null;
        String newPdfPath = null;

        try {
            newPdfPath = imageResolverDAO.getNewImageFilePath(node.getPath());
            if (!newPdfPath.endsWith(Constants.PDF_EXTENSION)) {
                newPdfPath = newPdfPath.concat(Constants.PDF_EXTENSION);
            }
            document = PDDocument.load(new File(newPdfPath));
            int numberOfPages = document.getNumberOfPages();
            LOGGER.warn(newPdfPath + ": Count of pages is 0");
            if (numberOfPages > 0 && node.getPageIndex() > numberOfPages)
                throw new CreateObjectException("The number of page: " + node.getPageIndex()
                        + " to be used for thumbnail is bigger than count of pages in the file: "
                        + numberOfPages);

        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException("Unable to read the pdf file: " + newPdfPath);
        } catch (DatabaseException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        } finally {
            if (document != null)
                try {
                    document.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage());
                    e.printStackTrace();
                    throw new CreateObjectException("Unable to close the pdf file: " + newPdfPath);
                }
        }
    }

    if (processedPages.containsKey(node.getPath())) {
        node.setExist(true);
        node.setUuid(processedPages.get(node.getPath()));
    }
    if (processedTracks.containsKey(node.getPath())) {
        node.setExist(true);
        node.setUuid(processedTracks.get(node.getPath()));
    }
    if (node.getExist()) {
        // do not create, but append only 
        List<NewDigitalObject> childrenToAdd = node.getChildren();
        if (childrenToAdd != null && !childrenToAdd.isEmpty()) {
            for (NewDigitalObject child : childrenToAdd) {
                if (!child.getExist()) {
                    String uuid = insertFOXML(child, mods, dc);
                    child.setUuid(Constants.FEDORA_UUID_PREFIX + uuid);
                    append(node, child);
                } else {
                    insertFOXML(child, mods, dc);
                }
            }
        }
        return node.getUuid();
    }
    FoxmlBuilder builder = FOXMLBuilderMapping.getBuilder(node);
    if (builder == null) {
        throw new CreateObjectException("unknown type " + node.getModel());
    }

    if (node.getUuid() == null || attempt != Constants.MAX_NUMBER_OF_INGEST_ATTEMPTS) {

        node.setUuid(FoxmlUtils.getRandomUuid());

        if (topLevelUuid == null) {
            topLevelUuid = node.getUuid();
            try {
                digitalObjectDAO.insertNewDigitalObject(node.getUuid(), node.getModel().getValue(),
                        node.getName(), inputDirPath, node.getUuid(), false, userId);
            } catch (DatabaseException e) {
                LOGGER.error("DB ERROR!!!: " + e.getMessage() + ": " + e);
                e.printStackTrace();
            }
        }
    }
    boolean isPage = node.getModel() == DigitalObjectModel.PAGE;
    boolean isTrack = node.getModel() == DigitalObjectModel.TRACK;
    boolean isSoundUnit = node.getModel() == DigitalObjectModel.SOUND_UNIT;

    builder.setSignature(node.getSignature());
    builder.setBase(base);
    builder.setUuid(node.getUuid());
    builder.setDcXmlContent(dc);
    builder.setModsXmlContent(mods);
    builder.setBundle(node.getBundle());
    builder.setType(node.getType());
    builder.setPolicy(node.getVisible() ? Policy.PUBLIC : Policy.PRIVATE);
    builder.setDateOrIntPartName(node.getDateOrIntPartName());
    builder.setNoteOrIntSubtitle(node.getNoteOrIntSubtitle());
    if (!isPage) {
        builder.setPartNumber(node.getPartNumberOrAlto());
        builder.setAditionalInfo(node.getAditionalInfoOrOcr());
    }
    if (node.getModel() == DigitalObjectModel.PAGE) {
        builder.setPageIndex(node.getPageIndex());
    }

    List<NewDigitalObject> childrenToAdd = node.getChildren();
    if (childrenToAdd != null && !childrenToAdd.isEmpty()) {
        List<RelsExtRelation> relations = builder.getChildren();
        for (NewDigitalObject child : childrenToAdd) {
            if (!child.getExist()) {
                String uuid = insertFOXML(child, mods, dc);
                child.setUuid(uuid);
            }
            relations.add(new RelsExtRelation(child.getUuid(),
                    NamedGraphModel.getRelationship(node.getModel(), child.getModel()), child.getName()));
        }
    }
    String imageUrl = null;
    String newFilePath = null;

    if (isPage || isSoundUnit) {
        String url = config.getImageServerUrl();
        url = addSlash(url);
        if (!url.startsWith("http://")) {
            if (url.startsWith("https://")) {
                url = url.substring(8);
            }
            url = "http://" + url;
        }
        if (!isSysno(sysno)) {
            imageUrl = url + "meditor" + getPathFromNonSysno(sysno) + (node.getUuid());
            newFilePath = addSlash(config.getImageServerUnknown()) + getPathFromNonSysno(sysno)
                    + node.getUuid();
        } else {
            String basePath = "";
            if (base != null && !"".equals(base)) {
                basePath = base.toLowerCase() + "/";
            }
            imageUrl = url + basePath + getSysnoPath(sysno) + (node.getUuid());
            newFilePath = addSlash(config.getImageServerKnown()) + basePath + getSysnoPath(sysno)
                    + node.getUuid();
        }

        builder.setImageUrl(imageUrl);
    } else if (isTrack) {
        String url = config.getRecordingServerUrl();
        url = addSlash(url);
        if (!url.startsWith("http://")) {
            if (url.startsWith("https://")) {
                url = url.substring(8);
            }
            url = "http://" + url;
        }
        String soundUrl;

        if (!isSysno(sysno)) {
            soundUrl = url + "meditor" + getPathFromNonSysno(sysno) + (node.getUuid());
            newFilePath = addSlash(config.getRecordingServerUnknown()) + getPathFromNonSysno(sysno)
                    + node.getUuid();
        } else {
            String basePath = "";
            if (base != null && !"".equals(base)) {
                basePath = base.toLowerCase() + "/";
            }
            newFilePath = addSlash(config.getRecordingServerKnown()) + basePath + getSysnoPath(sysno)
                    + node.getUuid();
            soundUrl = url + basePath + getSysnoPath(sysno) + (node.getUuid());
        }

        //No lossless audio on the input queue
        String soundPath = null;
        try {
            soundPath = imageResolverDAO.getNewImageFilePath(node.getPath());
        } catch (DatabaseException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        }
        if (builder instanceof TrackBuilder) {
            if (new File(soundPath + Constants.AUDIO_MIMETYPES.WAV_MIMETYPE.getExtension()).exists()) {
                ((TrackBuilder) builder).wavProvided(true);
            }
        }
        builder.setImageUrl(soundUrl);

    }

    builder.createDocument();

    String foxmlRepresentation = builder.getDocument(false);
    boolean success = IngestUtils.ingest(foxmlRepresentation, node.getName(), node.getUuid(),
            node.getModel().getValue(), topLevelUuid, inputDirPath);

    if (success)
        ingestedObjects.add(node.getUuid());

    if ((isPage || isSoundUnit) && success) {
        // TODO: StringBuffer
        boolean copySuccess;
        String newImagePath = null;
        try {
            newImagePath = imageResolverDAO.getNewImageFilePath(node.getPath());
            if (newImagePath == null) {
                throw new CreateObjectException("Unkown file path for " + node.getPath());
            } else if (!newImagePath.endsWith(Constants.JPEG_2000_EXTENSION)) {
                newImagePath = newImagePath.concat(Constants.JPEG_2000_EXTENSION);
            }

            copySuccess = IOUtils.copyFile(newImagePath, newFilePath + Constants.JPEG_2000_EXTENSION);

            if (copySuccess && LOGGER.isInfoEnabled()) {
                LOGGER.info("image " + newImagePath + "  was copied to  " + newFilePath
                        + Constants.JPEG_2000_EXTENSION);
            }
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        } catch (DatabaseException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        }
    }

    if (isPage) {
        String ocrPath = node.getAditionalInfoOrOcr();
        if (ocrPath != null && !"".equals(ocrPath)) {
            insertManagedDatastream(DATASTREAM_ID.TEXT_OCR, node.getUuid(), ocrPath, true, "text/plain");
        }

        String altoPath = node.getPartNumberOrAlto();
        if (altoPath != null && !"".equals(altoPath)) {
            insertManagedDatastream(DATASTREAM_ID.ALTO, node.getUuid(), altoPath, true, "text/xml");
        }
    }

    if (isTrack && success) {
        boolean copySuccessWav;
        boolean copySuccessMp3;
        boolean copySuccessOgg;
        String soundPath;
        try {
            soundPath = imageResolverDAO.getNewImageFilePath(node.getPath());
            soundPath = soundPath.substring(0, soundPath.length() - 4);

            if (new File(soundPath + Constants.AUDIO_MIMETYPES.WAV_MIMETYPE.getExtension()).exists()) {
                copySuccessWav = IOUtils.copyFile(
                        soundPath + Constants.AUDIO_MIMETYPES.WAV_MIMETYPE.getExtension(),
                        newFilePath + Constants.AUDIO_MIMETYPES.WAV_MIMETYPE.getExtension());
            }

            copySuccessMp3 = IOUtils.copyFile(soundPath + Constants.AUDIO_MIMETYPES.MP3_MIMETYPE.getExtension(),
                    newFilePath + Constants.AUDIO_MIMETYPES.MP3_MIMETYPE.getExtension());
            copySuccessOgg = IOUtils.copyFile(soundPath + Constants.AUDIO_MIMETYPES.OGG_MIMETYPE.getExtension(),
                    newFilePath + Constants.AUDIO_MIMETYPES.OGG_MIMETYPE.getExtension());

        } catch (DatabaseException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
            throw new CreateObjectException(e.getMessage(), e);
        }
    }

    if (!success) {
        insertFOXML(node, mods, dc, attempt - 1);
    } else if (isPdf) {
        handlePdf(node);
    }
    if (node.getModel() == DigitalObjectModel.PAGE)
        processedPages.put(node.getPath(), node.getUuid());
    if (node.getModel() == DigitalObjectModel.TRACK)
        processedTracks.put(node.getPath(), node.getUuid());

    return node.getUuid();
}

From source file:cz.mzk.editor.server.newObject.CreateObject.java

License:Open Source License

/**
 * Creates the thumb prew from pdf./*  w w w  .j  a v  a  2 s. c o  m*/
 *
 * @param dsId                 the ds id
 * @param pathWithoutExtension the path without extension
 * @param thumbPageNum         the thumb page num
 * @param uuid                 the uuid
 * @param width            the image width
 * @throws CreateObjectException the create object exception
 */
private void createThumbPrewFromPdf(DATASTREAM_ID dsId, String pathWithoutExtension, int thumbPageNum,
        String uuid, int width) throws CreateObjectException {
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PDDocument document = PDDocument
                    .load(Files.newInputStream(Paths.get(pathWithoutExtension + Constants.PDF_EXTENSION)));) {
        long startTime = System.currentTimeMillis();
        // convert pdf to image
        PDFRenderer pdfRenderer = new PDFRenderer(document);
        BufferedImage imageFull = pdfRenderer.renderImageWithDPI(thumbPageNum - 1, 72, ImageType.RGB);

        // resize image
        int height = (int) (imageFull.getHeight() * (double) width / imageFull.getWidth());
        BufferedImage preview = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D gPreview = preview.createGraphics();
        gPreview.drawImage(imageFull, 0, 0, width, height, null);
        gPreview.dispose();
        ImageIO.write(preview, "jpeg", outputStream);
        LOGGER.debug("Duration of " + pathWithoutExtension + Constants.PDF_EXTENSION + "conversion was "
                + (System.currentTimeMillis() - startTime) + "ms");

        // upload
        Client client = new ResteasyClientBuilder()
                .register(new BasicAuthentication(config.getFedoraLogin(), config.getFedoraPassword())).build();
        String prepUrl = "/objects/" + (uuid.contains("uuid:") ? uuid : "uuid:".concat(uuid)) + "/datastreams/"
                + dsId.getValue() + "?controlGroup=M&versionable=true&dsState=A&mimeType=image/jpeg";
        WebTarget target = client.target(config.getFedoraHost().concat(prepUrl));
        target.request()
                .post(Entity.entity(outputStream.toByteArray(), MediaType.APPLICATION_OCTET_STREAM_TYPE));
    } catch (IOException e) {
        LOGGER.error(e.getMessage());
        throw new CreateObjectException("Unable to run the convert proces on the pdf file: "
                + pathWithoutExtension + Constants.PDF_EXTENSION);

    }
}

From source file:ddf.catalog.transformer.input.pdf.PDDocumentGeneratorImpl.java

License:Open Source License

@Override
public PDDocument apply(InputStream inputStream) throws IOException {
    return PDDocument.load(inputStream);
}

From source file:de.berber.kindle.annotator.lib.PDFAnnotator.java

License:Apache License

@SuppressWarnings("unchecked")
public boolean run() {
    // read all annotations
    final List<Annotation> annotations = new KindleAnnotationReader(cc, pdfFile).read();

    if (annotations.size() == 0) {
        return true;
    }/*from www .j a  v a 2 s .  c o  m*/

    PDDocument document = null;
    // annotate pdf
    try {
        document = PDDocument.load(pdfFile);

        //inDocument.decrypt(pass);
        // get outline for bookmarks
        PDDocumentOutline documentOutline = document.getDocumentCatalog().getDocumentOutline();

        if (documentOutline == null) {
            // if there is no document outline we have to create a new one.
            documentOutline = new PDDocumentOutline();
            document.getDocumentCatalog().setDocumentOutline(documentOutline);
        }

        assert documentOutline != null;

        // convert annotations for each page
        int pageNumber = 0;
        for (PDPage page : (List<PDPage>) document.getDocumentCatalog().getAllPages()) {
            for (final Annotation dxAnn : annotations) {
                dxAnn.toPDAnnotation(pageNumber, documentOutline, page);
            }

            pageNumber++;
        }

        //inDocument.setAllSecurityToBeRemoved(true);
        document.save(outFile.toString());
    } catch (FileNotFoundException e) {
        LOG.error("Could not find input file " + pdfFile);
        return false;
    } catch (IOException e) {
        LOG.error("IOError while writing result file " + outFile);
        return false;
    } catch (COSVisitorException e) {
        LOG.error("PDFBox error while storing result file " + outFile);
        return false;
    } finally {
        if (document != null) {
            try {
                document.close();
            } catch (IOException e) {
                LOG.error("Error while closing PDF document " + pdfFile);
            }
        }
    }

    return true;
}

From source file:de.dominicscheurer.quicktxtview.view.FileViewerController.java

License:Open Source License

private String getFileContentsInDirectoryHTML(File directory) {
    final StringBuilder sb = new StringBuilder();
    final File[] files = listFiles(directory);

    if (files == null) {
        return "";
    }//from   ww w . ja  v  a  2 s  .c  o  m

    sb.append("<html>").append("<body>").append("<style type=\"text/css\">").append(fileTreeViewerCSS)
            .append("</style>");
    for (File file : files) {
        try {
            String contentsString;

            if (file.getName().endsWith(".pdf")) {
                final PDDocument doc = PDDocument.load(file);
                final StringWriter writer = new StringWriter();
                new PDFText2HTML("UTF-8").writeText(doc, writer);

                contentsString = writer.toString();

                writer.close();
                doc.close();
            } else {
                byte[] encoded = Files.readAllBytes(file.toPath());
                contentsString = new String(encoded, charset);

                contentsString = contentsString.replace("<", "&lt;");
                contentsString = contentsString.replace(">", "&gt;");
                contentsString = contentsString.replace("\n", "<br/>");
            }

            sb.append("<div class=\"entry\"><h3>").append(file.getName()).append("</h3>")
                    .append("<div class=\"content\">").append(contentsString).append("</div>").append("</div>");
        } catch (IOException e) {
        }
    }
    sb.append("</body></html>");

    return sb.toString();
}

From source file:de.haber.pdfbox.CountPages.java

License:Apache License

/**
 * Counts the number of pages from a given <b>input</b> file.
 * /*from   w  ww .j  av a 2  s.c o m*/
 * @param input
 *            input pdf file that has to exist and must be a file.
 * @return number of pages from the given pdf file.
 * @throws IOException
 *             If there is an error reading from the given file.
 * @throws IllegalArgumentException
 *             If the <b>file</b> does not exist or is not a file.
 */
public int count(File input) throws IOException {
    checkArgument(input.exists() && input.isFile(), "The input pdf has to exist and must be a file.");
    PDDocument doc = PDDocument.load(input);
    int res = doc.getNumberOfPages();
    doc.close();
    return res;
}

From source file:de.ilias.services.lucene.index.file.PDFBoxPDFHandler.java

License:Open Source License

/**
 * @throws IOException //from w w w  . ja  v  a  2s .c  o m
 * @see de.ilias.services.lucene.index.file.FileHandler#getContent(java.io.InputStream)
 */
public String getContent(InputStream is) throws FileHandlerException {

    PDDocument pddo = null;
    PDFTextStripper stripper = null;
    String str = new String("");

    try {

        pddo = PDDocument.load(is);

        if (pddo.isEncrypted()) {
            logger.warn("PDF Document is encrypted. Trying empty password...");
            return "";
        }
        stripper = new PDFTextStripper();
        str = stripper.getText(pddo);
    } catch (NumberFormatException e) {
        logger.warn("Invalid PDF version number given. Aborting");
    } catch (IOException e) {
        logger.warn(e.getMessage());
        throw new FileHandlerException(e);
    } catch (Exception e) {
        logger.error(e.getMessage());
        throw new FileHandlerException(e);
    } finally {
        try {
            if (pddo != null)
                pddo.close();
        } catch (IOException e) {
            ;
        }
    }
    return str;
}