Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2015-2022 Igor A. Maznitsa
*
* 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.
*/
package com.igormaznitsa.mindmap.model;
import static java.util.Objects.requireNonNull;
import java.io.File;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
* URI wrapper to be used in bounds of mind map.
*/
public class MMapURI implements Serializable {
public static final long serialVersionUID = 27896411234L;
private static final Properties EMPTY = new Properties();
private final URI uri;
private final Properties parameters;
private final boolean fileUriFlag;
/**
* Constructor.
*
* @param uri uri as string to be wrapped, must not be null
* @throws URISyntaxException thrown if malformed URI format
*/
public MMapURI(final String uri) throws URISyntaxException {
this(new URI(uri));
}
/**
* Constructor.
*
* @param uri uri to be wrapped, must not be null
* @throws URISyntaxException thrown if malformed URI format
*/
public MMapURI(final URI uri) throws URISyntaxException {
this.fileUriFlag = requireNonNull(uri).getScheme() == null ||
uri.getScheme().equalsIgnoreCase("file");
final URI preparedURI;
final String queryString = uri.getRawQuery();
if (queryString != null) {
this.parameters = ModelUtils.extractQueryPropertiesFromURI(uri);
if (this.fileUriFlag) {
final String uriAsString = uri.toString();
final int queryStart = uriAsString.lastIndexOf('?');
preparedURI =
new URI(queryStart >= 0 ? uriAsString.substring(0, queryStart) : uriAsString);
} else {
preparedURI = uri;
}
} else {
this.parameters = EMPTY;
preparedURI = uri;
}
this.uri = preparedURI;
}
private MMapURI(
final URI uri,
final boolean isFile,
final Properties properties
) {
this.uri = uri;
this.fileUriFlag = isFile;
this.parameters = properties == null ? new Properties() : (Properties) properties.clone();
}
/**
* Create from file.
*
* @param baseFolder base folder, can be null
* @param file target file, must not be null
* @param parameters optional parameters for URI, can be null
*/
public MMapURI(
final File baseFolder,
final File file,
final Properties parameters
) {
this.fileUriFlag = true;
this.parameters = new Properties();
if (parameters != null && !parameters.isEmpty()) {
this.parameters.putAll(parameters);
}
final Path filePath = file.toPath();
if (baseFolder == null) {
this.uri = ModelUtils.toURI(filePath);
} else {
final Path basePath = baseFolder.toPath();
if (basePath.isAbsolute()) {
final Path path = filePath.startsWith(basePath) ? basePath.relativize(filePath) : filePath;
this.uri = ModelUtils.toURI(path);
} else {
this.uri = ModelUtils.toURI(filePath);
}
}
}
private static String extractHost(final URI uri) {
String host = uri.getHost();
if (host == null) {
final String schemeSpecific = uri.getSchemeSpecificPart();
if (schemeSpecific != null && schemeSpecific.startsWith("//")) {
host = "";
}
}
return host;
}
/**
* Create from file path
*
* @param baseFolder base folder, can be null
* @param filePath file path, must not be null
* @param properties optional properties, can be null
* @return created URI link, must not be null
* @throws URISyntaxException thrown if errors with URI format
*/
@SuppressWarnings("ConstantConditions")
public static MMapURI makeFromFilePath(
final File baseFolder,
final String filePath,
final Properties properties
) throws URISyntaxException {
return new MMapURI(baseFolder, ModelUtils.makeFileForPath(filePath), properties);
}
@Override
public int hashCode() {
return this.uri.hashCode() ^ (this.fileUriFlag ? 1 : 0) ^ (31 * this.parameters.size());
}
@Override
public boolean equals(final Object that) {
if (that == null) {
return false;
}
if (this == that) {
return true;
}
if (that instanceof MMapURI) {
final MMapURI thatURI = (MMapURI) that;
if (this.parameters.size() != thatURI.parameters.size()) {
return false;
}
for (final String s : this.parameters.stringPropertyNames()) {
if (!thatURI.parameters.containsKey(s)) {
return false;
}
if (!this.parameters.getProperty(s).equals(thatURI.parameters.getProperty(s))) {
return false;
}
}
return this.uri.equals(thatURI.uri);
} else {
return false;
}
}
/**
* Make URI link with replaced base in path.
*
* @param replaceHost if true then host should be replaced
* @param newBase new base for the link
* @param numberOfResourceItems number of items to replace , last is zero
* @return new URI with replaced base, must not be null
* @throws URISyntaxException thrown if problem with URI
*/
public MMapURI replaceBaseInPath(
final boolean replaceHost,
final URI newBase,
int numberOfResourceItems
)
throws URISyntaxException {
final String newUriPath = newBase.getPath();
final String[] splitNewPath = newUriPath.split("\\/");
final String[] splitOldPath = this.uri.getPath().split("\\/");
final List resultPath = new ArrayList<>(Arrays.asList(splitNewPath));
numberOfResourceItems = numberOfResourceItems + 1;
int oldPathIndex = splitOldPath.length - numberOfResourceItems;
while (oldPathIndex < splitOldPath.length) {
if (oldPathIndex >= 0) {
resultPath.add(splitOldPath[oldPathIndex]);
}
oldPathIndex++;
}
final StringBuilder buffer = new StringBuilder();
for (int i = 0; i < resultPath.size(); i++) {
if (i > 0) {
buffer.append('/');
}
buffer.append(resultPath.get(i));
}
final URI newURI = new URI(replaceHost ? newBase.getScheme() : this.uri.getScheme(),
replaceHost ? newBase.getUserInfo() : this.uri.getUserInfo(),
replaceHost ? extractHost(newBase) : extractHost(this.uri),
replaceHost ? newBase.getPort() : this.uri.getPort(),
buffer.toString(),
this.uri.getQuery(),
this.uri.getFragment()
);
return new MMapURI(newURI, this.fileUriFlag, this.parameters);
}
/**
* Make new URI with replaced name.
*
* @param newName new name, must not be null
* @return new URI, must not be null
* @throws URISyntaxException if problems with URI syntax
*/
public MMapURI replaceName(final String newName) throws URISyntaxException {
final MMapURI result;
final String normalizedName = ModelUtils.escapeURIPath(newName).replace('\\', '/');
final String[] parsedNormalized = normalizedName.split("\\/");
final String[] parsedCurrentPath = this.uri.getPath().split("\\/");
final int baseLength = Math.max(0, parsedCurrentPath.length - parsedNormalized.length);
final StringBuilder buffer = new StringBuilder();
for (int i = 0; i < baseLength; i++) {
if (i > 0) {
buffer.append('/');
}
buffer.append(parsedCurrentPath[i]);
}
for (int i = 0; i < parsedNormalized.length; i++) {
if ((i == 0 && buffer.length() > 0) || i > 0) {
buffer.append('/');
}
buffer.append(parsedNormalized[i]);
}
result = new MMapURI(new URI(
this.uri.getScheme(),
this.uri.getUserInfo(),
extractHost(this.uri),
this.uri.getPort(),
buffer.toString(),
this.uri.getQuery(),
this.uri.getFragment()), this.fileUriFlag, parameters);
return result;
}
/**
* Convert into URI.
*
* @return converted URI, must not be null
*/
public URI asURI() {
if (this.fileUriFlag) {
try {
return new URI(this.uri.toASCIIString() + (this.parameters.isEmpty() ? "" :
'?' + ModelUtils.makeQueryStringForURI(this.parameters)));
} catch (URISyntaxException ex) {
throw new Error("Unexpected error during URI conversion");
}
} else {
return this.uri;
}
}
/**
* Get resource name with extension
*
* @return found resource name found before last slash
* @since 1.6.8
*/
public String getResourceName() {
String text = this.uri.getPath();
final int lastSlash = text.lastIndexOf('/');
if (lastSlash >= 0) {
text = text.substring(lastSlash + 1);
}
return text;
}
/**
* Get resource extension
*
* @return extension of the resource, can't be null, be empty if there is no extension
*/
public String getExtension() {
String text = this.getResourceName();
String result = "";
if (!text.isEmpty()) {
final int dotIndex = text.lastIndexOf('.');
if (dotIndex >= 0) {
result = text.substring(dotIndex + 1);
}
}
return result;
}
/**
* Convert int pstring.
*
* @param ascII if true then convert into ASCII string
* @param addPropertiesAsQuery if true then properties will be added as query
* @return string created from the URI object, must not be null
*/
public String asString(final boolean ascII, final boolean addPropertiesAsQuery) {
if (this.fileUriFlag) {
return (ascII ? this.uri.toASCIIString() : this.uri.toString()) +
(!addPropertiesAsQuery || this.parameters.isEmpty() ? "" :
'?' + ModelUtils.makeQueryStringForURI(this.parameters));
} else {
return ascII ? this.uri.toASCIIString() : this.uri.toString();
}
}
/**
* Get as file.
*
* @param baseFolder base folder if presented, can be null
* @return file representation, must not be null
*/
public File asFile(final File baseFolder) {
final File result;
if (this.uri.isAbsolute()) {
result = ModelUtils.toFile(this.uri);
} else {
try {
result = new File(baseFolder,
URLDecoder.decode(this.uri.getPath(), StandardCharsets.UTF_8.name()));
} catch (UnsupportedEncodingException ex) {
throw new Error("Unexpected error", ex);
}
}
return result;
}
/**
* Get URI parameters.
*
* @return parameters, must be null
*/
public Properties getParameters() {
return this.parameters;
}
/**
* Check that URI is absolute one
*
* @return true if the URI is absolute one, false for relative one
*/
public boolean isAbsolute() {
return this.uri.isAbsolute();
}
@Override
public String toString() {
return asString(false, true);
}
}