/* * Copyright (c) 2020 Dzikoysk * * 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 org.panda_lang.reposilite.metadata; import io.vavr.collection.Stream; import org.panda_lang.reposilite.utils.FilesUtils; import org.panda_lang.utilities.commons.StringUtils; import org.panda_lang.utilities.commons.collection.Pair; import org.panda_lang.utilities.commons.text.ContentJoiner; import java.io.File; import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Locale; import java.util.function.Function; import java.util.function.Predicate; public final class MetadataUtils { private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss") .withLocale(Locale.getDefault()) .withZone(ZoneOffset.UTC); private MetadataUtils() { } public static File[] toSortedBuilds(File artifactDirectory) { return Stream.of(FilesUtils.listFiles(artifactDirectory)) .filter(File::isFile) .filter(file -> file.getName().endsWith(".pom")) .transform(stream -> toSorted(stream, File::getName, File::isDirectory)) .toJavaArray(File[]::new); } public static File[] toFiles(File directory) { return Stream.of(FilesUtils.listFiles(directory)) .filter(File::isFile) .transform(stream -> toSorted(stream, File::getName, File::isDirectory)) .toJavaArray(File[]::new); } public static File[] toSortedVersions(File artifactDirectory) { return Stream.of(FilesUtils.listFiles(artifactDirectory)) .filter(File::isDirectory) .transform(stream -> toSorted(stream, File::getName, File::isDirectory)) .toJavaArray(File[]::new); } protected static String[] toSortedIdentifiers(String artifact, String version, File[] builds) { return Stream.of(builds) .map(build -> toIdentifier(artifact, version, build)) .filterNot(StringUtils::isEmpty) .distinct() .transform(stream -> toSorted(stream, Function.identity(), identifier -> true)) .toJavaArray(String[]::new); } protected static File[] toBuildFiles(File artifactDirectory, String identifier) { return Stream.of(FilesUtils.listFiles(artifactDirectory)) .filter(file -> file.getName().contains(identifier + ".") || file.getName().contains(identifier + "-")) .filterNot(file -> file.getName().endsWith(".md5")) .filterNot(file -> file.getName().endsWith(".sha1")) .transform(stream -> toSorted(stream, File::getName, File::isDirectory)) .toJavaArray(File[]::new); } public static <T> Stream<T> toSorted(Stream<T> stream, Function<T, String> mapper, Predicate<T> isDirectory) { return stream .map(object -> new Pair<>(object, mapper.apply(object).split("[-.]"))) .sorted(new MetadataComparator<>(pair -> mapper.apply(pair.getKey()), Pair::getValue, pair -> isDirectory.test(pair.getKey()))) .map(Pair::getKey); } public static String toIdentifier(String artifact, String version, File build) { String identifier = build.getName(); identifier = StringUtils.replace(identifier, "." + FilesUtils.getExtension(identifier), StringUtils.EMPTY); identifier = StringUtils.replace(identifier, artifact + "-", StringUtils.EMPTY); identifier = StringUtils.replace(identifier, version + "-", StringUtils.EMPTY); return declassifyIdentifier(identifier); } private static String declassifyIdentifier(String identifier) { int occurrences = StringUtils.countOccurrences(identifier, "-"); // no action required if (occurrences == 0) { return identifier; } int occurrence = identifier.indexOf("-"); // process identifiers without classifier or build number if (occurrences == 1) { return isBuildNumber(identifier.substring(occurrence + 1)) ? identifier : identifier.substring(0, occurrence); } // remove classifier return isBuildNumber(identifier.substring(occurrence + 1, identifier.indexOf("-", occurrence + 1))) ? identifier.substring(0, identifier.indexOf("-", occurrence + 1)) : identifier.substring(0, occurrence); } protected static String toUpdateTime(File file) { return TIMESTAMP_FORMATTER.format(Instant.ofEpochMilli(file.lastModified())); } public static String toGroup(String[] elements) { return ContentJoiner.on(".") .join(Arrays.copyOfRange(elements, 0, elements.length)) .toString(); } protected static String toGroup(String[] elements, int toShrink) { return toGroup(shrinkGroup(elements, toShrink)); } private static String[] shrinkGroup(String[] elements, int toShrink) { return Arrays.copyOfRange(elements, 0, elements.length - toShrink); } private static boolean isBuildNumber(String content) { for (char character : content.toCharArray()) { if (!Character.isDigit(character)) { return false; } } return true; } }