package com.ciandt.techgallery.service.impl;
import com.google.api.server.spi.response.BadRequestException;
import com.google.api.server.spi.response.InternalServerErrorException;
import com.google.api.server.spi.response.NotFoundException;
import com.google.appengine.api.oauth.OAuthRequestException;
import com.google.appengine.api.users.User;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Ref;
import com.ciandt.techgallery.persistence.dao.TechnologyLinkDAO;
import com.ciandt.techgallery.persistence.dao.impl.TechnologyLinkDAOImpl;
import com.ciandt.techgallery.persistence.model.TechGalleryUser;
import com.ciandt.techgallery.persistence.model.Technology;
import com.ciandt.techgallery.persistence.model.TechnologyLink;
import com.ciandt.techgallery.persistence.model.TechnologyFollowers;
import com.ciandt.techgallery.service.TechnologyLinkService;
import com.ciandt.techgallery.service.TechnologyFollowersService;
import com.ciandt.techgallery.service.TechnologyService;
import com.ciandt.techgallery.service.UserServiceTG;
import com.ciandt.techgallery.service.enums.ValidationMessageEnums;
import com.ciandt.techgallery.service.impl.profile.UserProfileServiceImpl;
import com.ciandt.techgallery.service.model.Response;
import com.ciandt.techgallery.service.model.TechnologyLinksTO;
import com.ciant.techgallery.transaction.ServiceFactory;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Services for Links Endpoint requests.
*
* @author Sidharta Noleto
*
*/
public class TechnologyLinkServiceImpl implements TechnologyLinkService {
/*
* Constants --------------------------------------------
*/
private static final Logger log = Logger.getLogger(TechnologyLinkServiceImpl.class.getName());
/*
* Attributes --------------------------------------------
*/
private static TechnologyLinkServiceImpl instance;
TechnologyLinkDAO technologyLinkDao = TechnologyLinkDAOImpl.getInstance();
UserServiceTG userService = UserServiceTGImpl.getInstance();
TechnologyService techService = TechnologyServiceImpl.getInstance();
private TechnologyFollowersService followersService = ServiceFactory.createServiceImplementation(
TechnologyFollowersService.class, TechnologyFollowersServiceImpl.class);
/*
* Constructors --------------------------------------------
*/
private TechnologyLinkServiceImpl() {}
/**
* Singleton method for the service.
*/
public static TechnologyLinkServiceImpl getInstance() {
if (instance == null) {
instance = new TechnologyLinkServiceImpl();
}
return instance;
}
/*
* Methods --------------------------------------------
*/
@Override
public TechnologyLink addLink(TechnologyLink link, User user)
throws InternalServerErrorException, BadRequestException, NotFoundException {
log.info("Starting creating Technology Link.");
final Technology technology = link.getTechnology().get();
validateUser(user);
validateLink(link);
validateTechnology(technology);
final TechGalleryUser techUser = userService.getUserByGoogleId(user.getUserId());
final TechnologyLink newLink = addNewLink(link, techUser, technology);
// TODO: Adicionar contador de links na tecnologia
// techService.addLinksCounter(technology);
techService.audit(technology.getId(), user);
followTechnology(technology, techUser);
return newLink;
}
private void followTechnology(final Technology technology, final TechGalleryUser techUser)
throws BadRequestException {
TechnologyFollowers technologyFollowers = followersService.findById(technology.getId());
if (technologyFollowers == null
|| !technologyFollowers.getFollowers().contains(Ref.create(techUser))) {
technologyFollowers = followersService.follow(technologyFollowers, techUser, technology);
followersService.update(technologyFollowers);
userService.updateUser(techUser);
}
}
@Override
public Response getLinksByTech(String techId, User user) throws InternalServerErrorException,
BadRequestException, NotFoundException, OAuthRequestException {
final Technology technology = techService.getTechnologyById(techId, user);
validateUser(user);
validateTechnology(technology);
final List<TechnologyLink> linksByTech =
technologyLinkDao.findAllByTechnology(technology);
final TechnologyLinksTO response = new TechnologyLinksTO();
response.setLinks(linksByTech);
return response;
}
@Override
public TechnologyLink deleteLink(Long linkId, User user)
throws InternalServerErrorException, BadRequestException, NotFoundException,
OAuthRequestException {
validateDeletion(linkId, user);
final TechnologyLink link = technologyLinkDao.findById(linkId);
technologyLinkDao.delete(link);
// TODO: Atualiza contador de links na tecnologia quando tivermos
// techService.removeLinksCounter(link.getTechnology().get());
return link;
}
private TechnologyLink addNewLink(TechnologyLink link, TechGalleryUser techUser,
Technology technology) {
log.info("Adding new Link...");
final TechnologyLink newLink =
new TechnologyLink(link.getDescription(), link.getLink(), technology, techUser, new Date());
final Key<TechnologyLink> newLinkKey = technologyLinkDao.add(newLink);
newLink.setId(newLinkKey.getId());
log.info("New Link added: " + newLink.getId());
return newLink;
}
/**
*/
private void validateLink(TechnologyLink link) throws BadRequestException {
log.info("Validating the link");
if (link == null || link.getDescription() == null || link.getDescription().isEmpty()) {
throw new BadRequestException(ValidationMessageEnums.DESCRIPTION_CANNOT_BLANK.message());
}
if (link == null || link.getLink() == null || link.getLink().isEmpty()) {
throw new BadRequestException(ValidationMessageEnums.LINK_CANNOT_BLANK.message());
}
if (link.getDescription().length() > 100) {
throw new BadRequestException(ValidationMessageEnums.DESCRIPTION_MUST_BE_LESSER.message());
}
if (link != null && link.getLink() != null && !link.getLink().isEmpty()) {
Pattern p = Pattern
.compile("(@)?(href=')?(HREF=')?(HREF=\")?(href=\")?(http://|https://)?[a-zA-Z_0-9\\-]+(\\.\\w[a-zA-Z_0-9\\-]+)+(/[#&\\n\\-=?\\+\\%/\\.\\w]+)?");
Matcher m = p.matcher(link.getLink());
if( !m.matches() ) {
throw new BadRequestException(ValidationMessageEnums.LINK_MUST_BE_VALID.message());
}
}
}
/**
* @throws NotFoundException in case the information are not founded
* @throws BadRequestException in case a request with problem were made.
*/
private void validateLink(Long linkId) throws BadRequestException, NotFoundException {
log.info("Validating the link");
if (linkId == null) {
throw new BadRequestException(ValidationMessageEnums.LINK_ID_CANNOT_BLANK.message());
}
final TechnologyLink link = technologyLinkDao.findById(linkId);
if (link == null) {
throw new NotFoundException(ValidationMessageEnums.LINK_NOT_EXIST.message());
}
}
/**
* @throws BadRequestException in case a request with problem were made.
* @throws NotFoundException in case the information are not founded
*/
private void validateTechnology(Technology technology)
throws BadRequestException, NotFoundException {
log.info("Validating the technology");
if (technology == null) {
throw new NotFoundException(ValidationMessageEnums.TECHNOLOGY_NOT_EXIST.message());
}
}
/**
* Validate the user logged in.
*
* @param user info about user from google
*
* @throws BadRequestException in case a request with problem were made.
* @throws InternalServerErrorException in case something goes wrong
* @throws NotFoundException in case the information are not founded
*/
private void validateUser(User user)
throws BadRequestException, NotFoundException, InternalServerErrorException {
log.info("Validating user to link");
if (user == null || user.getUserId() == null || user.getUserId().isEmpty()) {
throw new BadRequestException(ValidationMessageEnums.USER_GOOGLE_ENDPOINT_NULL.message());
}
final TechGalleryUser techUser = userService.getUserByGoogleId(user.getUserId());
if (techUser == null) {
throw new NotFoundException(ValidationMessageEnums.USER_NOT_EXIST.message());
}
}
/**
* @throws BadRequestException in case a request with problem were made.
* @throws InternalServerErrorException in case something goes wrong
* @throws NotFoundException in case the information are not founded
*/
private void validateDeletion(Long linkId, User user)
throws BadRequestException, NotFoundException, InternalServerErrorException {
log.info("Validating the deletion");
validateLink(linkId);
validateUser(user);
final TechnologyLink link = technologyLinkDao.findById(linkId);
final TechGalleryUser techUser = userService.getUserByGoogleId(user.getUserId());
if (!link.getAuthor().get().equals(techUser)) {
throw new BadRequestException(ValidationMessageEnums.LINK_AUTHOR_ERROR.message());
}
}
@Override
public TechnologyLink getById(Long id) throws NotFoundException {
final TechnologyLink link = technologyLinkDao.findById(id);
if (link == null) {
throw new NotFoundException(ValidationMessageEnums.LINK_NOT_EXIST.message());
} else {
return link;
}
}
}