public static URI relativizeURI()

in poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java [269:384]


    public static URI relativizeURI(URI sourceURI, URI targetURI, boolean msCompatible) {
        StringBuilder retVal = new StringBuilder();
        String[] segmentsSource = sourceURI.getPath().split("/", -1);
        String[] segmentsTarget = targetURI.getPath().split("/", -1);

        // If the source URI is empty
        if (segmentsSource.length == 0) {
            throw new IllegalArgumentException(
                    "Can't relativize an empty source URI !");
        }

        // If target URI is empty
        if (segmentsTarget.length == 0) {
            throw new IllegalArgumentException(
                    "Can't relativize an empty target URI !");
        }

        // If the source is the root, then the relativized
        //  form must actually be an absolute URI
        if(sourceURI.toString().equals("/")) {
            String path = targetURI.getPath();
            if(msCompatible && path.length() > 0 && path.charAt(0) == '/') {
                try {
                    targetURI = new URI(path.substring(1));
                } catch (Exception e) {
                    LOG.atWarn().withThrowable(e).log("Failed to relativize");
                    return null;
                }
            }
            return targetURI;
        }


        // Relativize the source URI against the target URI.
        // First up, figure out how many steps along we can go
        // and still have them be the same
        int segmentsTheSame = 0;
        for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) {
            if (segmentsSource[i].equals(segmentsTarget[i])) {
                // Match so far, good
                segmentsTheSame++;
            } else {
                break;
            }
        }

        // If we didn't have a good match or at least except a first empty element
        if ((segmentsTheSame == 0 || segmentsTheSame == 1) &&
                segmentsSource[0].isEmpty() && segmentsTarget[0].isEmpty()) {
            for (int i = 0; i < segmentsSource.length - 2; i++) {
                retVal.append("../");
            }
            for (int i = 0; i < segmentsTarget.length; i++) {
                if (segmentsTarget[i].isEmpty())
                    continue;
                retVal.append(segmentsTarget[i]);
                if (i != segmentsTarget.length - 1)
                    retVal.append("/");
            }

            try {
                return new URI(retVal.toString());
            } catch (Exception e) {
                LOG.atWarn().withThrowable(e).log("Failed to relativize");
                return null;
            }
        }

        // Special case for where the two are the same
        if (segmentsTheSame == segmentsSource.length
                && segmentsTheSame == segmentsTarget.length) {
            if(sourceURI.equals(targetURI)){
                // if source and target are the same they should be resolved to the last segment,
                // Example: if a slide references itself, e.g. the source URI is
                // "/ppt/slides/slide1.xml" and the targetURI is "slide1.xml" then
                // this it should be relativized as "slide1.xml", i.e. the last segment.
                retVal.append(segmentsSource[segmentsSource.length - 1]);
            }

        } else {
            // Matched for so long, but no more

            // Do we need to go up a directory or two from
            // the source to get here?
            // (If it's all the way up, then don't bother!)
            if (segmentsTheSame == 1) {
                retVal.append("/");
            } else {
                for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) {
                    retVal.append("../");
                }
            }

            // Now go from here on down
            for (int j = segmentsTheSame; j < segmentsTarget.length; j++) {
                if (retVal.length() > 0
                        && retVal.charAt(retVal.length() - 1) != '/') {
                    retVal.append("/");
                }
                retVal.append(segmentsTarget[j]);
            }
        }

        // if the target had a fragment then append it to the result
        String fragment = targetURI.getRawFragment();
        if (fragment != null) {
            retVal.append("#").append(fragment);
        }

        try {
            return new URI(retVal.toString());
        } catch (Exception e) {
            LOG.atWarn().withThrowable(e).log("Failed to relativize");
            return null;
        }
    }