package org.subethamail.core.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.internet.InternetAddress;
import lombok.extern.java.Log;
import org.subethamail.common.MailUtils;
import org.subethamail.common.SubEthaMessage;
import org.subethamail.core.acct.i.MyListRelationship;
import org.subethamail.core.acct.i.PersonData;
import org.subethamail.core.acct.i.SubscribedList;
import org.subethamail.core.admin.i.BlueprintData;
import org.subethamail.core.lists.i.AttachmentPartData;
import org.subethamail.core.lists.i.EnabledFilterData;
import org.subethamail.core.lists.i.FilterData;
import org.subethamail.core.lists.i.InlinePartData;
import org.subethamail.core.lists.i.ListData;
import org.subethamail.core.lists.i.ListDataPlus;
import org.subethamail.core.lists.i.MailData;
import org.subethamail.core.lists.i.MailHold;
import org.subethamail.core.lists.i.MailSummary;
import org.subethamail.core.lists.i.RoleData;
import org.subethamail.core.lists.i.SubscriberData;
import org.subethamail.core.lists.i.TextPartData;
import org.subethamail.core.plugin.i.Blueprint;
import org.subethamail.core.plugin.i.Filter;
import org.subethamail.entity.EmailAddress;
import org.subethamail.entity.EnabledFilter;
import org.subethamail.entity.Mail;
import org.subethamail.entity.Mail.HoldType;
import org.subethamail.entity.MailingList;
import org.subethamail.entity.Person;
import org.subethamail.entity.Role;
import org.subethamail.entity.Subscription;
import org.subethamail.entity.SubscriptionHold;
import org.subethamail.entity.i.Permission;
/**
* Offers static utility methods to convert between internal entity
* objects and public interface value objects.
*
* @author Jeff Schnitzer
* @author Jon Stevens
*/
@Log
public class Transmute
{
/** */
public static List<BlueprintData> blueprints(Iterable<Blueprint> rawColl)
{
List<BlueprintData> result = CollectionUtils.newArrayListSized(rawColl);
for (Blueprint raw: rawColl)
result.add(blueprint(raw));
return result;
}
/** */
public static BlueprintData blueprint(Blueprint raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new BlueprintData(
raw.getClass().getName(),
raw.getName(),
raw.getDescription());
}
/** */
public static List<ListData> mailingLists(Collection<MailingList> rawColl)
{
List<ListData> result = new ArrayList<ListData>(rawColl.size());
for (MailingList raw: rawColl)
result.add(mailingList(raw));
return result;
}
/** */
public static ListData mailingList(MailingList raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new ListData(
raw.getId(),
raw.getEmail(),
raw.getName(),
raw.getUrl(),
raw.getUrlBase(),
raw.getDescription(),
raw.getWelcomeMessage(),
raw.getOwnerEmail(),
raw.isSubscriptionHeld());
}
/** */
public static ListDataPlus mailingListPlus(MailingList raw, int subscriberCount, int messageCount)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new ListDataPlus(
raw.getId(),
raw.getEmail(),
raw.getName(),
raw.getUrl(),
raw.getUrlBase(),
raw.getDescription(),
raw.getWelcomeMessage(),
raw.getOwnerEmail(),
raw.isSubscriptionHeld(),
subscriberCount,
messageCount);
}
/** Does not add held subscriptions */
public static List<SubscriberData> subscribers(Collection<Subscription> subscriptions, boolean showNote)
{
List<SubscriberData> result = new ArrayList<SubscriberData>(subscriptions.size());
for (Subscription subscription: subscriptions)
result.add(subscriber(subscription, showNote));
return result;
}
/** */
public static SubscriberData subscriber(Subscription raw, boolean showNote)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new SubscriberData(
raw.getPerson().getId(),
raw.getPerson().getName(),
raw.getPerson().getEmailList(),
Transmute.role(raw.getRole()),
(raw.getDeliverTo() != null) ? raw.getDeliverTo().getId() : null,
raw.getDateCreated(),
showNote ? raw.getNote() : null);
}
/**
* @param rawPerson can be null
* @return the status of the person for the given list.
*/
public static MyListRelationship myListRelationship(Person rawPerson, MailingList rawList)
{
Set<Permission> perms = rawList.getPermissionsFor(rawPerson);
perms.size(); // initialize if it's a proxy
Subscription rawSub = (rawPerson == null) ? null : rawPerson.getSubscription(rawList.getId());
EmailAddress deliverTo = (rawSub == null) ? null : rawSub.getDeliverTo();
return new MyListRelationship(
rawList.getId(),
rawList.getName(),
rawList.getEmail(),
perms,
deliverTo == null ? null : deliverTo.getId(),
rawSub == null ? null : role(rawSub.getRole()));
}
/**
* Just hides the exception handling
*/
public static InternetAddress internetAddress(String email, String name)
{
try
{
return new InternetAddress(email, name);
}
catch (UnsupportedEncodingException ex)
{
throw new IllegalArgumentException("Unable to handle " + email + "/" + name, ex);
}
}
/**
* @return a sorted list of subscriptions
*/
public static List<SubscribedList> subscriptions(Collection<Subscription> rawColl)
{
List<SubscribedList> result = new ArrayList<SubscribedList>(rawColl.size());
for (Subscription raw: rawColl)
result.add(subscription(raw));
Collections.sort(result);
return result;
}
/**
*/
public static SubscribedList subscription(Subscription raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new SubscribedList(
raw.getList().getId(),
raw.getList().getEmail(),
raw.getList().getName(),
raw.getList().getUrl(),
raw.getList().getUrlBase(),
raw.getList().getDescription(),
raw.getList().getOwnerEmail(),
raw.getList().isSubscriptionHeld(),
raw.getRole().getName(),
(raw.getDeliverTo() != null) ? raw.getDeliverTo().getId() : null);
}
/**
* @param showEmail determines whether or not the summary will contain the
* email address of the author.
*/
public static List<MailSummary> mailSummaries(Collection<Mail> rawColl, boolean showEmail, MailSummary replacement)
{
List<MailSummary> result = new ArrayList<MailSummary>(rawColl.size());
for (Mail raw: rawColl)
result.add(mailSummary(raw, showEmail, replacement));
return result;
}
/**
* @param replacement is a summary we stop and use instead of continuing recursion.
* If null, no replacement will occur.
*/
public static MailSummary mailSummary(Mail raw, boolean showEmail, MailSummary replacement)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
if (replacement != null && replacement.getId().equals(raw.getId()))
return replacement;
InternetAddress addy = raw.getFromAddress();
return new MailSummary(
raw.getId(),
raw.getList().getId(),
raw.getSubject(),
showEmail ? addy.getAddress() : null,
addy.getPersonal(),
raw.getSentDate(),
mailSummaries(raw.getReplies(), showEmail, replacement));
}
public static MailData mailData(Mail raw, boolean showEmail)
{
try
{
InternetAddress addy = raw.getFromAddress();
byte[] rawContent = raw.getContent();
SubEthaMessage msg = rawContent!=null?new SubEthaMessage(null, rawContent):new SubEthaMessage(null);
List<InlinePartData> inlineParts = new ArrayList<InlinePartData>();
List<AttachmentPartData> attachmentParts = new ArrayList<AttachmentPartData>();
for (Part part: msg.getParts())
{
String contentType = part.getContentType();
if (contentType.startsWith(SubEthaMessage.DETACHMENT_MIME_TYPE))
{
//we need the orig Content-Type before the message was munged
contentType = part.getHeader(SubEthaMessage.HDR_ORIGINAL_CONTENT_TYPE)[0];
//put back the orig Content-Type
part.setHeader(SubEthaMessage.HDR_CONTENT_TYPE, contentType);
String name = part.getFileName();
// just in case we are working with something that isn't
// C-D: attachment; filename=""
if (name == null || name.length() == 0)
name = MailUtils.getNameFromContentType(contentType);
Long id = (Long) part.getContent();
//TODO: Set the correct size. This should be the size of the Attachment.content (Blob)
AttachmentPartData apd = new AttachmentPartData(id, contentType, name, 0);
attachmentParts.add(apd);
}
else
{
// not an attachment cause it isn't stored as a detached part.
Object content = part.getContent();
String name = part.getFileName();
// just in case we are working with something that isn't
// C-D: attachment; filename=""
if (name == null || name.length() == 0)
name = MailUtils.getNameFromContentType(contentType);
InlinePartData ipd;
if (content instanceof String)
{
ipd = new TextPartData((String)content, part.getContentType(), name, part.getSize());
}
else
{
ipd = new InlinePartData(content, part.getContentType(), name, part.getSize());
}
inlineParts.add(ipd);
}
}
return new MailData(
raw.getId(),
raw.getSubject(),
showEmail ? addy.getAddress() : null,
addy.getPersonal(),
raw.getSentDate(),
Transmute.mailSummaries(raw.getReplies(), showEmail, null),
raw.getList().getId(),
inlineParts,
attachmentParts);
}
catch (MessagingException ex)
{
// Should be impossible since everything was already run through
// JavaMail when the data was imported.
throw new RuntimeException(ex);
}
catch (IOException ex)
{
// Ditto
throw new RuntimeException(ex);
}
}
/**
*/
public static MailData[] mailThread(Mail raw, boolean showEmail)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
Mail root = raw;
while (root.getParent() != null) { root = root.getParent(); }
List<Mail> mails = raw.getDescendents();
MailData[] mailDatas = new MailData[mails.size()];
int x = 0;
for (Mail mail: mails)
{
mailDatas[x] = Transmute.mailData(mail, showEmail);
}
return mailDatas;
}
/**
*/
public static List<RoleData> roles(Collection<Role> rawColl)
{
List<RoleData> result = new ArrayList<RoleData>(rawColl.size());
for (Role raw: rawColl)
result.add(role(raw));
return result;
}
/**
*/
public static RoleData role(Role raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
// Might be a proxy, must initialize
raw.getPermissions().size();
return new RoleData(
raw.getId(),
raw.getName(),
raw.isOwner(),
raw.getPermissions(),
raw.getList().getId());
}
/**
*/
public static List<FilterData> filters(Collection<Filter> rawColl)
{
List<FilterData> result = new ArrayList<FilterData>(rawColl.size());
for (Filter raw: rawColl)
result.add(filter(raw));
return result;
}
/**
*/
public static FilterData filter(Filter raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new FilterData(
raw.getClass().getName(),
raw.getName(),
raw.getDescription(),
raw.getParameters());
}
/**
*/
public static EnabledFilterData enabledFilter(Filter filter, EnabledFilter enabled)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",enabled);
return new EnabledFilterData(
filter.getClass().getName(),
filter.getName(),
filter.getDescription(),
filter.getParameters(),
enabled.getList().getId(),
enabled.getArgumentMap());
}
/**
*/
public static List<SubscriberData> heldSubscriptions(Collection<SubscriptionHold> rawColl)
{
List<SubscriberData> result = new ArrayList<SubscriberData>(rawColl.size());
for (SubscriptionHold raw: rawColl)
result.add(heldSubscription(raw));
return result;
}
/**
*/
public static SubscriberData heldSubscription(SubscriptionHold raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new SubscriberData(
raw.getPerson().getId(),
raw.getPerson().getName(),
raw.getPerson().getEmailList(),
null,
(raw.getDeliverTo() != null) ? raw.getDeliverTo().getId() : null,
raw.getDateCreated(),
null);
}
/**
*/
public static Collection<MailHold> heldMail(Collection<Mail> rawColl)
{
List<MailHold> result = new ArrayList<MailHold>(rawColl.size());
for (Mail raw: rawColl)
result.add(heldMail(raw));
return result;
}
/**
*/
public static MailHold heldMail(Mail raw)
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0}",raw);
return new MailHold(
raw.getId(),
raw.getSubject(),
raw.getFrom(),
raw.getSentDate(),
raw.getHold() == HoldType.HARD);
}
/**
* This method converts Person objects into PersonData objects.
*/
public static List<PersonData> people(Collection<Person> persons)
{
List<PersonData> result = new ArrayList<PersonData>(persons.size());
for (Person person: persons)
{
result.add(person(person));
}
return result;
}
/**
* This method converts a Person object into a PersonData object.
*/
public static PersonData person(Person person)
{
return new PersonData(person.getId(),
person.getName(),
person.getEmailList(),
person.isSiteAdmin());
}
}