Package com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.parse

Source Code of com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.parse.NewsletterConfigDOM

/*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
* This file is part of Entando software.
* Entando is a free software;
* You can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2.
*
* See the file License for the specific language governing permissions  
* and limitations under the License
*
*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
*/
package com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.parse;

import java.io.StringReader;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import com.agiletec.aps.system.ApsSystemUtils;
import com.agiletec.aps.system.exception.ApsSystemException;
import com.agiletec.aps.util.DateConverter;
import com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.model.NewsletterConfig;
import com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.model.NewsletterContentType;

/*
<newsletterConfig>
 
  <scheduler active="true" onlyOwner="false" delayHours="24" start="01/03/2007 11:08" />
 
  <subscriptions allAttributeName="newsletter_allContents">
    <descr>
      mappa delle corrispondeze tra attributo buleano
      'sottoscrizione categoria newsletter' di profilo utente
      e categoria di contenuto/tematismo-newsletter
    </descr>
    <subscription categoryCode="food" attributeName="newsletter_food" />
    <subscription categoryCode="travel" attributeName="newsletter_travel" />
    ......
  </subscriptions>
 
  <contentTypes>
    <contentType code="NWL" defaultModel="1" htmlModel="2" />
    <contentType code="FOO" defaultModel="21" htmlModel="22" />
    .......
  </contentTypes>
 
  <mail senderCode="CODE1" mailAttrName="email" alsoHtml="true" unsubscriptionPage="newsletter_unsubscribe" >
    <subject><![CDATA[Oggetto della mail]]></subject>
    <htmlHeader><![CDATA[
<br />Header html della mail<br />
    ]]></htmlHeader>
    <htmlFooter><![CDATA[
<br />Footer html della mail<br />
    ]]></htmlFooter>
    <htmlSeparator><![CDATA[
Separatore html tra contenuti
    ]]></htmlSeparator>
    <textHeader><![CDATA[
Header text della mail
    ]]></textHeader>
    <textFooter><![CDATA[
Footer text della mail
    ]]></textFooter>
    <textSeparator><![CDATA[
Separatore text tra contenuti
    ]]></textSeparator>
   
    <subscriberHtmlFooter><![CDATA[Clicca sul link per cancellare la sottoscrizione <a href="{unsubscribeLink}" >CONFERMA</a></body></html>]]></htmlFooter>
    <subscriberTextFooter><![CDATA[Clicca sul link per cancellare la sottoscrizione <a href="{unsubscribeLink}" >CONFERMA</a>]]></textFooter>
   
    <subscription pageCode="newsletter_terminatereg" tokenValidityDays="90" >
      <subject><![CDATA[Conferma la sottoscrizione al servizio di Newsletter]]></subject>
      <htmlBody><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it">
<head></head>
<body><p>Clicca sul link per confermare <a href="{subscribeLink}" >***CONFERMA***</a></p> </body></html>]]></htmlBody>
      <textBody><![CDATA[Clicca sul link per confermare <a href="{subscribeLink}" >***CONFERMA***</a>]]></textBody>
    </subscription>
  </mail>
</newsletterConfig>
*/

/**
* Classe DOM delegata alle operazioni di lettura/scrittura della configurazione del servizio di newsletter.
*
* @author E.Santoboni, E.Mezzano
*/
public class NewsletterConfigDOM {
 
  /**
   * Extract the newsletter configuration from an xml.
   * @param xml The xml containing the configuration.
   * @return The newsletter configuration.
   * @throws ApsSystemException In case of parsing errors.
   */
  public NewsletterConfig extractConfig(String xml) throws ApsSystemException {
    NewsletterConfig config = new NewsletterConfig();
    Element root = this.getRootElement(xml);
    this.extractScheduler(root, config);
    this.extractSubscriptions(root, config);
    this.extractContentTypes(root, config);
    this.extractMailConfig(root, config);
    return config;
  }
 
  /**
   * Create an xml containing the newsletter configuration.
   * @param config The newsletter configuration.
   * @return The xml containing the configuration.
   * @throws ApsSystemException In case of errors.
   */
  public String createConfigXml(NewsletterConfig config) throws ApsSystemException {
    Element root = this.createConfigElement(config);
    Document doc = new Document(root);
    XMLOutputter out = new XMLOutputter();
    Format format = Format.getPrettyFormat();
    format.setIndent("\t");
    out.setFormat(format);
    String xml = out.outputString(doc);
    return xml;
  }
 
  private void extractScheduler(Element root, NewsletterConfig config) {
    Element schedulerElement = root.getChild(SCHEDULER_ELEM);
    String active = schedulerElement.getAttributeValue(SCHEDULER_ACTIVE_ATTR);
    config.setActive(active != null && active.equalsIgnoreCase("true"));
    String onlyOwner = schedulerElement.getAttributeValue(SCHEDULER_ONLYOWNER_ATTR);
    config.setOnlyOwner(onlyOwner != null && onlyOwner.equalsIgnoreCase("true"));
    String delayHours = schedulerElement.getAttributeValue(SCHEDULER_DELAYHOURS_ATTR);
    int hours = 1;
    if (delayHours != null && delayHours.length()>0) {
      hours = Integer.parseInt(delayHours);
    }
    config.setHoursDelay(hours);
    String start = schedulerElement.getAttributeValue(SCHEDULER_START_ATTR);
    if (start!=null && start.length()>0) {
      config.setStartScheduler(DateConverter.parseDate(start, SCHEDULER_STARTDATE_CONFIG_PATTERN));
    } else {
      config.setStartScheduler(new Date());
    }
  }
 
  /**
   * Estrae la parte di configurazione relativa alle sottoscrizioni, mappante le relazioni tra categorie e relativo attributo del profilo.
   * @param root L'elemento radice contenente il sottoelemento relativo alle sottoscrizioni.
   * @param config La configurazione del servizio newsletter.
   */
  private void extractSubscriptions(Element root, NewsletterConfig config) {
    Element subscriptionsElem = root.getChild(SUBSCRIPTIONS_ELEM);
    String allContentsAttribute = subscriptionsElem.getAttributeValue(SUBSCRIPTIONS_ALL_ATTR);
    allContentsAttribute = (allContentsAttribute != null && allContentsAttribute.trim().length() > 0) ? allContentsAttribute.trim() : null;
    config.setAllContentsAttributeName(allContentsAttribute);
    List<Element> subscriptionElems = subscriptionsElem.getChildren(SUBSCRIPTION_CHILD);
    if (null != subscriptionElems) {
      for (int i=0; i<subscriptionElems.size(); i++) {
        Element subscriptionElem = (Element) subscriptionElems.get(i);
        String categoryCode = subscriptionElem.getAttributeValue(SUBSCRIPTION_CATEGORYCODE_ATTR);
        String attributeName = subscriptionElem.getAttributeValue(SUBSCRIPTION_ATTRIBUTENAME_ATTR);
        config.addSubscription(categoryCode, attributeName);
      }
    }
  }
 
  /**
   * Estrae la parte di configurazione relativa ai tipi di contenuto, contenente i modelli utilizzati per i tipi di contenuto notificabili.
   * @param root L'elemento radice contenente il sottoelemento relativo ai tipi di contenuto.
   * @param config La configurazione del servizio newsletter.
   */
  private void extractContentTypes(Element root, NewsletterConfig config) {
    Element contentTypesElem = root.getChild(CONTENTTYPES_ELEM);
    if (null != contentTypesElem) {
      List<Element> contentTypeElements = contentTypesElem.getChildren(CONTENTTYPE_CHILD);
      if (null != contentTypeElements) {
        for (int i=0; i<contentTypeElements.size(); i++) {
          Element contentTypeElem = contentTypeElements.get(i);
          config.addContentType(this.extractContentType(contentTypeElem));
        }
      }
    }
  }
 
  /**
   * Estrae la parte di configurazione relativa alla mail.
   * @param root L'elemento radice contenente il sottoelemento relativo alle mail.
   * @param config La configurazione del servizio newsletter.
   */
  private void extractMailConfig(Element root, NewsletterConfig config) {
    Element mailElem = root.getChild(MAIL_ELEM);
   
    String alsoHtml = mailElem.getAttributeValue(MAIL_ALSOHTML_ATTR);
    config.setAlsoHtml(alsoHtml != null && "true".equalsIgnoreCase(alsoHtml));
   
    String senderCode = mailElem.getAttributeValue(MAIL_SENDERCODE_ATTR);
    config.setSenderCode(senderCode);
   
    String mailAttrName = mailElem.getAttributeValue(MAIL_MAILATTRNAME_ATTR);
    config.setMailAttrName(mailAttrName);
   
    String unsubscriptionPage = mailElem.getAttributeValue(MAIL_UNSUBSCRIPTIONPAGE_ATTR);
    config.setUnsubscriptionPageCode(unsubscriptionPage);
   
    config.setSubject(mailElem.getChildText(MAIL_SUBJECT_CHILD));
   
    config.setHtmlHeader(mailElem.getChildText(MAIL_HTML_HEADER_CHILD));
    config.setHtmlFooter(mailElem.getChildText(MAIL_HTML_FOOTER_CHILD));
    config.setHtmlSeparator(mailElem.getChildText(MAIL_HTML_SEPARATOR_CHILD));
   
    config.setTextHeader(mailElem.getChildText(MAIL_TEXT_HEADER_CHILD));
    config.setTextFooter(mailElem.getChildText(MAIL_TEXT_FOOTER_CHILD));
    config.setTextSeparator(mailElem.getChildText(MAIL_TEXT_SEPARATOR_CHILD));
   
    config.setSubscribersHtmlFooter(mailElem.getChildText(MAIL_SUBSCRIBER_HTML_FOOTER_CHILD));
    config.setSubscribersTextFooter(mailElem.getChildText(MAIL_SUBSCRIBER_TEXT_FOOTER_CHILD));
   
    Element subscriptionElem = mailElem.getChild(MAIL_SUBSCRIPTION_CHILD);
    if (subscriptionElem!=null) {
      String pageCode = subscriptionElem.getAttributeValue(MAIL_SUBSCRIPTION_PAGECODE_ATTR);
      config.setSubscriptionPageCode(pageCode);
     
      String tokenValidity = subscriptionElem.getAttributeValue(MAIL_SUBSCRIPTION_TOKENVALIDITY_ATTR);
      config.setSubscriptionTokenValidityDays(Integer.parseInt(tokenValidity));
     
      config.setSubscriptionSubject(subscriptionElem.getChildText(MAIL_SUBSCRIPTION_SUBJECT_CHILD));
      config.setSubscriptionHtmlBody(subscriptionElem.getChildText(MAIL_SUBSCRIPTION_HTML_CHILD));
      config.setSubscriptionTextBody(subscriptionElem.getChildText(MAIL_SUBSCRIPTION_TEXT_CHILD));
    }
  }
 
  /**
   * Estrae la parte di configurazione relativa ad un singolo tipo di contenuto.
   * @param contentTypeElem L'elemento contenente la configurazione di un singolo tipo di contenuto.
   * @return La configurazione del tipo di contenuto.
   */
  protected NewsletterContentType extractContentType(Element contentTypeElem) {
    NewsletterContentType contentType = new NewsletterContentType();
   
    String contentTypeCode = contentTypeElem.getAttributeValue(CONTENTTYPE_CODE_ATTR);
    contentType.setContentTypeCode(contentTypeCode);
   
    String defaultModel = contentTypeElem.getAttributeValue(CONTENTTYPE_DEFMODEL_ATTR);
    contentType.setSimpleTextModel(Integer.parseInt(defaultModel));
   
    String htmlModel = contentTypeElem.getAttributeValue(CONTENTTYPE_HTMLMODEL_ATTR);
    if (htmlModel!=null && htmlModel.length()>0) {
      contentType.setHtmlModel(Integer.parseInt(htmlModel));
    }
    return contentType;
  }
 
  /**
   * Crea l'elemento della configurazione del servizio di newsletter.
   * @param config La configurazione del servizio newsletter.
   * @return L'elemento della configurazione del servizio di newsletter.
   */
  private Element createConfigElement(NewsletterConfig config) {
    Element configElem = new Element(ROOT);
   
    Element shcedulerElem = this.createSchedulerElement(config);
    configElem.addContent(shcedulerElem);
   
    Element subscriptionsElem = this.createSubscriptionsElement(config);
    configElem.addContent(subscriptionsElem);
   
    Element contentTypesElem = this.createContentTypesElement(config);
    configElem.addContent(contentTypesElem);
   
    Element mailElem = this.createMailElement(config);
    configElem.addContent(mailElem);
   
    return configElem;
  }
 
  /**
   * Crea l'elemento della configurazione relativa alle sottoscrizioni.
   * @param config La configurazione del servizio newsletter.
   * @return L'elemento di configurazione relativo alle sottoscrizioni.
   */
  private Element createSubscriptionsElement(NewsletterConfig config) {
    Element subscriptionsElem = new Element(SUBSCRIPTIONS_ELEM);
   
    String allContentsAttribute = config.getAllContentsAttributeName();
    allContentsAttribute = allContentsAttribute != null ? allContentsAttribute.trim() : "";
    subscriptionsElem.setAttribute(SUBSCRIPTIONS_ALL_ATTR, allContentsAttribute);
   
    Iterator subscriptionsIter = config.getSubscriptions().entrySet().iterator();
    while (subscriptionsIter.hasNext()) {
      Entry subscriptionEntry = (Entry) subscriptionsIter.next();
      Element subscriptionChild = new Element(SUBSCRIPTION_CHILD);
      String categoryCode = (String) subscriptionEntry.getKey();
      subscriptionChild.setAttribute(SUBSCRIPTION_CATEGORYCODE_ATTR, categoryCode);
      String attributeName = (String) subscriptionEntry.getValue();
      subscriptionChild.setAttribute(SUBSCRIPTION_ATTRIBUTENAME_ATTR, attributeName);
      subscriptionsElem.addContent(subscriptionChild);
    }
    return subscriptionsElem;
  }
 
  private Element createSchedulerElement(NewsletterConfig config) {
    Element schedulerElement = new Element(SCHEDULER_ELEM);
    schedulerElement.setAttribute(SCHEDULER_ACTIVE_ATTR, String.valueOf(config.isActive()));
    schedulerElement.setAttribute(SCHEDULER_ONLYOWNER_ATTR, String.valueOf(config.isOnlyOwner()));
    schedulerElement.setAttribute(SCHEDULER_DELAYHOURS_ATTR, String.valueOf(config.getHoursDelay()));
    schedulerElement.setAttribute(SCHEDULER_START_ATTR, DateConverter.getFormattedDate(config.getStartScheduler(), SCHEDULER_STARTDATE_CONFIG_PATTERN));
    return schedulerElement;
  }
 
  /**
   * Crea l'elemento della configurazione relativa ai tipi di contenuto.
   * @param config La configurazione del servizio newsletter.
   * @return L'elemento di configurazione relativo ai tipi di contenuto.
   */
  protected Element createContentTypesElement(NewsletterConfig config) {
    Element contentTypesElem = new Element(CONTENTTYPES_ELEM);
   
    Iterator<NewsletterContentType> contentTypesIter = config.getContentTypes().values().iterator();
    while (contentTypesIter.hasNext()) {
      NewsletterContentType contentType = contentTypesIter.next();
     
      Element contentTypeChild = new Element(CONTENTTYPE_CHILD);
      contentTypeChild.setAttribute(CONTENTTYPE_CODE_ATTR, contentType.getContentTypeCode());
      String textModel = String.valueOf(contentType.getSimpleTextModel());
      contentTypeChild.setAttribute(CONTENTTYPE_DEFMODEL_ATTR, textModel);
      String htmlModel = String.valueOf(contentType.getHtmlModel());
      contentTypeChild.setAttribute(CONTENTTYPE_HTMLMODEL_ATTR, htmlModel);
      contentTypesElem.addContent(contentTypeChild);
    }
    return contentTypesElem;
  }
 
  /**
   * Crea l'elemento della configurazione relativa alle mail.
   * @param config La configurazione del servizio newsletter.
   * @return L'elemento di configurazione relativo alle mail.
   */
  private Element createMailElement(NewsletterConfig config) {
    Element mailElem = new Element(MAIL_ELEM);
   
    mailElem.setAttribute(MAIL_ALSOHTML_ATTR, String.valueOf(config.isAlsoHtml()));
    mailElem.setAttribute(MAIL_SENDERCODE_ATTR, config.getSenderCode());
    mailElem.setAttribute(MAIL_MAILATTRNAME_ATTR, config.getMailAttrName());
    mailElem.setAttribute(MAIL_UNSUBSCRIPTIONPAGE_ATTR, config.getUnsubscriptionPageCode());
   
    Element subject = new Element(MAIL_SUBJECT_CHILD);
    subject.addContent(new CDATA(config.getSubject()));
    mailElem.addContent(subject);
   
    Element htmlHeader = new Element(MAIL_HTML_HEADER_CHILD);
    htmlHeader.addContent(new CDATA(config.getHtmlHeader()));
    mailElem.addContent(htmlHeader);
   
    Element htmlFooter = new Element(MAIL_HTML_FOOTER_CHILD);
    htmlFooter.addContent(new CDATA(config.getHtmlFooter()));
    mailElem.addContent(htmlFooter);
   
    Element htmlSeparator = new Element(MAIL_HTML_SEPARATOR_CHILD);
    htmlSeparator.addContent(new CDATA(config.getHtmlSeparator()));
    mailElem.addContent(htmlSeparator);
   
    Element textHeader = new Element(MAIL_TEXT_HEADER_CHILD);
    textHeader.addContent(new CDATA(config.getTextHeader()));
    mailElem.addContent(textHeader);
   
    Element textFooter = new Element(MAIL_TEXT_FOOTER_CHILD);
    textFooter.addContent(new CDATA(config.getTextFooter()));
    mailElem.addContent(textFooter);
   
    Element textSeparator = new Element(MAIL_TEXT_SEPARATOR_CHILD);
    textSeparator.addContent(new CDATA(config.getTextSeparator()));
    mailElem.addContent(textSeparator);
   
   
    Element subscribersHtmlFooter = new Element(MAIL_SUBSCRIBER_HTML_FOOTER_CHILD);
    subscribersHtmlFooter.addContent(new CDATA(config.getSubscribersHtmlFooter()));
    mailElem.addContent(subscribersHtmlFooter);
   
    Element subscribersTextFooter = new Element(MAIL_SUBSCRIBER_TEXT_FOOTER_CHILD);
    subscribersTextFooter.addContent(new CDATA(config.getSubscribersTextFooter()));
    mailElem.addContent(subscribersTextFooter);
   
    Element subscriptionElem = new Element(MAIL_SUBSCRIPTION_CHILD);
    subscriptionElem.setAttribute(MAIL_SUBSCRIPTION_PAGECODE_ATTR, config.getSubscriptionPageCode());
    subscriptionElem.setAttribute(MAIL_SUBSCRIPTION_TOKENVALIDITY_ATTR, String.valueOf(config.getSubscriptionTokenValidityDays()));
   
    Element subscriptionSubject = new Element(MAIL_SUBSCRIPTION_SUBJECT_CHILD);
    subscriptionSubject.addContent(new CDATA(config.getSubscriptionSubject()));
    subscriptionElem.addContent(subscriptionSubject);
   
    Element subscriptionTextBody = new Element(MAIL_SUBSCRIPTION_HTML_CHILD);
    subscriptionTextBody.addContent(new CDATA(config.getSubscriptionHtmlBody()));
    subscriptionElem.addContent(subscriptionTextBody);
   
    Element subscriptionHtmlBody = new Element(MAIL_SUBSCRIPTION_TEXT_CHILD);
    subscriptionHtmlBody.addContent(new CDATA(config.getSubscriptionTextBody()));
    subscriptionElem.addContent(subscriptionHtmlBody);
   
    mailElem.addContent(subscriptionElem);
    return mailElem;
  }
 
  /**
   * Returns the Xml element from a given text.
   * @param xmlText The text containing an Xml.
   * @return The Xml element from a given text.
   * @throws ApsSystemException In case of parsing exceptions.
   */
  private Element getRootElement(String xmlText) throws ApsSystemException {
    SAXBuilder builder = new SAXBuilder();
    builder.setValidation(false);
    StringReader reader = new StringReader(xmlText);
    Element root = null;
    try {
      Document doc = builder.build(reader);
      root = doc.getRootElement();
    } catch (Throwable t) {
      ApsSystemUtils.getLogger().error("Error parsing xml: " + t.getMessage());
      throw new ApsSystemException("Error parsing xml", t);
    }
    return root;
  }
 
  private static final String ROOT = "newsletterConfig";
 
  private static final String SCHEDULER_ELEM = "scheduler";
  private static final String SCHEDULER_ACTIVE_ATTR = "active";
  private static final String SCHEDULER_ONLYOWNER_ATTR = "onlyOwner";
  private static final String SCHEDULER_DELAYHOURS_ATTR = "delayHours";
  private static final String SCHEDULER_START_ATTR = "start";

  private static final String SUBSCRIPTIONS_ELEM = "subscriptions";
  private static final String SUBSCRIPTIONS_ALL_ATTR = "allAttributeName";
  private static final String SUBSCRIPTION_CHILD = "subscription";
  private static final String SUBSCRIPTION_CATEGORYCODE_ATTR = "categoryCode";
  private static final String SUBSCRIPTION_ATTRIBUTENAME_ATTR = "attributeName";
 
  protected static final String CONTENTTYPES_ELEM = "contentTypes";
  protected static final String CONTENTTYPE_CHILD = "contentType";
  protected static final String CONTENTTYPE_CODE_ATTR = "code";
  protected static final String CONTENTTYPE_DEFMODEL_ATTR = "defaultModel";
  protected static final String CONTENTTYPE_HTMLMODEL_ATTR = "htmlModel";
 
  private static final String MAIL_ELEM = "mail";
  private static final String MAIL_ALSOHTML_ATTR = "alsoHtml";
  private static final String MAIL_SENDERCODE_ATTR = "senderCode";
  private static final String MAIL_MAILATTRNAME_ATTR = "mailAttrName";
  private static final String MAIL_UNSUBSCRIPTIONPAGE_ATTR = "unsubscriptionPage";
  private static final String MAIL_SUBJECT_CHILD = "subject";
  private static final String MAIL_HTML_HEADER_CHILD = "htmlHeader";
  private static final String MAIL_HTML_FOOTER_CHILD = "htmlFooter";
  private static final String MAIL_HTML_SEPARATOR_CHILD = "htmlSeparator";
  private static final String MAIL_TEXT_HEADER_CHILD = "textHeader";
  private static final String MAIL_TEXT_FOOTER_CHILD = "textFooter";
  private static final String MAIL_TEXT_SEPARATOR_CHILD = "textSeparator";
  private static final String MAIL_SUBSCRIBER_HTML_FOOTER_CHILD = "subscriberHtmlFooter";
  private static final String MAIL_SUBSCRIBER_TEXT_FOOTER_CHILD = "subscriberTextFooter";
 
  private static final String MAIL_SUBSCRIPTION_CHILD = "subscription";
  private static final String MAIL_SUBSCRIPTION_PAGECODE_ATTR = "pageCode";
  private static final String MAIL_SUBSCRIPTION_TOKENVALIDITY_ATTR = "tokenValidityDays";
  private static final String MAIL_SUBSCRIPTION_SUBJECT_CHILD = "subject";
  private static final String MAIL_SUBSCRIPTION_HTML_CHILD = "htmlBody";
  private static final String MAIL_SUBSCRIPTION_TEXT_CHILD = "textBody";
 
  private static final String SCHEDULER_STARTDATE_CONFIG_PATTERN = "dd/MM/yyyy HH:mm";
 
}
TOP

Related Classes of com.agiletec.plugins.jpnewsletter.aps.system.services.newsletter.parse.NewsletterConfigDOM

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.