text:
package org.sagebionetworks.repo.manager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sagebionetworks.common.util.progress.ProgressCallback;
import org.sagebionetworks.repo.manager.SendRawEmailRequestBuilder.BodyType;
import org.sagebionetworks.repo.manager.file.FileHandleManager;
import org.sagebionetworks.repo.manager.principal.SynapseEmailService;
import org.sagebionetworks.repo.manager.team.TeamConstants;
import org.sagebionetworks.repo.model.ACCESS_TYPE;
import org.sagebionetworks.repo.model.ACLInheritanceException;
import org.sagebionetworks.repo.model.AccessControlList;
import org.sagebionetworks.repo.model.AuthorizationConstants.BOOTSTRAP_PRINCIPAL;
import org.sagebionetworks.repo.model.AuthorizationUtils;
import org.sagebionetworks.repo.model.DatastoreException;
import org.sagebionetworks.repo.model.GroupMembersDAO;
import org.sagebionetworks.repo.model.MessageDAO;
import org.sagebionetworks.repo.model.Node;
import org.sagebionetworks.repo.model.NodeDAO;
import org.sagebionetworks.repo.model.ObjectType;
import org.sagebionetworks.repo.model.QueryResults;
import org.sagebionetworks.repo.model.ResourceAccess;
import org.sagebionetworks.repo.model.TooManyRequestsException;
import org.sagebionetworks.repo.model.UnauthorizedException;
import org.sagebionetworks.repo.model.UserGroup;
import org.sagebionetworks.repo.model.UserGroupDAO;
import org.sagebionetworks.repo.model.UserInfo;
import org.sagebionetworks.repo.model.UserProfile;
import org.sagebionetworks.repo.model.dao.FileHandleDao;
import org.sagebionetworks.repo.model.dao.NotificationEmailDAO;
import org.sagebionetworks.repo.model.file.FileHandle;
import org.sagebionetworks.repo.model.message.MessageBundle;
import org.sagebionetworks.repo.model.message.MessageRecipientSet;
import org.sagebionetworks.repo.model.message.MessageSortBy;
import org.sagebionetworks.repo.model.message.MessageStatus;
import org.sagebionetworks.repo.model.message.MessageStatusType;
import org.sagebionetworks.repo.model.message.MessageToUser;
import org.sagebionetworks.repo.model.message.MessageToUserUtils;
import org.sagebionetworks.repo.model.message.Settings;
import org.sagebionetworks.repo.model.principal.PrincipalAliasDAO;
import org.sagebionetworks.repo.transactions.WriteTransaction;
import org.sagebionetworks.repo.web.NotFoundException;
import org.sagebionetworks.util.ValidateArgument;
import org.springframework.beans.factory.annotation.Autowired;

import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
import com.google.common.collect.Lists;

public class MessageManagerImpl implements MessageManager {

	static private Logger log = LogManager.getLogger(MessageManagerImpl.class);

	/**
	 * The maximum number of messages a user can create within a given interval
	 * The interval is defined by {@link #MESSAGE_CREATION_INTERVAL}
	 */
	private static final long MAX_NUMBER_OF_NEW_MESSAGES = 10L;

	/**
	 * The span of the interval, in milliseconds, in which created messages are counted
	 * See {@link #MAX_NUMBER_OF_NEW_MESSAGES}
	 */
	private static final long MESSAGE_CREATION_INTERVAL_MILLISECONDS = 60000L;

	/**
	 * The maximum number of targets of a message
	 */
	protected static final long MAX_NUMBER_OF_RECIPIENTS = 50L;

	@Autowired
	private MessageDAO messageDAO;

	@Autowired
	private UserGroupDAO userGroupDAO;

	@Autowired
	private GroupMembersDAO groupMembersDAO;

	@Autowired
	private UserManager userManager;

	@Autowired
	private UserProfileManager userProfileManager;

	@Autowired
	private NotificationEmailDAO notificationEmailDao;

	@Autowired
	private PrincipalAliasDAO principalAliasDAO;

	@Autowired
	private AuthorizationManager authorizationManager;

	@Autowired
	private SynapseEmailService sesClient;

	@Autowired
	private FileHandleManager fileHandleManager;

	@Autowired
	FileHandleDao fileHandleDao;

	@Autowired
	private NodeDAO nodeDAO;

	@Autowired
	private EntityPermissionsManager entityPermissionsManager;

	public MessageManagerImpl() { };

	/**
	 * Used for testing
	 */
	public MessageManagerImpl(MessageDAO messageDAO, UserGroupDAO userGroupDAO,
			GroupMembersDAO groupMembersDAO, UserManager userManager,
			UserProfileManager userProfileManager,
			NotificationEmailDAO notificationEmailDao,
			PrincipalAliasDAO principalAliasDAO,
			AuthorizationManager authorizationManager,
			SynapseEmailService sesClient,
			FileHandleManager fileHandleManager, NodeDAO nodeDAO,
			EntityPermissionsManager entityPermissionsManager,
			FileHandleDao fileHandleDao) {
		this.messageDAO = messageDAO;
		this.userGroupDAO = userGroupDAO;
		this.groupMembersDAO = groupMembersDAO;
		this.userManager = userManager;
		this.userProfileManager = userProfileManager;
		this.notificationEmailDao = notificationEmailDao;
		this.principalAliasDAO = principalAliasDAO;
		this.authorizationManager = authorizationManager;
		this.sesClient = sesClient;
		this.fileHandleManager = fileHandleManager;
		this.nodeDAO = nodeDAO;
		this.entityPermissionsManager = entityPermissionsManager;
		this.fileHandleDao = fileHandleDao;
	}

	@Override
	public MessageToUser getMessage(UserInfo userInfo, String messageId) throws NotFoundException {
		MessageToUser message = messageDAO.getMessage(messageId);

		// Get the user's ID and the user's groups' IDs
		String userId = userInfo.getId().toString();
		Set<String> userGroups = new HashSet<String>();
		for (Long ug : userInfo.getGroups()) {
			userGroups.add(ug.toString());
		}
		userGroups.add(userId);

		// Is the user the sender?
		if (!message.getCreatedBy().equals(userId)) {
			// Is the user an intended recipient?
			boolean isRecipient = false;
			for (String recipient : message.getRecipients()) {
				if (userGroups.contains(recipient)) {
					isRecipient = true;
					break;
				}
			}

			// Not allowed to get the message
			if (!isRecipient) {
				throw new UnauthorizedException("You are not the sender or receiver of this message (" + messageId + ")");
			}
		}
		return message;
	}

	@Override
	public String getMessageFileRedirectURL(UserInfo userInfo, String messageId) throws NotFoundException {
		// If the user can get the message metadata (permission checking by the manager)
		// then the user can download the file
		MessageToUser dto = getMessage(userInfo, messageId);
		return fileHandleManager.getRedirectURLForFileHandle(dto.getFileHandleId());
	}

	@Override
	@WriteTransaction
	public MessageToUser createMessageWithThrottle(UserInfo userInfo, MessageToUser dto) throws NotFoundException {
		boolean userIsTrustedMessageSender = userInfo.getGroups().contains(TeamConstants.TRUSTED_MESSAGE_SENDER_TEAM_ID);
		// Throttle message creation
		if (!userInfo.isAdmin() && !userIsTrustedMessageSender && !messageDAO.canCreateMessage(userInfo.getId().toString(),
					MAX_NUMBER_OF_NEW_MESSAGES,
					MESSAGE_CREATION_INTERVAL_MILLISECONDS)) {
			throw new TooManyRequestsException(
					"Please slow down.  You may send a maximum of "
							+ MAX_NUMBER_OF_NEW_MESSAGES + " message(s) every "
							+ (MESSAGE_CREATION_INTERVAL_MILLISECONDS / 1000) + " second(s)");
		}
		return createMessage(userInfo, dto);
	}

	@Override
	@WriteTransaction
	public MessageToUser createMessage(UserInfo userInfo, MessageToUser dto) throws NotFoundException {
		ValidateArgument.required(userInfo, "userInfo");
		ValidateArgument.required(dto, "dto");
		ValidateArgument.requirement(dto.getRecipients() != null && !dto.getRecipients().isEmpty(),
				"recipients must be set.");
		// Make sure the sender is correct
		dto.setCreatedBy(userInfo.getId().toString());
		if (!userInfo.isAdmin()) {
			// Can't be anonymous
			if (AuthorizationUtils.isUserAnonymous(userInfo)) {
				throw new UnauthorizedException("Anonymous user may not send messages.");
			}

			boolean userIsTrustedMessageSender = userInfo.getGroups().contains(TeamConstants.TRUSTED_MESSAGE_SENDER_TEAM_ID);

			// Limit the number of recipients
			if (!userIsTrustedMessageSender && dto.getRecipients() != null && dto.getRecipients().size() > MAX_NUMBER_OF_RECIPIENTS) {
				throw new IllegalArgumentException(
						"May not message more than "
								+ MAX_NUMBER_OF_RECIPIENTS
								+ " at once.  Consider grouping the recipients in a Team if possible.");
			}
		}

		if (!authorizationManager.canAccessRawFileHandleById(userInfo, dto.getFileHandleId()).getAuthorized()
				&& !messageDAO.canSeeMessagesUsingFileHandle(userInfo.getGroups(), dto.getFileHandleId())) {
			throw new UnauthorizedException("Invalid file handle given");
		}

		// Make sure the recipients all exist
		List<UserGroup> ugs = userGroupDAO.get(Lists.newArrayList(dto.getRecipients()));
		if (ugs.size() != dto.getRecipients().size()) {
			throw new IllegalArgumentException("One or more of the following IDs are not recognized: " + dto.getRecipients());
		}

		dto = messageDAO.createMessage(dto);

		// If the recipient list is only one element long,
		// process and send the message in this transaction
		if (dto.getRecipients().size() == 1) {
			UserGroup ug;
			try {
				ug = userGroupDAO.get(Long.parseLong(dto.getRecipients().iterator().next()));
			} catch (NotFoundException e) {
				throw new DatastoreException("Could not get a user group that satisfied message creation constraints");
			}

			// Defer the sending of messages to non-individuals
			// since there could be more than one actual recipient after finding the members
			if (ug.getIsIndividual()) {
				List<String> errors;
				try {
					errors = processMessage(dto.getId(), true, null);
				} catch (NotFoundException e) {
					throw new DatastoreException("Could not find a message that was created in the same transaction");
				}
				if (errors.size() > 0) {
					throw new IllegalArgumentException(StringUtils.join(errors, "\n"));
				}
			}
		}
		return dto;
	}

	@Override
	@WriteTransaction
	public MessageToUser createMessageToEntityOwner(UserInfo userInfo,
			String entityId, MessageToUser toCreate) throws NotFoundException, ACLInheritanceException {
		// No permission checks since we only need to find the IDs of the creator of the node
		//   (or anyone with CHANGE_PERMISSIONS access)
		Node entity = nodeDAO.getNode(entityId);
		String benefactor = nodeDAO.getBenefactor(entityId);
		AccessControlList acl = entityPermissionsManager.getACL(benefactor, userInfo);

		// Find all users with permission to change permissions
		Set<Long> sharers = new HashSet<Long>();
		for (ResourceAccess ra : acl.getResourceAccess()) {
			if (ra.getAccessType().contains(ACCESS_TYPE.CHANGE_PERMISSIONS)) {
				sharers.add(ra.getPrincipalId());
			}
		}

		if (toCreate.getRecipients() == null) {
			toCreate.setRecipients(new HashSet<String>());
		}

		// If the creator has permission, just message the creator
		if (sharers.contains(entity.getCreatedByPrincipalId())) {
			toCreate.getRecipients().add(entity.getCreatedByPrincipalId().toString());

		// Otherwise message everyone else
		} else {
			if (sharers.size() <= 0) {
				throw new UnauthorizedException("Unable to find a user with access to this entity.  Please contact a Synapse Administrator at synapseInfo@sagebase.org");
			}
			for (Long sharer : sharers) {
				toCreate.getRecipients().add(sharer.toString());
			}
		}

		// Create the message like normal
		return createMessage(userInfo, toCreate);
	}

	@Override
	@WriteTransaction
	public MessageToUser forwardMessage(UserInfo userInfo, String messageId,
			MessageRecipientSet recipients) throws NotFoundException {
		MessageToUser message = getMessage(userInfo, messageId);
		message.setRecipients(recipients.getRecipients());
		message.setInReplyTo(messageId);
		message = MessageToUserUtils.setUserGeneratedMessageFooter(message);
		return createMessageWithThrottle(userInfo, message);
	}

	@Override
	public List<MessageToUser> getConversation(UserInfo userInfo, String associatedMessageId,
			MessageSortBy sortBy, boolean descending, long limit, long offset) throws NotFoundException {
		MessageToUser dto = messageDAO.getMessage(associatedMessageId);
		String rootMessageId = dto.getInReplyToRoot();

		List<MessageToUser> dtos = messageDAO.getConversation(rootMessageId, userInfo.getId().toString(),
				sortBy, descending, limit, offset);
		return dtos;
	}

	@Override
	public List<MessageBundle> getInbox(UserInfo userInfo,
			List<MessageStatusType> included, MessageSortBy sortBy, boolean descending, long limit, long offset) {
		List<MessageBundle> dtos = messageDAO.getReceivedMessages(userInfo.getId().toString(),
				included, sortBy, descending, limit, offset);
		return dtos;
	}

	@Override
	public List<MessageToUser> getOutbox(UserInfo userInfo,
			MessageSortBy sortBy, boolean descending, long limit, long offset) {
		List<MessageToUser> dtos = messageDAO.getSentMessages(userInfo.getId().toString(),
				sortBy, descending, limit, offset);
		return dtos;
	}

	@Override
	@WriteTransaction
	public void markMessageStatus(UserInfo userInfo, MessageStatus status) throws NotFoundException {
		// Check to see if the user can see the message being updated
		getMessage(userInfo, status.getMessageId());

		// Update the message
		status.setRecipientId(userInfo.getId().toString());
		boolean succeeded = messageDAO.updateMessageStatus_SameTransaction(status);

		if (!succeeded) {
			throw new UnauthorizedException("Cannot change status of message (" + status.getMessageId() + ")");
		}
	}

	@Override
	@WriteTransaction
	public List<String> processMessage(String messageId, ProgressCallback progressCallback) throws NotFoundException {
		return processMessage(messageId, false, progressCallback);
	}

	/**
	 * See {@link #processMessage(String)}
	 * Also used by {@link #createMessage(UserInfo, MessageToUser)}
	 *
	 * @param singleTransaction Should the sending be done in one transaction or one transaction per recipient?
	 *    This allows the sending of messages during creation to complete without deadlock.
	 *    Note: It is crucial to pass in "true" when creating *and* sending a message in the same operation together.
	 *      Otherwise the 'sending step' waits forever for the lock obtained by the 'creation step' to be released.
	 * General usage of this method sets this parameter to false.
	 * @throws
	 */
	private List<String> processMessage(String messageId, boolean singleTransaction, ProgressCallback progressCallback) throws NotFoundException {
		MessageToUser dto = messageDAO.getMessage(messageId);
		FileHandle fileHandle = fileHandleDao.get(dto.getFileHandleId());
		ContentType contentType = ContentType.parse(fileHandle.getContentType());
		String mimeType = contentType.getMimeType().trim().toLowerCase();

		try {
			String messageBody = fileHandleManager.downloadFileToString(dto.getFileHandleId());
			return processMessage(dto, singleTransaction, messageBody, mimeType, progressCallback);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * See {@link #processMessage(String, boolean)}
	 * Also used by {@link #sendTemplateEmail(String, String, String, boolean)}
	 *
	 * @param messageBody The body of any email(s) that get sent as a result of processing this message
	 *    Note: This parameter is provided so that templated messages do not need to be uploaded then downloaded before sending
	 */
	private List<String> processMessage(
			MessageToUser dto, boolean singleTransaction,
			String messageBody, String mimeType,
			ProgressCallback progressCallback) throws NotFoundException {
		List<String> errors = new ArrayList<String>();

		// Check to see if the message has already been sent
		// If so, nothing else needs to be done
		if (messageDAO.getMessageSent(dto.getId())) {
			return errors;
		}
		String senderUserName = null;

		UserInfo userInfo = userManager.getUserInfo(Long.parseLong(dto.getCreatedBy()));

		// in practice there is always a user name, but strictly speaking it is allowed to be missing

		try {
			senderUserName = principalAliasDAO.getUserName(userInfo.getId());
		} catch (NotFoundException e) {
			senderUserName = null;
		}
		String senderDisplayName = null;
		try {
			UserProfile senderUserProfile = userProfileManager.getUserProfile(userInfo.getId().toString());
			senderDisplayName = EmailUtils.getDisplayName(senderUserProfile);
		} catch (NotFoundException e) {
			senderDisplayName = null;
		}

		// Get the individual recipients
		Set<String> recipients = expandRecipientSet(userInfo, dto.getRecipients(), errors);

		// Make sure the caller set the boolean correctly
		if (recipients.size() > 1 && singleTransaction) {
			throw new IllegalArgumentException("A message sent to multiple recipients must be done in separate transactions");
		}

		// Now that the recipients list has been expanded, begin processing the message
		for (String userId : recipients) {
			// Try to send messages to each user individually
			try {
				// Get the user's settings
				Settings settings = null;
				UserProfile profile = userProfileManager.getUserProfile(userId);
				settings = profile.getNotificationSettings();
				if(settings == null){
					settings = new Settings();
				}
				MessageStatusType userMessageStatus = null; // setting to null tells the DAO to use the default value
				// This marks a user as a recipient of the message
				if (singleTransaction) {
					messageDAO.createMessageStatus_SameTransaction(dto.getId(), userId, userMessageStatus);
				} else {
					messageDAO.createMessageStatus_NewTransaction(dto.getId(), userId, userMessageStatus);
				}

				// Should emails be sent?
				if (settings.getSendEmailNotifications() == null || settings.getSendEmailNotifications()) {
					String email = getEmailForUser(Long.parseLong(userId));
					SendRawEmailRequestBuilder.BodyType bodyType;
					if (ContentType.APPLICATION_JSON.getMimeType().equals(mimeType)) {
						bodyType = SendRawEmailRequestBuilder.BodyType.JSON;
					} else {
						boolean isHtml= ContentType.TEXT_HTML.getMimeType().equals(mimeType);
						bodyType = isHtml ? SendRawEmailRequestBuilder.BodyType.HTML : SendRawEmailRequestBuilder.BodyType.PLAIN_TEXT;
					}

					SendRawEmailRequest sendRawEmailRequest = new SendRawEmailRequestBuilder()
						.withRecipientEmail(email)
						.withSubject(dto.getSubject())
						.withTo(dto.getTo())
						.withCc(dto.getCc())
						.withBcc(dto.getBcc())
						.withBody(messageBody, bodyType)
						.withSenderUserName(senderUserName)
						.withSenderDisplayName(senderDisplayName)
						.withUserId(userId)
						.withNotificationUnsubscribeEndpoint(dto.getNotificationUnsubscribeEndpoint())
						.withUnsubscribeLink(dto.getWithUnsubscribeLink())
						.withUserProfileSettingEndpoint(dto.getUserProfileSettingEndpoint())
						.withProfileSettingLink(dto.getWithProfileSettingLink())
						.withIsNotificationMessage(dto.getIsNotificationMessage())
						.build();
					sesClient.sendRawEmail(sendRawEmailRequest);
					// Should the message be marked as READ?
					if (settings.getMarkEmailedMessagesAsRead() != null && settings.getMarkEmailedMessagesAsRead()) {
						userMessageStatus = MessageStatusType.READ;
					}
				}

				if (userMessageStatus!=null) {
					// the status has been changed, so we have to update it again
					MessageStatus messageStatus = new MessageStatus();
					messageStatus.setMessageId(dto.getId());
					messageStatus.setRecipientId(userId);
					messageStatus.setStatus(userMessageStatus);
					if (singleTransaction) {
						messageDAO.updateMessageStatus_SameTransaction(messageStatus);
					} else {
						messageDAO.updateMessageStatus_NewTransaction(messageStatus);
					}
				}
			} catch (Exception e) {
				log.info("Error caught while processing message", e);
				errors.add("Failed while processing message for recipient (" + userId + "): " + e.getMessage());
			}
		}

		messageDAO.updateMessageTransmissionAsComplete(dto.getId());

		return errors;
	}

	/**
	 * Helper for {@link #processMessage(String, boolean, String)}
	 *
	 * Takes a set of user IDs and expands it into a set of individuals that the user is permitted to message
	 */
	private Set<String> expandRecipientSet(UserInfo userInfo, Set<String> intendedRecipients, List<String> errors) throws NotFoundException {
		// From the list of intended recipients, filter out the un-permitted recipients
		Set<String> recipients = new HashSet<String>();
		for (String principalId : intendedRecipients) {
			Long principalIdLong = Long.parseLong(principalId);
			UserGroup ug;
			try {
				ug = userGroupDAO.get(principalIdLong);
			} catch (NotFoundException e) {
				errors.add(e.getMessage());
				continue;
			}

			boolean userIsTrustedMessageSender = userInfo.getGroups().contains(TeamConstants.TRUSTED_MESSAGE_SENDER_TEAM_ID);
			// Check permissions to send to non-individuals
			if (!userIsTrustedMessageSender &&
					!ug.getIsIndividual() &&
					!authorizationManager.canAccess(userInfo, principalId, ObjectType.TEAM, ACCESS_TYPE.SEND_MESSAGE).getAuthorized()) {
				String sender = null;
				String team = null;
				try {
					sender = principalAliasDAO.getUserName(userInfo.getId());
				} catch (NotFoundException e) {
					sender = userInfo.getId().toString();
				}
				try {
					team = principalAliasDAO.getTeamName(Long.parseLong(principalId));
				} catch (NotFoundException e) {
					team = principalId;
				}
				errors.add(sender + " may not send messages to the group (" + team + ")");
				continue;
			}

			// The principal is a valid recipient
			if (ug.getIsIndividual()) {
				recipients.add(principalId);
			} else {
				// Handle the implicit group that contains all users
				// Note: only admins can pass the authorization check to reach this
				if (BOOTSTRAP_PRINCIPAL.AUTHENTICATED_USERS_GROUP.getPrincipalId().toString().equals(principalId)) {
					for (UserGroup member : userGroupDAO.getAllPrincipals()) {
						if (member.getIsIndividual() && !isNotEmailRecipient(member.getId())) {
							recipients.add(member.getId());
						}
					}
				}

				// Expand non-individuals into individuals
				for (UserGroup member : groupMembersDAO.getMembers(principalId)) {
					recipients.add(member.getId());
				}
			}
		}

		return recipients;
	}

	// this filters out bootstrapped principals, who are NOT email recipients
	private static boolean isNotEmailRecipient(String principalId) {
		for (BOOTSTRAP_PRINCIPAL pb : BOOTSTRAP_PRINCIPAL.values()) {
			if (pb.getPrincipalId().toString().equals(principalId)) return true;
		}
		return false;
	}

	@Override
	@WriteTransaction
	public void deleteMessage(UserInfo userInfo, String messageId) {
		if (!userInfo.isAdmin()) {
			throw new UnauthorizedException("Only admins may delete messages");
		}

		messageDAO.deleteMessage(messageId);
	}

	@Override
	@WriteTransaction
	public void sendPasswordResetEmail(Long recipientId, String sessionToken) throws NotFoundException {
		String subject = "Set Synapse Password";
		Map<String,String> fieldValues = new HashMap<String,String>();
		fieldValues.put(EmailUtils.TEMPLATE_KEY_ORIGIN_CLIENT, "Synapse");

		String alias = principalAliasDAO.getUserName(recipientId);
		UserProfile userProfile = userProfileManager.getUserProfile(recipientId.toString());
		String displayName = EmailUtils.getDisplayName(userProfile);

		fieldValues.put(EmailUtils.TEMPLATE_KEY_DISPLAY_NAME, alias);

		fieldValues.put(EmailUtils.TEMPLATE_KEY_USERNAME, alias);
		String webLink = "https://www.synapse.org/Portal.html#!PasswordReset:" + sessionToken;
		fieldValues.put(EmailUtils.TEMPLATE_KEY_WEB_LINK, webLink);
		String messageBody = EmailUtils.readMailTemplate("message/PasswordResetTemplate.txt", fieldValues);
		String email = getEmailForUser(recipientId);
		SendRawEmailRequest sendEmailRequest = new SendRawEmailRequestBuilder()
				.withRecipientEmail(email)
				.withSubject(subject)
				.withBody(messageBody, BodyType.PLAIN_TEXT)
				.withSenderUserName(alias)
				.withSenderDisplayName(displayName)
				.withUserId(recipientId.toString())
				.withIsNotificationMessage(true)
				.build();
		sesClient.sendRawEmail(sendEmailRequest);
	}

	@Override
	@WriteTransaction
	public void sendWelcomeEmail(Long recipientId, String notificationUnsubscribeEndpoint) throws NotFoundException {
		String subject = "Welcome to Synapse!";
		Map<String,String> fieldValues = new HashMap<String,String>();
		fieldValues.put(EmailUtils.TEMPLATE_KEY_ORIGIN_CLIENT, "Synapse");

		String alias = principalAliasDAO.getUserName(recipientId);
		fieldValues.put(EmailUtils.TEMPLATE_KEY_DISPLAY_NAME, alias);

		fieldValues.put(EmailUtils.TEMPLATE_KEY_USERNAME, alias);
		String messageBody = EmailUtils.readMailTemplate("message/WelcomeTemplate.txt", fieldValues);
		String email = getEmailForUser(recipientId);
		SendRawEmailRequest sendEmailRequest = new SendRawEmailRequestBuilder()
				.withRecipientEmail(email)
				.withSubject(subject)
				.withBody(messageBody, BodyType.PLAIN_TEXT)
				.withUserId(recipientId.toString())
				.withNotificationUnsubscribeEndpoint(notificationUnsubscribeEndpoint)
				.withIsNotificationMessage(true)
				.build();
		sesClient.sendRawEmail(sendEmailRequest);
	}

	@Override
	@WriteTransaction
	public void sendDeliveryFailureEmail(String messageId, List<String> errors) throws NotFoundException {
		// Build the subject and body of the message
		MessageToUser dto = messageDAO.getMessage(messageId);
		Long senderId = Long.parseLong(dto.getCreatedBy());
		String subject = "Message " + messageId + " Delivery Failure(s)";

		String alias = principalAliasDAO.getUserName(senderId);

		Map<String,String> fieldValues = new HashMap<String,String>();
		fieldValues.put(EmailUtils.TEMPLATE_KEY_DISPLAY_NAME, alias);

		fieldValues.put(EmailUtils.TEMPLATE_KEY_MESSAGE_SUBJECT, dto.getSubject());
		fieldValues.put(EmailUtils.TEMPLATE_KEY_DETAILS, "- " + StringUtils.join(errors, "\n- "));
		String email = getEmailForUser(senderId);
		String messageBody = EmailUtils.readMailTemplate("message/DeliveryFailureTemplate.txt", fieldValues);

		SendRawEmailRequest sendEmailRequest = new SendRawEmailRequestBuilder()
				.withRecipientEmail(email)
				.withSubject(subject)
				.withBody(messageBody, BodyType.PLAIN_TEXT)
				.withNotificationUnsubscribeEndpoint(dto.getNotificationUnsubscribeEndpoint())
				.withUserId(senderId.toString())
				.withIsNotificationMessage(true)
				.build();
		sesClient.sendRawEmail(sendEmailRequest);
	}

	private String getEmailForUser(Long principalId) throws NotFoundException {
		return notificationEmailDao.getNotificationEmailForPrincipal(principalId);
	}

}


text:
import Euler(digitFactorial, toDigitsBase)

-- check from first two digit number
-- up to the maximum value that could be produced
-- 9! = 362880, no more than seven 9 digits
allFactSums = sum $ filter (\x -> x == factSum x) [10..7*digitFactorial 9]
    where factSum n = sum $ map digitFactorial $ toDigitsBase 10 n

main = putStrLn $ show $ allFactSums

redpajama_set_name: RedPajamaGithub


text:
package play.data

import java.util
import java.util.Optional
import java.time.{ LocalDate, ZoneId }
import javax.validation.{ Validation, Validator, Configuration => vConfiguration }
import javax.validation.groups.Default

import com.typesafe.config.{ Config, ConfigFactory }
import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator
import org.specs2.mutable.Specification
import play.{ ApplicationLoader, BuiltInComponentsFromContext }
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.WithApplication
import play.api.Application
import play.core.j.JavaContextComponents
import play.data.validation.ValidationError
import play.mvc.EssentialFilter
import play.mvc.Http.{ Context, Request, RequestBuilder }
import play.routing.Router
import play.twirl.api.Html

import scala.beans.BeanProperty
import scala.collection.JavaConverters._
import scala.compat.java8.OptionConverters._

class RuntimeDependencyInjectionFormSpec extends FormSpec {
  private var app: Option[Application] = None

  override def defaultContextComponents: JavaContextComponents = app.getOrElse(application()).injector.instanceOf[JavaContextComponents]

  override def formFactory: FormFactory = app.getOrElse(application()).injector.instanceOf[FormFactory]

  override def application(extraConfig: (String, Any)*): Application = {
    val builtApp = GuiceApplicationBuilder().configure(extraConfig.toMap).build()
    app = Option(builtApp)
    builtApp
  }
}

class CompileTimeDependencyInjectionFormSpec extends FormSpec {

  class MyComponents(context: ApplicationLoader.Context, extraConfig: Map[String, Any] = Map.empty) extends BuiltInComponentsFromContext(context)
    with FormFactoryComponents {
    override def router(): Router = Router.empty()

    override def httpFilters(): java.util.List[EssentialFilter] = java.util.Collections.emptyList()

    override def config(): Config = {
      val javaExtraConfig = extraConfig.mapValues {
        case v: Seq[Any] => v.asJava
        case v => v
      }.asJava
      ConfigFactory.parseMap(javaExtraConfig).withFallback(super.config())
    }
  }

  private var components: Option[MyComponents] = None
  private lazy val context = ApplicationLoader.create(play.Environment.simple())

  override def formFactory: FormFactory = components.getOrElse{
    new MyComponents(context)
  }.formFactory()

  override def application(extraConfig: (String, Any)*): Application = {
    val myComponents = new MyComponents(context, extraConfig.toMap)
    components = Option(myComponents)
    myComponents.application().asScala()
  }

  override def defaultContextComponents: JavaContextComponents = components.getOrElse(new MyComponents(ApplicationLoader.create(play.Environment.simple()))).javaContextComponents()
}

trait FormSpec extends Specification {

  sequential

  def formFactory: FormFactory
  def application(extraConfig: (String, Any)*): Application
  def defaultContextComponents: JavaContextComponents

  "a java form" should {

    "with a root name" should {
      "be valid with all fields" in {
        val req = FormSpec.dummyRequest(Map("task.id" -> Array("1234567891"), "task.name" -> Array("peter"), "task.dueDate" -> Array("15/12/2009"), "task.endDate" -> Array("2008-11-21")))
        Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

        val myForm = formFactory.form("task", classOf[play.data.Task]).bindFromRequest()
        myForm hasErrors () must beEqualTo(false)
      }
      "allow to access the value of an invalid form prefixing fields with the root name" in new WithApplication(application()) {
        val req = FormSpec.dummyRequest(Map("task.id" -> Array("notAnInt"), "task.name" -> Array("peter"), "task.done" -> Array("true"), "task.dueDate" -> Array("15/12/2009")))
        Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

        val myForm = formFactory.form("task", classOf[play.data.Task]).bindFromRequest()

        myForm hasErrors () must beEqualTo(true)
        myForm.field("task.name").value.asScala must beSome("peter")
      }
      "have an error due to missing required value" in new WithApplication(application()) {
        val contextComponents = defaultContextComponents

        val req = FormSpec.dummyRequest(Map("task.id" -> Array("1234567891x"), "task.name" -> Array("peter")))
        Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, contextComponents))

        val myForm = formFactory.form("task", classOf[play.data.Task]).bindFromRequest()
        myForm hasErrors () must beEqualTo(true)
        myForm.errors("task.dueDate").get(0).messages().asScala must contain("error.required")
      }
    }
    "be valid with all fields" in {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("15/12/2009"), "endDate" -> Array("2008-11-21")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
    }
    "be valid with mandatory params passed" in {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("15/12/2009")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
    }
    "query params ignored when using POST" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "POST", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getName() must beEqualTo("peter")
      myForm.value().get().getId() must beEqualTo(null)
    }
    "query params ignored when using PUT" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "PUT", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getName() must beEqualTo("peter")
      myForm.value().get().getId() must beEqualTo(null)
    }
    "query params ignored when using PATCH" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "PATCH", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getName() must beEqualTo("peter")
      myForm.value().get().getId() must beEqualTo(null)
    }

    "query params NOT ignored when using GET" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "GET", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() must beEqualTo(LocalDate.of(2009, 12, 15)) // we also parse the body for GET requests
      myForm.value().get().getName() must beEqualTo("michael") // but query param overwrites body when using GET
      myForm.value().get().getId() must beEqualTo(55555)
    }
    "query params NOT ignored when using DELETE" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "DELETE", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() must beEqualTo(LocalDate.of(2009, 12, 15)) // we also parse the body for DELETE requests
      myForm.value().get().getName() must beEqualTo("michael") // but query param overwrites body when using DELETE
      myForm.value().get().getId() must beEqualTo(55555)
    }
    "query params NOT ignored when using HEAD" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "HEAD", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() must beEqualTo(LocalDate.of(2009, 12, 15)) // we also parse the body for HEAD requests
      myForm.value().get().getName() must beEqualTo("michael") // but query param overwrites body when using HEAD
      myForm.value().get().getId() must beEqualTo(55555)
    }
    "query params NOT ignored when using OPTIONS" in {
      val req = FormSpec.dummyRequest(Map("name" -> Array("peter"), "dueDate" -> Array("15/12/2009")), "OPTIONS", "?name=michael&id=55555")
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(false)
      myForm.value().get().getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() must beEqualTo(LocalDate.of(2009, 12, 15)) // we also parse the body for OPTIONS requests
      myForm.value().get().getName() must beEqualTo("michael") // but query param overwrites body when using OPTIONS
      myForm.value().get().getId() must beEqualTo(55555)
    }

    "have an error due to badly formatted date" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("2009/11e/11")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("dueDate").get(0).messages().size() must beEqualTo(2)
      myForm.errors("dueDate").get(0).messages().get(1) must beEqualTo("error.invalid.java.util.Date")
      myForm.errors("dueDate").get(0).messages().get(0) must beEqualTo("error.invalid")
      myForm.errors("dueDate").get(0).message() must beEqualTo("error.invalid.java.util.Date")

      // make sure we can access the values of an invalid form
      myForm.value().get().getId() must beEqualTo(1234567891)
      myForm.value().get().getName() must beEqualTo("peter")
    }
    "throws an exception when trying to access value of invalid form via get()" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("2009/11e/11")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm.get must throwAn[IllegalStateException]
    }
    "allow to access the value of an invalid form even when not even one valid value was supplied" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("notAnInt"), "dueDate" -> Array("2009/11e/11")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm.value().get().getId() must_== null
      myForm.value().get().getName() must_== null
    }
    "have an error due to badly formatted date after using setTransientLang" in new WithApplication(application("play.i18n.langs" -> Seq("en", "en-US", "fr"))) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("2009/11e/11")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      Context.current.get().setTransientLang("fr")

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("dueDate").get(0).messages().size() must beEqualTo(3)
      myForm.errors("dueDate").get(0).messages().get(2) must beEqualTo("error.invalid.dueDate") // is ONLY defined in messages.fr
      myForm.errors("dueDate").get(0).messages().get(1) must beEqualTo("error.invalid.java.util.Date") // is defined in play's default messages file
      myForm.errors("dueDate").get(0).messages().get(0) must beEqualTo("error.invalid") // is defined in play's default messages file
      myForm.errors("dueDate").get(0).message() must beEqualTo("error.invalid.dueDate") // is ONLY defined in messages.fr
    }
    "have an error due to badly formatted date after using changeLang" in new WithApplication(application("play.i18n.langs" -> Seq("en", "en-US", "fr"))) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("2009/11e/11")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      Context.current.get().changeLang("fr")

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("dueDate").get(0).messages().size() must beEqualTo(3)
      myForm.errors("dueDate").get(0).messages().get(2) must beEqualTo("error.invalid.dueDate") // is ONLY defined in messages.fr
      myForm.errors("dueDate").get(0).messages().get(1) must beEqualTo("error.invalid.java.util.Date") // is defined in play's default messages file
      myForm.errors("dueDate").get(0).messages().get(0) must beEqualTo("error.invalid") // is defined in play's default messages file
      myForm.errors("dueDate").get(0).message() must beEqualTo("error.invalid.dueDate") // is ONLY defined in messages.fr
    }
    "have an error due to missing required value" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891x"), "name" -> Array("peter")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("dueDate").get(0).messages().asScala must contain("error.required")
    }
    "have an error due to bad value in Id field" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891x"), "name" -> Array("peter"), "dueDate" -> Array("12/12/2009")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("id").get(0).messages().asScala must contain("error.invalid")
    }

    "have an error due to badly formatted date for default date binder" in new WithApplication(application()) {
      val req = FormSpec.dummyRequest(Map("id" -> Array("1234567891"), "name" -> Array("peter"), "dueDate" -> Array("15/12/2009"), "endDate" -> Array("2008-11e-21")))
      Context.current.set(new Context(666, null, req, Map.empty.asJava, Map.empty.asJava, Map.empty.asJava, defaultContextComponents))

      val myForm = formFactory.form(classOf[play.data.Task]).bindFromRequest()
      myForm hasErrors () must beEqualTo(true)
      myForm.errors("endDate").get(0).messages().asScala must contain("error.invalid.java.util.Date")
    }

    "support repeated values for Java binding" in {

      val user1 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki")))).get
      user1.getName must beEqualTo("Kiki")
      user1.getEmails.size must beEqualTo(0)

      val user2 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki"), "emails[0]" -> Array("kiki@gmail.com")))).get
      user2.getName must beEqualTo("Kiki")
      user2.getEmails.size must beEqualTo(1)

      val user3 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki"), "emails[0]" -> Array("kiki@gmail.com"), "emails[1]" -> Array("kiki@zen.com")))).get
      user3.getName must beEqualTo("Kiki")
      user3.getEmails.size must beEqualTo(2)

      val user4 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki"), "emails[]" -> Array("kiki@gmail.com")))).get
      user4.getName must beEqualTo("Kiki")
      user4.getEmails.size must beEqualTo(1)

      val user5 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki"), "emails[]" -> Array("kiki@gmail.com", "kiki@zen.com")))).get
      user5.getName must beEqualTo("Kiki")
      user5.getEmails.size must beEqualTo(2)

    }

    "support optional deserialization of a common map" in {
      val data = new util.HashMap[String, String]()
      data.put("name", "Kiki")

      val userForm1: Form[AnotherUser] = formFactory.form(classOf[AnotherUser])
      val user1 = userForm1.bind(new java.util.HashMap[String, String]()).get()
      user1.getCompany.isPresent must beFalse

      data.put("company", "Acme")

      val userForm2: Form[AnotherUser] = formFactory.form(classOf[AnotherUser])
      val user2 = userForm2.bind(data).get()
      user2.getCompany.isPresent must beTrue
    }

    "support optional deserialization of a request" in {
      val user1 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki")))).get
      user1.getCompany.isPresent must beEqualTo(false)

      val user2 = formFactory.form(classOf[AnotherUser]).bindFromRequest(FormSpec.dummyRequest(Map("name" -> Array("Kiki"), "company" -> Array("Acme")))).get
      user2.getCompany.get must beEqualTo("Acme")
    }

    "bind when valid" in {
      val userForm: Form[MyUser] = formFactory.form(classOf[MyUser])
      val user = userForm.bind(new java.util.HashMap[String, String]()).get()
      userForm.hasErrors() must equalTo(false)
      (user == null) must equalTo(false)
    }

    "support email validation" in {
      val userEmail = formFactory.form(classOf[UserEmail])
      userEmail.bind(Map("email" -> "john@example.com").asJava).errors().asScala must beEmpty
      userEmail.bind(Map("email" -> "o'flynn@example.com").asJava).errors().asScala must beEmpty
      userEmail.bind(Map("email" -> "john@ex'ample.com").asJava).errors().asScala must not(beEmpty)
    }

    "support custom validators" in {
      "that fails when validator's condition is not met" in {
        val form = formFactory.form(classOf[Red])
        val bound = form.bind(Map("name" -> "blue").asJava)
        bound.hasErrors must_== true
        bound.hasGlobalErrors must_== true
        bound.globalErrors().asScala must not(beEmpty)
      }

      "that returns customized message when validator fails" in {
        val form = formFactory.form(classOf[MyBlueUser]).bind(
          Map("name" -> "Shrek", "skinColor" -> "green", "hairColor" -> "blue", "nailColor" -> "darkblue").asJava)
        form.hasErrors must beEqualTo(true)
        form.errors("hairColor").asScala must beEmpty
        form.errors("nailColor").asScala must beEmpty
        val validationErrors = form.errors("skinColor")
        validationErrors.size() must beEqualTo(1)
        validationErrors.get(0).message must beEqualTo("notblue")
        validationErrors.get(0).arguments().size must beEqualTo(2)
        validationErrors.get(0).arguments().get(0) must beEqualTo("argOne")
        validationErrors.get(0).arguments().get(1) must beEqualTo("argTwo")
      }

      "that returns customized message in annotation when validator fails" in {
        val form = formFactory.form(classOf[MyBlueUser]).bind(
          Map("name" -> "Smurf", "skinColor" -> "blue", "hairColor" -> "white", "nailColor" -> "darkblue").asJava)
        form.errors("skinColor").asScala must beEmpty
        form.errors("nailColor").asScala must beEmpty
        form.hasErrors must beEqualTo(true)
        val validationErrors = form.errors("hairColor")
        validationErrors.size() must beEqualTo(1)
        validationErrors.get(0).message must beEqualTo("i-am-blue")
        validationErrors.get(0).arguments().size must beEqualTo(0)
      }

      "that returns customized message when validator fails even when args param from getErrorMessageKey is null" in {
        val form = formFactory.form(classOf[MyBlueUser]).bind(
          Map("name" -> "Nemo", "skinColor" -> "blue", "hairColor" -> "blue", "nailColor" -> "yellow").asJava)
        form.errors("skinColor").asScala must beEmpty
        form.errors("hairColor").asScala must beEmpty
        form.hasErrors must beEqualTo(true)
        val validationErrors = form.errors("nailColor")
        validationErrors.size() must beEqualTo(1)
        validationErrors.get(0).message must beEqualTo("notdarkblue")
        validationErrors.get(0).arguments().size must beEqualTo(0)
      }

    }

    "support type arguments constraints" in {
      val listForm = formFactory.form(classOf[TypeArgumentForm]).bindFromRequest(FormSpec.dummyRequest(Map(
        "list[0]" -> Array("4"), "list[1]" -> Array("-3"), "list[2]" -> Array("6"),
        "map['ab']" -> Array("28"), "map['something']" -> Array("2"), "map['worksperfect']" -> Array("87"),
        "optional" -> Array("Acme")
      )))

      listForm.hasErrors must beEqualTo(true)
      listForm.errors().size() must beEqualTo(4)
      listForm.errors("list[1]").get(0).messages().size() must beEqualTo(1)
      listForm.errors("list[1]").get(0).messages().get(0) must beEqualTo("error.min")
      listForm.value().get().getList.get(0) must beEqualTo(4)
      listForm.value().get().getList.get(1) must beEqualTo(-3)
      listForm.value().get().getList.get(2) must beEqualTo(6)
      listForm.errors("map[ab]").get(0).messages().get(0) must beEqualTo("error.minLength")
      listForm.value().get().getMap.get("ab") must beEqualTo(28)
      listForm.errors("map[something]").get(0).messages().get(0) must beEqualTo("error.min")
      listForm.value().get().getMap.get("something") must beEqualTo(2)
      listForm.value().get().getMap.get("worksperfect") must beEqualTo(87)
      listForm.errors("optional").get(0).messages().get(0) must beEqualTo("error.minLength")
      listForm.value().get().getOptional.get must beEqualTo("Acme")
      // Also test an Optional that binds a value but doesn't cause a validation error:
      val optForm = formFactory.form(classOf[TypeArgumentForm]).bindFromRequest(FormSpec.dummyRequest(Map(
        "optional" -> Array("Microsoft Corporation")
      )))
      optForm.errors().size() must beEqualTo(0)
      optForm.get().getOptional.get must beEqualTo("Microsoft Corporation")
    }

    "support @repeatable constraints" in {
      val form = formFactory.form(classOf[RepeatableConstraintsForm]).bind(Map("name" -> "xyz").asJava)
      form.field("name").constraints().size() must beEqualTo(4)
      form.field("name").constraints().get(0)._1 must beEqualTo("constraint.validatewith")
      form.field("name").constraints().get(1)._1 must beEqualTo("constraint.validatewith")
      form.field("name").constraints().get(2)._1 must beEqualTo("constraint.pattern")
      form.field("name").constraints().get(3)._1 must beEqualTo("constraint.pattern")
      form.hasErrors must beEqualTo(true)
      form.hasGlobalErrors() must beEqualTo(false)
      form.errors().size() must beEqualTo(4)
      form.errors("name").size() must beEqualTo(4)
      val nameErrorMessages = form.errors("name").asScala.flatMap(_.messages().asScala)
      nameErrorMessages.size must beEqualTo(4)
      nameErrorMessages must contain("Should be a - c")
      nameErrorMessages must contain("Should be c - h")
      nameErrorMessages must contain("notgreen")
      nameErrorMessages must contain("notblue")
    }

    "work with the @repeat helper" in {
      val form = formFactory.form(classOf[JavaForm])

      import play.core.j.PlayFormsMagicForJava._

      def render(form: Form[_], min: Int = 1) = views.html.helper.repeat.apply(form("foo"), min) { f =>
        val a = f("a")
        val b = f("b")
        Html(s"${a.name}=${a.value.getOrElse("")},${b.name}=${b.value.getOrElse("")}")
      }.map(_.toString)

      "render the right number of fields if there's multiple sub fields at a given index when filled from a value" in {
        render(
          form.fill(new JavaForm(List(new JavaSubForm("somea", "someb")).asJava))
        ) must exactly("foo[0].a=somea,foo[0].b=someb")
      }

      "render the right number of fields if there's multiple sub fields at a given index when filled from a form" in {
        render(
          fillNoBind("somea" -> "someb")
        ) must exactly("foo[0].a=somea,foo[0].b=someb")
      }

      "get the order of the fields correct when filled from a value" in {
        render(
          form.fill(new JavaForm(List(new JavaSubForm("a", "b"), new JavaSubForm("c", "d"),
            new JavaSubForm("e", "f"), new JavaSubForm("g", "h")).asJava))
        ) must exactly("foo[0].a=a,foo[0].b=b", "foo[1].a=c,foo[1].b=d",
            "foo[2].a=e,foo[2].b=f", "foo[3].a=g,foo[3].b=h").inOrder
      }

      "get the order of the fields correct when filled from a form" in {
        render(
          fillNoBind("a" -> "b", "c" -> "d", "e" -> "f", "g" -> "h")
        ) must exactly("foo[0].a=a,foo[0].b=b", "foo[1].a=c,foo[1].b=d",
            "foo[2].a=e,foo[2].b=f", "foo[3].a=g,foo[3].b=h").inOrder
      }
    }

    "work with the @repeatWithIndex helper" in {
      val form = formFactory.form(classOf[JavaForm])

      import play.core.j.PlayFormsMagicForJava._

      def render(form: Form[_], min: Int = 1) = views.html.helper.repeatWithIndex.apply(form("foo"), min) { (f, i) =>
        val a = f("a")
        val b = f("b")
        Html(s"${a.name}=${a.value.getOrElse("")}${i},${b.name}=${b.value.getOrElse("")}${i}")
      }.map(_.toString)

      "render the right number of fields if there's multiple sub fields at a given index when filled from a value" in {
        render(
          form.fill(new JavaForm(List(new JavaSubForm("somea", "someb")).asJava))
        ) must exactly("foo[0].a=somea0,foo[0].b=someb0")
      }

      "render the right number of fields if there's multiple sub fields at a given index when filled from a form" in {
        render(
          fillNoBind("somea" -> "someb")
        ) must exactly("foo[0].a=somea0,foo[0].b=someb0")
      }

      "get the order of the fields correct when filled from a value" in {
        render(
          form.fill(new JavaForm(List(new JavaSubForm("a", "b"), new JavaSubForm("c", "d"),
            new JavaSubForm("e", "f"), new JavaSubForm("g", "h")).asJava))
        ) must exactly("foo[0].a=a0,foo[0].b=b0", "foo[1].a=c1,foo[1].b=d1",
            "foo[2].a=e2,foo[2].b=f2", "foo[3].a=g3,foo[3].b=h3").inOrder
      }

      "get the order of the fields correct when filled from a form" in {
        render(
          fillNoBind("a" -> "b", "c" -> "d", "e" -> "f", "g" -> "h")
        ) must exactly("foo[0].a=a0,foo[0].b=b0", "foo[1].a=c1,foo[1].b=d1",
            "foo[2].a=e2,foo[2].b=f2", "foo[3].a=g3,foo[3].b=h3").inOrder
      }
    }

    def fillNoBind(values: (String, String)*) = {
      val map = values.zipWithIndex.flatMap {
        case ((a, b), i) => Seq("foo[" + i + "].a" -> a, "foo[" + i + "].b" -> b)
      }.toMap
      // Don't use bind, the point here is to have a form with data that isn't bound, otherwise the mapping indexes
      // used come from the form, not the input data
      new Form[JavaForm](null, classOf[JavaForm], map.asJava,
        List.empty.asJava.asInstanceOf[java.util.List[ValidationError]], Optional.empty[JavaForm], null, null, FormSpec.validator())
    }

    "return the appropriate constraints for the desired validation group(s)" in {
      "when NOT supplying a group all constraints that have the javax.validation.groups.Default group should be returned" in {
        // (When a constraint annotation doesn't define a "groups" attribute, it's default group will be Default.class by default)
        val myForm = formFactory.form(classOf[SomeUser])
        myForm.field("email").constraints().size() must beEqualTo(2)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("firstName").constraints().size() must beEqualTo(2)
        myForm.field("firstName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("firstName").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("lastName").constraints().size() must beEqualTo(3)
        myForm.field("lastName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("lastName").constraints().get(1)._1 must beEqualTo("constraint.minLength")
        myForm.field("lastName").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
        myForm.field("password").constraints().size() must beEqualTo(2)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.minLength")
        myForm.field("password").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(2)
        myForm.field("repeatPassword").constraints().get(0)._1 must beEqualTo("constraint.minLength")
        myForm.field("repeatPassword").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
      }

      "when NOT supplying the Default.class group all constraints that have the javax.validation.groups.Default group should be returned" in {
        // The exact same tests again, but now we explicitly supply the Default.class group
        val myForm = formFactory.form(classOf[SomeUser], classOf[Default])
        myForm.field("email").constraints().size() must beEqualTo(2)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("firstName").constraints().size() must beEqualTo(2)
        myForm.field("firstName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("firstName").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("lastName").constraints().size() must beEqualTo(3)
        myForm.field("lastName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("lastName").constraints().get(1)._1 must beEqualTo("constraint.minLength")
        myForm.field("lastName").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
        myForm.field("password").constraints().size() must beEqualTo(2)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.minLength")
        myForm.field("password").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(2)
        myForm.field("repeatPassword").constraints().get(0)._1 must beEqualTo("constraint.minLength")
        myForm.field("repeatPassword").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
      }

      "only return constraints for a specific group" in {
        // Only return the constraints for the PasswordCheck
        val myForm = formFactory.form(classOf[SomeUser], classOf[PasswordCheck])
        myForm.field("email").constraints().size() must beEqualTo(0)
        myForm.field("firstName").constraints().size() must beEqualTo(0)
        myForm.field("lastName").constraints().size() must beEqualTo(0)
        myForm.field("password").constraints().size() must beEqualTo(1)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(1)
        myForm.field("repeatPassword").constraints().get(0)._1 must beEqualTo("constraint.required")
      }

      "only return constraints for another specific group" in {
        // Only return the constraints for the LoginCheck
        val myForm = formFactory.form(classOf[SomeUser], classOf[LoginCheck])
        myForm.field("email").constraints().size() must beEqualTo(2)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.email")
        myForm.field("firstName").constraints().size() must beEqualTo(0)
        myForm.field("lastName").constraints().size() must beEqualTo(0)
        myForm.field("password").constraints().size() must beEqualTo(1)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(0)
      }

      "return constraints for two given groups" in {
        // Only return the required constraint for the LoginCheck and the PasswordCheck
        val myForm = formFactory.form(classOf[SomeUser], classOf[LoginCheck], classOf[PasswordCheck])
        myForm.field("email").constraints().size() must beEqualTo(2)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.email")
        myForm.field("firstName").constraints().size() must beEqualTo(0)
        myForm.field("lastName").constraints().size() must beEqualTo(0)
        myForm.field("password").constraints().size() must beEqualTo(1)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(1)
        myForm.field("repeatPassword").constraints().get(0)._1 must beEqualTo("constraint.required")
      }

      "return constraints for three given groups where on of them is the Default group" in {
        // Only return the required constraint for the LoginCheck, PasswordCheck and the Default group
        val myForm = formFactory.form(classOf[SomeUser], classOf[LoginCheck], classOf[PasswordCheck], classOf[Default])
        myForm.field("email").constraints().size() must beEqualTo(3)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.email")
        myForm.field("email").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
        myForm.field("firstName").constraints().size() must beEqualTo(2)
        myForm.field("firstName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("firstName").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("lastName").constraints().size() must beEqualTo(3)
        myForm.field("lastName").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("lastName").constraints().get(1)._1 must beEqualTo("constraint.minLength")
        myForm.field("lastName").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
        myForm.field("password").constraints().size() must beEqualTo(3)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("password").constraints().get(1)._1 must beEqualTo("constraint.minLength")
        myForm.field("password").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
        myForm.field("repeatPassword").constraints().size() must beEqualTo(3)
        myForm.field("repeatPassword").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("repeatPassword").constraints().get(1)._1 must beEqualTo("constraint.minLength")
        myForm.field("repeatPassword").constraints().get(2)._1 must beEqualTo("constraint.maxLength")
      }
    }

    "respect the order of validation groups defined via group sequences" in {
      "first group gets validated and already fails and therefore second group wont even get validated anymore" in {
        val myForm = formFactory.form(classOf[SomeUser], classOf[OrderedChecks]).bind(Map("email" -> "invalid_email", "password" -> "", "repeatPassword" -> "").asJava)
        // first group
        myForm.errors("email").size() must beEqualTo(1)
        myForm.errors("email").get(0).message() must beEqualTo("error.email")
        myForm.errors("password").size() must beEqualTo(1)
        myForm.errors("password").get(0).message() must beEqualTo("error.required")
        // next group
        myForm.errors("repeatPassword").size() must beEqualTo(0)
      }
      "first group gets validated and already succeeds but then second group fails" in {
        val myForm = formFactory.form(classOf[SomeUser], classOf[OrderedChecks]).bind(Map("email" -> "larry@google.com", "password" -> "asdfasdf", "repeatPassword" -> "").asJava)
        // first group
        myForm.errors("email").size() must beEqualTo(0)
        myForm.errors("password").size() must beEqualTo(0)
        // next group
        myForm.errors("repeatPassword").size() must beEqualTo(1)
        myForm.errors("repeatPassword").get(0).message() must beEqualTo("error.required")
      }
      "all group gets validated and succeed" in {
        val myForm = formFactory.form(classOf[SomeUser], classOf[OrderedChecks]).bind(Map("email" -> "larry@google.com", "password" -> "asdfasdf", "repeatPassword" -> "asdfasdf").asJava)
        // first group
        myForm.errors("email").size() must beEqualTo(0)
        myForm.errors("password").size() must beEqualTo(0)
        // next group
        myForm.errors("repeatPassword").size() must beEqualTo(0)
        myForm.hasErrors() must beEqualTo(false)
        myForm.hasGlobalErrors() must beEqualTo(false)
      }
    }

    "honor its validate method" in {
      "when it returns an error object" in {
        val myForm = formFactory.form(classOf[SomeUser]).bind(Map("password" -> "asdfasdf", "repeatPassword" -> "vwxyz").asJava)
        myForm.error("password").get.message() must beEqualTo ("Passwords do not match")
      }
      "when it returns an null (error) object" in {
        val myForm = formFactory.form(classOf[SomeUser]).bind(Map("password" -> "asdfasdf", "repeatPassword" -> "asdfasdf").asJava)
        myForm.globalErrors().size() must beEqualTo(0)
        myForm.errors("password").size() must beEqualTo(0)
      }
      "when it returns an error object but is skipped because its not in validation group" in {
        val myForm = formFactory.form(classOf[SomeUser], classOf[LoginCheck]).bind(Map("password" -> "asdfasdf", "repeatPassword" -> "vwxyz").asJava)
        myForm.error("password").isPresent must beFalse
      }
      "when it returns a string" in {
        val myForm = formFactory.form(classOf[LoginUser]).bind(Map("email" -> "fail@google.com").asJava)
        myForm.globalErrors().size() must beEqualTo(1)
        myForm.globalErrors().get(0).message() must beEqualTo("Invalid email provided!")
      }
      "when it returns an empty string" in {
        val myForm = formFactory.form(classOf[LoginUser]).bind(Map("email" -> "bill.gates@microsoft.com").asJava)
        myForm.globalErrors().size() must beEqualTo(1)
        myForm.globalErrors().get(0).message() must beEqualTo("")
      }
      "when it returns an error list" in {
        val myForm = formFactory.form(classOf[AnotherUser]).bind(Map("name" -> "Bob Marley").asJava)
        myForm.globalErrors().size() must beEqualTo(1)
        myForm.globalErrors().get(0).message() must beEqualTo("Form could not be processed")
        myForm.errors("name").size() must beEqualTo(1)
        myForm.errors("name").get(0).message() must beEqualTo("Name not correct")
      }
      "when it returns an empty error list" in {
        val myForm = formFactory.form(classOf[AnotherUser]).bind(Map("name" -> "Kiki").asJava)
        myForm.globalErrors().size() must beEqualTo(0)
        myForm.errors().size() must beEqualTo(0)
        myForm.errors("name").size() must beEqualTo(0)
      }
    }

    "not process it's legacy validate method when the Validatable interface is implemented" in {
      val myForm = formFactory.form(classOf[LegacyUser]).bind(Map("foo" -> "foo").asJava)
      myForm.globalErrors().size() must beEqualTo(0)
    }

    "keep the declared order of constraint annotations" in {
      "return the constraints in the same order we declared them" in {
        val myForm = formFactory.form(classOf[LoginUser])
        myForm.field("email").constraints().size() must beEqualTo(6)
        myForm.field("email").constraints().get(0)._1 must beEqualTo("constraint.pattern")
        myForm.field("email").constraints().get(1)._1 must beEqualTo("constraint.validatewith")
        myForm.field("email").constraints().get(2)._1 must beEqualTo("constraint.required")
        myForm.field("email").constraints().get(3)._1 must beEqualTo("constraint.minLength")
        myForm.field("email").constraints().get(4)._1 must beEqualTo("constraint.email")
        myForm.field("email").constraints().get(5)._1 must beEqualTo("constraint.maxLength")
      }

      "return the constraints in the same order we declared them, mixed with a non constraint annotation" in {
        val myForm = formFactory.form(classOf[LoginUser])
        myForm.field("name").constraints().size() must beEqualTo(6)
        myForm.field("name").constraints().get(0)._1 must beEqualTo("constraint.required")
        myForm.field("name").constraints().get(1)._1 must beEqualTo("constraint.maxLength")
        myForm.field("name").constraints().get(2)._1 must beEqualTo("constraint.email")
        myForm.field("name").constraints().get(3)._1 must beEqualTo("constraint.minLength")
        myForm.field("name").constraints().get(4)._1 must beEqualTo("constraint.pattern")
        myForm.field("name").constraints().get(5)._1 must beEqualTo("constraint.validatewith")
      }

      "return the constraints of a superclass in the same order we declared them" in {
        val myForm = formFactory.form(classOf[LoginUser])
        myForm.field("password").constraints().size() must beEqualTo(6)
        myForm.field("password").constraints().get(0)._1 must beEqualTo("constraint.minLength")
        myForm.field("password").constraints().get(1)._1 must beEqualTo("constraint.validatewith")
        myForm.field("password").constraints().get(2)._1 must beEqualTo("constraint.required")
        myForm.field("password").constraints().get(3)._1 must beEqualTo("constraint.maxLength")
        myForm.field("password").constraints().get(4)._1 must beEqualTo("constraint.pattern")
        myForm.field("password").constraints().get(5)._1 must beEqualTo("constraint.email")
      }
    }
  }

}

object FormSpec {

  def dummyRequest(data: Map[String, Array[String]], method: String = "POST", query: String = ""): Request = {
    new RequestBuilder()
      .method(method)
      .uri("http://localhost/test" + query)
      .bodyFormArrayValues(data.asJava)
      .build()
  }

  def validator(): Validator = {
    val validationConfig: vConfiguration[_] = Validation.byDefaultProvider().configure().messageInterpolator(new ParameterMessageInterpolator())
    validationConfig.buildValidatorFactory().getValidator()
  }

}

class JavaForm(@BeanProperty var foo: java.util.List[JavaSubForm]) {
  def this() = this(null)
}
class JavaSubForm(@BeanProperty var a: String, @BeanProperty var b: String) {
  def this() = this(null, null)
}


text:
'use strict';

function urlShortner (db) {
  var UrlShortnerHelper = require(process.cwd() + '/app/helpers/urlShortnerHelper.js');

  var urls = db.collection('urls');

  this.redirectUrl = function(req, res){
    var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;

    var urlQuery = {
      "short_url": {
        "$eq": fullUrl
      }
    }

    urls.findOne(urlQuery, {}, function(err, result) {
      if (err) {
        throw err;
      }

      if (result)
      {
        res.redirect(result.original_url)
      }
      else
      {
        res.json({"error":"No short url found for given input"});
      }
    });
  }

  this.addUrl = function(req, res) {
    var urlShortnerHelper = new UrlShortnerHelper();

    if (!urlShortnerHelper.isAValidUrl(req.params.url)){
      res.json( { "error" : "URL invalid. Valid format is http://www.example.com" } );
      return;
    }

    var hostUrl = req.protocol + '://' + req.get('host');

    var shortUrl = urlShortnerHelper.generateShortUrl(hostUrl)

    var urlProjection = {  '_id': false }

    var urlQuery = {
      "short_url": {
        "$eq": shortUrl
      }
    }

    var insertObj = { 'original_url': req.params.url,
                      'short_url' : shortUrl }

    urls.insert(insertObj, function (err) {
      if (err) {
         throw err;
      }

       urls.findOne(urlQuery, urlProjection, function (err, url) {
          if (err) {
             throw err;
          }

          res.json(url);
       });
    });
  }
}

module.exports = urlShortner;


text:
Docker **sequana_conda_ngs**
====================================

Overview
---------

This is a Docker image on top on sequana/sequana_ngs that installs
conda packages (NGS specific) for **Sequana**.

Description
----------------

Se the sequana_install.sh for detailled list of packages.

Here are some of them:

- snakemake
- bioservices
- pyvcf
- spades
- bwa
- freebates
- kraken
- bowtie2

For developers:
------------------

Build the image::

    git clone https://github.com/sequana/sequana
    cd sequana/docker/sequana_conda_ngs
    sh build.sh

Push on hub.docker.com::

    sh push.sh

Run the local image (not a pulled one in this example)::

    sudo docker run -it sequana_conda_ngs


text:
<TestStep assemblyPath="" typeName="BizUnit.FileMoveStep" failOnError="true" runConcurrently="false">
<!--
            <SourcePath>C:\Kevin\Code-Projects\BizUnit\BizUnit3.0\Src\BizUnit.Tests\Out\InDoc1.xml</SourcePath>
            <DestinationPath>C:\Kevin\Code-Projects\BizUnit\BizUnit3.0\Src\BizUnit.Tests\Out\MovedDoc.xml</DestinationPath>

-->
  <SourcePath>..\..\..\Test\BizUnit.Tests\Out\InDoc1.xml</SourcePath>
            <DestinationPath>..\..\..\Test\BizUnit.Tests\Out\MovedDoc.xml</DestinationPath>
</TestStep>


text:
package com.prowidesoftware.swift.model.mt.mt6xx;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

public class MT671Test {

    @Test
    public void test1() {
        MT671 m = new MT671();
        m.append(MT671.SequenceB.newInstance(MT671.SequenceB2.newInstance()));
        assertTrue(m.getSequenceC().isEmpty());
    }

    /**
     * Sequence C and B2 use the same delimiter so we need to add parent sequence for unique find
     */
    @Test
    public void test2() {
        MT671 m = new MT671();
        m.append(MT671.SequenceB.newInstance());
        m.append(MT671.SequenceC.newInstance());
        assertTrue(m.getSequenceB2List().isEmpty());
    }

    @Test
    public void test3() {
        MT671 m = new MT671();
        m.append(MT671.SequenceC.newInstance());
        assertFalse(m.getSequenceC().isEmpty());
    }

}


text:
<?php

namespace Web\Response\Abstraction;

interface HeaderInterface
{
    /**
     * Return string representation of object
     *
     * return string
     */
    public function toString();
}


text:
package build.tools.jdwpgen;

import java.util.*;
import java.io.*;

class UntaggedValueTypeNode extends ValueTypeNode {

    String docType() {
        return "untagged-value";
    }

    public void genJavaWrite(PrintWriter writer, int depth,
                             String writeLabel) {
        genJavaDebugWrite(writer, depth, writeLabel);
        indent(writer, depth);
        writer.println("ps.writeUntaggedValue(" + writeLabel + ");");
    }

    String javaRead() {
        return "ps.readUntaggedValue()";
    }
}


text:
module Specinfra
  module Backend
    class Docker < Exec
      def initialize(config = {})
        super

        begin
          require 'docker' unless defined?(::Docker)
        rescue LoadError
          fail "Docker client library is not available. Try installing `docker-api' gem."
        end

        ::Docker.url = get_config(:docker_url)

        if image = get_config(:docker_image)
          @images = []
          @base_image = get_or_pull_image(image)

          create_and_start_container
          ObjectSpace.define_finalizer(self, proc { cleanup_container })
        elsif container = get_config(:docker_container)
          @container = ::Docker::Container.get(container)
        else
          fail 'Please specify docker_image or docker_container.'
        end
      end

      def run_command(cmd, opts={})
        cmd = build_command(cmd)
        run_pre_command(opts)
        docker_run!(cmd, opts)
      end

      def send_file(from, to)
        if @base_image
          @images << commit_container if @container
          @images << current_image.insert_local('localPath' => from, 'outputPath' => to)
          cleanup_container
          create_and_start_container
        elsif @container
          # This needs Docker >= 1.8
          @container.archive_in(from, to)
        else
          fail 'Cannot call send_file without docker_image or docker_container.'
        end
      end

      def commit_container
        @container.commit
      end

      private

      def create_and_start_container
        opts = { 'Image' => current_image.id }

        if current_image.json["Config"]["Cmd"].nil? && current_image.json["Config"]["Entrypoint"].nil?
          opts.merge!({'Cmd' => ['/bin/sh']})
        end

        opts.merge!({'OpenStdin' => true})

        if path = get_config(:path)
          (opts['Env'] ||= []) << "PATH=#{path}"
        end

        env = get_config(:env).to_a.map { |v| v.join('=') }
        opts['Env'] = opts['Env'].to_a.concat(env)

        opts.merge!(get_config(:docker_container_create_options) || {})

        @container = ::Docker::Container.create(opts)
        @container.start
        while @container.json['State'].key?('Health') && @container.json['State']['Health']['Status'] == "starting" do
          sleep 0.5
        end
      end

      def cleanup_container
        @container.stop
        @container.delete
      end

      def current_image
        @images.last || @base_image
      end

      def docker_run!(cmd, opts={})
        opts.merge!(get_config(:docker_container_exec_options) || {})
        stdout, stderr, status = @container.exec(cmd.shellsplit, opts)

        CommandResult.new :stdout => stdout.join, :stderr => stderr.join,
        :exit_status => status
      rescue ::Docker::Error::DockerError => e
        raise
      rescue => e
        @container.kill
        err = stderr.nil? ? ([e.message] + e.backtrace) : stderr
        CommandResult.new :stdout => [stdout].join, :stderr => err.join,
        :exit_status => (status || 1)
      end

      def get_or_pull_image(name)
        begin
          ::Docker::Image.get(name)
        rescue ::Docker::Error::NotFoundError
          ::Docker::Image.create('fromImage' => name)
        end
      end

      def run_pre_command(opts)
        if get_config(:pre_command)
          cmd = build_command(get_config(:pre_command))
          docker_run!(cmd, opts)
        end
      end
    end
  end
end


text:
package ca.eandb.util.progress;

/**
 * A ProgressMonitor that synchronizes all operations on itself
 * and its descendant ProgressMonitors.  This class is a
 * decorator.
 * @author Brad Kimmel
 */
public final class SynchronizedProgressMonitor implements ProgressMonitor {

  /** The ProgressMonitor to decorate. */
  private final ProgressMonitor monitor;

  /**
   * The Object to synchronize against.  This will be the root
   * ProgressMonitor.
   */
  private final Object syncObject;

  /**
   * Creates a new SynchronizedProgressMonitor.
   * @param monitor The ProgressMonitor whose operations are to
   *     be synchronized.
   */
  public SynchronizedProgressMonitor(ProgressMonitor monitor) {
    this(monitor, monitor);
  }

  /**
   * Creates a new SynchronizedProgressMonitor.
   * @param monitor The ProgressMonitor to decorate.
   * @param syncObject The Object on which to synchronize all
   *     operations.
   */
  private SynchronizedProgressMonitor(ProgressMonitor monitor, Object syncObject) {
    this.monitor = monitor;
    this.syncObject = syncObject;
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#isCancelPending()
   */
  public boolean isCancelPending() {
    synchronized (syncObject) {
      return monitor.isCancelPending();
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#addCancelListener(ca.eandb.util.progress.CancelListener)
   */
  public void addCancelListener(CancelListener listener) {
    synchronized (syncObject) {
      monitor.addCancelListener(listener);
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyCancelled()
   */
  public void notifyCancelled() {
    synchronized (syncObject) {
      monitor.notifyCancelled();
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyComplete()
   */
  public void notifyComplete() {
    synchronized (syncObject) {
      monitor.notifyComplete();
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyIndeterminantProgress()
   */
  public boolean notifyIndeterminantProgress() {
    synchronized (syncObject) {
      return monitor.notifyIndeterminantProgress();
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyProgress(int, int)
   */
  public boolean notifyProgress(int value, int maximum) {
    synchronized (syncObject) {
      return monitor.notifyProgress(value, maximum);
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyProgress(double)
   */
  public boolean notifyProgress(double progress) {
    synchronized (syncObject) {
      return monitor.notifyProgress(progress);
    }
  }

  /* (non-Javadoc)
   * @see ca.eandb.util.progress.ProgressMonitor#notifyStatusChanged(java.lang.String)
   */
  public void notifyStatusChanged(String status) {
    synchronized (syncObject) {
      monitor.notifyStatusChanged(status);
    }
  }

}


text:
namespace {

// Listing of the accelerators that are either handled or forwarded by
// bubbles. Any accelerators that are not explicitly listed here
// are ignored and silently dropped. This table is expected to change
// after discussion over which accelerators should be addressed in
// bubbles. For a complete listing of accelerators that are used
// in chrome consult accelerators_gtk.cc
const BubbleAcceleratorGtk kAcceleratorMap[] = {
  // Tab/window controls.
  { GDK_w, GDK_CONTROL_MASK },

  // Navigation / toolbar buttons.
  { GDK_Escape, GdkModifierType(0) }
};

}  // namespace

// static
BubbleAcceleratorsGtk::const_iterator BubbleAcceleratorsGtk::begin() {
 return &kAcceleratorMap[0];
}

// static
BubbleAcceleratorsGtk::const_iterator BubbleAcceleratorsGtk::end() {
 return &kAcceleratorMap[arraysize(kAcceleratorMap)];
}


text:
<template>
    <button class="trigger-click" onclick={handleButtonClick}>click me</button>
</template>


text:
<!DOCTYPE html>

  {% include head.html %}
  {% include mathjax.html %}

    {% include header.html %}

        {{ content }}

    {% include footer.html %}

    {% include hemline.html %}


text:
from unittest.mock import Mock

import time
from tqdm import tqdm

from avalanche.benchmarks import fixed_size_experience_split, SplitMNIST, split_online_stream
from avalanche.training import ReservoirSamplingBuffer
from avalanche.training import ParametricBuffer

if __name__ == '__main__':
    benchmark = SplitMNIST(n_experiences=5)

    experience = benchmark.train_stream[0]
    print("len experience: ", len(experience.dataset))

    start = time.time()
    buffer = ReservoirSamplingBuffer(100)
    for t, exp in tqdm(enumerate(split_online_stream(benchmark.train_stream, 10))):
        buffer.update_from_dataset(exp.dataset)
        b = buffer.buffer
        # depths = _flatdata_depth(b)
        # lenidxs = len(b._indices)
        # lendsets = len(b._datasets)
        # print(f"DATA depth={depths}, idxs={lenidxs}, dsets={lendsets}")
        #
        # atts = [b.targets.data, b.targets_task_labels.data]
        # depths = [_flatdata_depth(b) for b in atts]
        # lenidxs = [len(b._indices) for b in atts]
        # lendsets = [len(b._datasets) for b in atts]
        # print(f"(t={t}) ATTS depth={depths}, idxs={lenidxs}, dsets={lendsets}")

    end = time.time()
    duration = end - start
    print("ReservoirSampling Duration: ", duration)

    start = time.time()
    buffer = ParametricBuffer(100)
    for exp in tqdm(split_online_stream(benchmark.train_stream, 10)):
        buffer.update(Mock(experience=exp, dataset=exp.dataset))
        bgs = buffer.buffer_datasets

        # depths = [_flatdata_depth(b) for b in bgs]
        # lenidxs = [len(b._indices) for b in bgs]
        # lendsets = [len(b._datasets) for b in bgs]
        # lentots = sum([len(b) for b in bgs])
        # print(f"DATA depth={depths}, idxs={lenidxs}, dsets={lendsets}, len={lentots}")
        #
        # atts = [bgs[0].targets.data, bgs[0].targets_task_labels.data]
        # depths = [_flatdata_depth(b) for b in atts]
        # lenidxs = [len(b._indices) for b in atts]
        # lendsets = [len(b._datasets) for b in atts]
        # lentots = sum([len(b) for b in bgs])
        # print(f"ATTS depth={depths}, idxs={lenidxs}, dsets={lendsets}, len={lentots}")
    end = time.time()
    duration = end - start
    print("ParametricBuffer (random sampling) Duration: ", duration)