use of org.haiku.haikudepotserver.support.VersionCoordinates in project haikudepotserver by haiku.
the class UserRatingApiImpl method searchUserRatings.
@Override
public SearchUserRatingsResult searchUserRatings(SearchUserRatingsRequest request) {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(request.limit);
Preconditions.checkState(request.limit > 0);
final ObjectContext context = serverRuntime.newContext();
UserRatingSearchSpecification searchSpecification = new UserRatingSearchSpecification();
if (null != request.daysSinceCreated) {
searchSpecification.setDaysSinceCreated(request.daysSinceCreated.intValue());
}
Architecture architecture = null;
if (null != request.pkgVersionArchitectureCode) {
architecture = getArchitecture(context, request.pkgVersionArchitectureCode);
}
Optional<Pkg> pkgOptional = Optional.empty();
if (null != request.pkgName) {
pkgOptional = Pkg.tryGetByName(context, request.pkgName);
if (pkgOptional.isEmpty()) {
throw new ObjectNotFoundException(Pkg.class.getSimpleName(), request.pkgName);
}
}
Optional<Repository> repositoryOptional = Optional.empty();
if (!Strings.isNullOrEmpty(request.repositoryCode)) {
searchSpecification.setRepository(getRepository(context, request.repositoryCode));
}
if (null != request.pkgVersionMajor) {
if (repositoryOptional.isEmpty()) {
throw new IllegalStateException("the repository is required when a pkg version is specified");
}
if (pkgOptional.isEmpty()) {
throw new IllegalStateException("the pkg is required when a pkg version is specified");
}
if (null == architecture) {
throw new IllegalStateException("the architecture is required when a pkg version is specified");
}
PkgVersion pkgVersion = PkgVersion.getForPkg(context, pkgOptional.get(), repositoryOptional.get(), architecture, new VersionCoordinates(request.pkgVersionMajor, request.pkgVersionMinor, request.pkgVersionMicro, request.pkgVersionPreRelease, request.pkgVersionRevision)).filter(_PkgVersion::getActive).orElseThrow(() -> new ObjectNotFoundException(PkgVersion.class.getSimpleName(), ""));
searchSpecification.setPkgVersion(pkgVersion);
} else {
searchSpecification.setArchitecture(architecture);
if (pkgOptional.isPresent()) {
searchSpecification.setPkg(pkgOptional.get());
}
}
if (null != request.userNickname) {
Optional<User> userOptional = User.tryGetByNickname(context, request.userNickname);
if (userOptional.isEmpty()) {
throw new ObjectNotFoundException(User.class.getSimpleName(), request.userNickname);
}
searchSpecification.setUser(userOptional.get());
}
searchSpecification.setLimit(request.limit);
searchSpecification.setOffset(request.offset);
List<UserRating> foundUserRatings = userRatingService.search(context, searchSpecification);
final SearchUserRatingsResult result = new SearchUserRatingsResult();
result.total = userRatingService.total(context, searchSpecification);
result.items = foundUserRatings.stream().map(ur -> {
SearchUserRatingsResult.UserRating resultUserRating = new SearchUserRatingsResult.UserRating();
resultUserRating.active = ur.getActive();
resultUserRating.code = ur.getCode();
resultUserRating.comment = ur.getComment();
resultUserRating.createTimestamp = ur.getCreateTimestamp().getTime();
resultUserRating.modifyTimestamp = ur.getModifyTimestamp().getTime();
resultUserRating.userRatingStabilityCode = null != ur.getUserRatingStability() ? ur.getUserRatingStability().getCode() : null;
resultUserRating.naturalLanguageCode = ur.getNaturalLanguage().getCode();
resultUserRating.pkgVersion = createPkgVersion(ur.getPkgVersion());
resultUserRating.rating = ur.getRating();
resultUserRating.user = createUser(ur.getUser());
return resultUserRating;
}).collect(Collectors.toList());
return result;
}
use of org.haiku.haikudepotserver.support.VersionCoordinates in project haikudepotserver by haiku.
the class UserRatingApiImpl method createUserRating.
@Override
public CreateUserRatingResult createUserRating(CreateUserRatingRequest request) {
Preconditions.checkNotNull(request);
Preconditions.checkState(!Strings.isNullOrEmpty(request.naturalLanguageCode));
Preconditions.checkState(!Strings.isNullOrEmpty(request.pkgName));
Preconditions.checkState(!Strings.isNullOrEmpty(request.pkgVersionArchitectureCode));
Preconditions.checkArgument(!Strings.isNullOrEmpty(request.repositoryCode), "the repository code should be supplied");
Preconditions.checkArgument(null == request.rating || request.rating >= UserRating.MIN_USER_RATING, "the user rating " + request.rating + " is less than the minimum allowed of " + UserRating.MIN_USER_RATING);
Preconditions.checkArgument(null == request.rating || request.rating <= UserRating.MAX_USER_RATING, "the user rating " + request.rating + " is greater than the maximum allowed of " + UserRating.MIN_USER_RATING);
if (null != request.comment) {
request.comment = Strings.emptyToNull(request.comment.trim());
}
if (Strings.isNullOrEmpty(request.comment) && null == request.userRatingStabilityCode && null == request.rating) {
throw new IllegalStateException("it is not possible to create a user rating with no meaningful rating data");
}
final ObjectContext context = serverRuntime.newContext();
Optional<Pkg> pkgOptional = Pkg.tryGetByName(context, request.pkgName);
if (pkgOptional.isEmpty()) {
throw new ObjectNotFoundException(Pkg.class.getSimpleName(), request.pkgName);
}
Architecture architecture = getArchitecture(context, request.pkgVersionArchitectureCode);
NaturalLanguage naturalLanguage = getNaturalLanguage(context, request.naturalLanguageCode);
Repository repository = getRepository(context, request.repositoryCode);
User user = User.tryGetByNickname(context, request.userNickname).orElseThrow(() -> new ObjectNotFoundException(User.class.getSimpleName(), request.userNickname));
Optional<UserRatingStability> userRatingStabilityOptional = Optional.empty();
if (null != request.userRatingStabilityCode) {
userRatingStabilityOptional = UserRatingStability.getByCode(context, request.userRatingStabilityCode);
if (userRatingStabilityOptional.isEmpty()) {
throw new ObjectNotFoundException(UserRatingStability.class.getSimpleName(), request.userRatingStabilityCode);
}
}
// check authorization
Optional<User> authenticatedUserOptional = tryObtainAuthenticatedUser(context);
if (authenticatedUserOptional.isEmpty()) {
throw new AccessDeniedException("only authenticated users are able to add user ratings");
}
if (!authenticatedUserOptional.get().getNickname().equals(user.getNickname())) {
throw new AccessDeniedException("it is not allowed to add a user rating for another user");
}
if (!permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), pkgOptional.get(), Permission.PKG_CREATEUSERRATING)) {
throw new AccessDeniedException("unable to create user ratings for [" + pkgOptional.get() + "]");
}
// check the package version
Optional<PkgVersion> pkgVersionOptional;
switch(request.pkgVersionType) {
case LATEST:
pkgVersionOptional = pkgService.getLatestPkgVersionForPkg(context, pkgOptional.get(), repository, Collections.singletonList(architecture));
break;
case SPECIFIC:
pkgVersionOptional = PkgVersion.getForPkg(context, pkgOptional.get(), repository, architecture, new VersionCoordinates(request.pkgVersionMajor, request.pkgVersionMinor, request.pkgVersionMicro, request.pkgVersionPreRelease, request.pkgVersionRevision));
break;
default:
throw new IllegalStateException("unsupported pkg version type; " + request.pkgVersionType.name());
}
if (pkgVersionOptional.isEmpty()) {
throw new ObjectNotFoundException(PkgVersion.class.getSimpleName(), pkgOptional.get().getName() + "_" + request.pkgVersionType.name());
}
if (!pkgVersionOptional.get().getIsLatest()) {
throw new IllegalStateException("it is not possible to add a user rating to a version other than the latest version.");
}
List<UserRating> legacyUserRatings = UserRating.findByUserAndPkg(context, user, pkgOptional.get());
for (UserRating legacyUserRating : legacyUserRatings) {
if (legacyUserRating.getPkgVersion().equals(pkgVersionOptional.get())) {
throw new IllegalStateException("an existing user rating '" + legacyUserRating.getCode() + "' already exists for this package version; it is not possible to add another one");
}
}
// now create the new user rating.
UserRating userRating = context.newObject(UserRating.class);
userRating.setCode(UUID.randomUUID().toString());
userRating.setUserRatingStability(userRatingStabilityOptional.orElse(null));
userRating.setUser(user);
userRating.setComment(Strings.emptyToNull(Strings.nullToEmpty(request.comment).trim()));
userRating.setPkgVersion(pkgVersionOptional.get());
userRating.setNaturalLanguage(naturalLanguage);
userRating.setRating(request.rating);
context.commitChanges();
LOGGER.info("did create user rating for user {} on package {}", user.toString(), pkgOptional.get().toString());
return new CreateUserRatingResult(userRating.getCode());
}
use of org.haiku.haikudepotserver.support.VersionCoordinates in project haikudepotserver by haiku.
the class UserRatingServiceImpl method userRatingDerivation.
/**
* <p>This method will calculate the user rating for the package. It may not be possible to generate a
* user rating; in which case, an absent {@link Optional} is returned.</p>
*/
Optional<DerivedUserRating> userRatingDerivation(ObjectContext context, Pkg pkg, Repository repository) {
Preconditions.checkNotNull(context);
Preconditions.checkNotNull(pkg);
// haul all of the pkg versions into memory first.
// active only
List<PkgVersion> pkgVersions = PkgVersion.getForPkg(context, pkg, repository, false);
if (!pkgVersions.isEmpty()) {
final VersionCoordinatesComparator versionCoordinatesComparator = new VersionCoordinatesComparator();
// convert the package versions into coordinates and sort those.
List<VersionCoordinates> versionCoordinates = pkgVersions.stream().map(pv -> pv.toVersionCoordinates().toVersionCoordinatesWithoutPreReleaseOrRevision()).distinct().sorted(versionCoordinatesComparator).collect(Collectors.toList());
// work back VERSIONS_BACK from the latest in order to find out where to start fishing out user
// ratings from.
final VersionCoordinates oldestVersionCoordinates;
if (versionCoordinates.size() < userRatingDerivationVersionsBack + 1) {
oldestVersionCoordinates = versionCoordinates.get(0);
} else {
oldestVersionCoordinates = versionCoordinates.get(versionCoordinates.size() - (userRatingDerivationVersionsBack + 1));
}
// now we need to find all of the package versions that are including this one or newer.
{
final VersionCoordinatesComparator mainPartsVersionCoordinatesComparator = new VersionCoordinatesComparator(true);
pkgVersions = pkgVersions.stream().filter(pv -> mainPartsVersionCoordinatesComparator.compare(pv.toVersionCoordinates(), oldestVersionCoordinates) >= 0).collect(Collectors.toList());
}
// only one user rating should taken from each user; the latest one. Get a list of all of the
// people who have rated these versions.
List<Short> ratings = new ArrayList<>();
List<String> userNicknames = getUserNicknamesWhoHaveRatedPkgVersions(context, pkgVersions);
for (String nickname : userNicknames) {
User user = User.getByNickname(context, nickname);
List<UserRating> userRatingsForUser = new ArrayList<>(UserRating.getByUserAndPkgVersions(context, user, pkgVersions));
userRatingsForUser.sort((o1, o2) -> ComparisonChain.start().compare(o1.getPkgVersion().toVersionCoordinates(), o2.getPkgVersion().toVersionCoordinates(), versionCoordinatesComparator).compare(o1.getCreateTimestamp(), o2.getCreateTimestamp()).compare(o1.getPkgVersion().getArchitecture().getCode(), o2.getPkgVersion().getArchitecture().getCode()).result());
if (!userRatingsForUser.isEmpty()) {
UserRating latestUserRatingForUser = userRatingsForUser.get(userRatingsForUser.size() - 1);
if (null != latestUserRatingForUser.getRating()) {
ratings.add(latestUserRatingForUser.getRating());
}
}
}
if (ratings.size() >= userRatingsDerivationMinRatings) {
return Optional.of(new DerivedUserRating(averageAsFloat(ratings), ratings.size()));
}
}
return Optional.empty();
}
use of org.haiku.haikudepotserver.support.VersionCoordinates in project haikudepotserver by haiku.
the class PkgDownloadController method download.
@RequestMapping(value = { "/" + SEGMENT_PKGDOWNLOAD + PATH }, method = RequestMethod.GET)
public void download(HttpServletResponse response, @PathVariable(value = KEY_PKGNAME) String pkgName, @PathVariable(value = KEY_REPOSITORYCODE) String repositoryCode, @PathVariable(value = KEY_MAJOR) String major, @PathVariable(value = KEY_MINOR) String minor, @PathVariable(value = KEY_MICRO) String micro, @PathVariable(value = KEY_PRERELEASE) String prerelease, @PathVariable(value = KEY_REVISION) String revisionStr, @PathVariable(value = KEY_ARCHITECTURECODE) String architectureCode) throws IOException, RequestObjectNotFound {
Preconditions.checkArgument(null != response, "the response is required");
ObjectContext context = serverRuntime.newContext();
Pkg pkg = Pkg.tryGetByName(context, pkgName).orElseThrow(() -> {
LOGGER.info("unable to find the package; {}", pkgName);
return new RequestObjectNotFound();
});
Repository repository = Repository.tryGetByCode(context, repositoryCode).orElseThrow(() -> {
LOGGER.info("unable to find the repository; {}", repositoryCode);
return new RequestObjectNotFound();
});
Architecture architecture = Architecture.tryGetByCode(context, architectureCode).orElseThrow(() -> {
LOGGER.info("unable to find the architecture; {}", architectureCode);
return new RequestObjectNotFound();
});
revisionStr = hyphenToNull(revisionStr);
VersionCoordinates versionCoordinates = new VersionCoordinates(hyphenToNull(major), hyphenToNull(minor), hyphenToNull(micro), hyphenToNull(prerelease), null == revisionStr ? null : Integer.parseInt(revisionStr));
PkgVersion pkgVersion = PkgVersion.getForPkg(context, pkg, repository, architecture, versionCoordinates).orElseThrow(() -> {
LOGGER.info("unable to find the pkg version; {}, {}", pkgName, versionCoordinates);
return new RequestObjectNotFound();
});
Optional<URL> urlOptional = pkgVersion.tryGetHpkgURL(ExposureType.EXTERNAL_FACING);
if (urlOptional.isEmpty()) {
LOGGER.info("unable to allow download of the hpkg data as no url was able to be generated");
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
} else {
URL url = urlOptional.get();
if (ImmutableSet.of("http", "https").contains(url.getProtocol())) {
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader(HttpHeaders.LOCATION, url.toString());
response.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString());
PrintWriter writer = response.getWriter();
writer.print(url.toString());
writer.flush();
} else {
response.setContentType(MediaType.OCTET_STREAM.toString());
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=\"%s\"", pkgVersion.getHpkgFilename()));
try (InputStream inputStream = url.openStream()) {
LOGGER.info("downloaded package version; {} - {}", pkg.getName(), pkgVersion);
ByteStreams.copy(inputStream, response.getOutputStream());
} catch (IOException ioe) {
// logged without a stack trace because it happens fairly often that a robot will initiate the download and then drop it.
LOGGER.error("unable to relay data to output stream from '{}'; {} -- {}", url.toString(), ioe.getClass().getSimpleName(), ioe.getMessage());
}
}
}
}
use of org.haiku.haikudepotserver.support.VersionCoordinates in project haikudepotserver by haiku.
the class PkgImportServiceImpl method possiblyReconfigurePersistedPkgVersionToBeLatest.
private void possiblyReconfigurePersistedPkgVersionToBeLatest(ObjectContext objectContext, PkgVersion persistedLatestExistingPkgVersion, PkgVersion persistedPkgVersion) {
if (null != persistedLatestExistingPkgVersion) {
VersionCoordinatesComparator versionCoordinatesComparator = new VersionCoordinatesComparator();
VersionCoordinates persistedPkgVersionCoords = persistedPkgVersion.toVersionCoordinates();
VersionCoordinates persistedLatestExistingPkgVersionCoords = persistedLatestExistingPkgVersion.toVersionCoordinates();
int c = versionCoordinatesComparator.compare(persistedPkgVersionCoords, persistedLatestExistingPkgVersionCoords);
if (c > 0) {
persistedPkgVersion.setIsLatest(true);
persistedLatestExistingPkgVersion.setIsLatest(false);
} else {
boolean isRealArchitecture = !persistedPkgVersion.getArchitecture().getCode().equals(Architecture.CODE_SOURCE);
if (0 == c) {
if (isRealArchitecture) {
LOGGER.debug("imported a package version [{}] of [{}] which is the same as the existing [{}]", persistedPkgVersionCoords, persistedPkgVersion.getPkg().getName(), persistedLatestExistingPkgVersionCoords);
}
} else {
if (isRealArchitecture) {
// [apl 3.dec.2016]
// If the package from the repository is older than the one that is presently marked as latest
// then a regression has occurred. In this case make the imported one be the latest and mark
// the later ones as "inactive".
List<PkgVersion> pkgVersionsToDeactivate = PkgVersion.getForPkg(objectContext, persistedPkgVersion.getPkg(), persistedPkgVersion.getRepositorySource().getRepository(), false).stream().filter((pv) -> pv.getArchitecture().equals(persistedPkgVersion.getArchitecture())).filter((pv) -> versionCoordinatesComparator.compare(persistedPkgVersionCoords, pv.toVersionCoordinates()) < 0).collect(Collectors.toList());
LOGGER.warn("imported a package version {} of {} which is older or the same as the existing {}" + " -- will deactivate {} pkg versions after the imported one and make the" + " imported one as latest", persistedPkgVersionCoords, persistedPkgVersion.getPkg().getName(), persistedLatestExistingPkgVersionCoords, pkgVersionsToDeactivate.size());
for (PkgVersion pkgVersionToDeactivate : pkgVersionsToDeactivate) {
pkgVersionToDeactivate.setActive(false);
pkgVersionToDeactivate.setIsLatest(false);
LOGGER.info("deactivated {}", pkgVersionToDeactivate);
}
persistedPkgVersion.setIsLatest(true);
}
}
}
} else {
persistedPkgVersion.setIsLatest(true);
}
}
Aggregations