/** * Licensed to JumpMind Inc under one or more contributor * license agreements. See the NOTICE file distributed * with this work for additional information regarding * copyright ownership. JumpMind Inc licenses this file * to you under the GNU General Public License, version 3.0 (GPLv3) * (the "License"); you may not use this file except in compliance * with the License. * * You should have received a copy of the GNU General Public License, * version 3.0 (GPLv3) along with this library; if not, see * <http://www.gnu.org/licenses/>. * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jumpmind.symmetric.integrate; import java.text.ParseException; import java.util.Map; import org.jumpmind.db.model.Table; import org.jumpmind.symmetric.io.data.CsvData; import org.jumpmind.symmetric.io.data.DataContext; import org.jumpmind.symmetric.io.data.DataEventType; import org.jumpmind.symmetric.io.data.writer.IDatabaseWriterFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A convenience class that allows the end user to template a message using * SymmetricDS filter data. </p> You may use %COLUMN% formatted tokens in your * template data which will be replaced by data coming in through the filter. * The following tokens are also supported: * <ol> * <li>%DMLTYPE% - evaluates to INSERT, UPDATE or DELETE</li> * <li>%TIMESTAMP% - evaluates to ms value returned by * System.currentTimeInMillis()</li> * </ol> * </p> If you have special formatting needs, implement the {@link IFormat} * interface and map your formatter to the column you want to 'massage.' */ public class TemplatedPublisherDataLoaderFilter extends AbstractTextPublisherDataLoaderFilter { static final Logger logger = LoggerFactory.getLogger(TemplatedPublisherDataLoaderFilter.class); private String headerTableTemplate; private String footerTableTemplate; private String contentTableTemplate; private Map<String, IFormat> columnNameToDataFormatter; private boolean processDelete = true; private boolean processInsert = true; private boolean processUpdate = true; private IDatabaseWriterFilter dataFilter; @Override protected String addTextElement( DataContext context, Table table, CsvData data) { if (this.dataFilter == null || this.dataFilter.beforeWrite(context, table, data)) { DataEventType eventType = data.getDataEventType(); String template = null; if ((processInsert && eventType == DataEventType.INSERT) || (processUpdate && eventType == DataEventType.UPDATE) || (processDelete && eventType == DataEventType.DELETE)) { template = contentTableTemplate; if (template != null) { template = fillOutTemplate(table, data, template, context); } } return template; } else { return null; } } @Override protected String addTextFooter(DataContext context) { return footerTableTemplate; } @Override protected String addTextHeader(DataContext context) { return headerTableTemplate; } protected String fillOutTemplate(Table table, CsvData data, String template, DataContext context) { DataEventType eventType = data.getDataEventType(); String[] colNames = null; String[] colValues = null; if (eventType == DataEventType.DELETE) { colNames = table.getPrimaryKeyColumnNames(); colValues = data.getParsedData(CsvData.PK_DATA); } else { colNames = table.getColumnNames(); colValues = data.getParsedData(CsvData.ROW_DATA); } for (int i = 0; i < colValues.length; i++) { String col = colNames[i]; template = replace(template, col, format(col, colValues[i])); } template = template.replace("DMLTYPE", eventType.name()); template = template.replace("TIMESTAMP", Long.toString(System.currentTimeMillis())); return template; } protected String format(String col, String data) { if (columnNameToDataFormatter != null) { IFormat formatter = columnNameToDataFormatter.get(col); if (formatter != null) { try { data = formatter.format(data); } catch (ParseException e) { throw new RuntimeException(e); } } } return data; } protected String replace(String template, String token, String value) { if (value == null) { value = ""; } if (template != null) { template = template.replace("%" + token + "%", value); } return template; } public void setColumnNameToDataFormatter(Map<String, IFormat> columnNameToDataFormatter) { this.columnNameToDataFormatter = columnNameToDataFormatter; } public void setProcessDelete(boolean processDeletes) { this.processDelete = processDeletes; } public void setProcessInsert(boolean processInserts) { this.processInsert = processInserts; } public void setProcessUpdate(boolean processUpdates) { this.processUpdate = processUpdates; } public void setHeaderTableTemplate(String headerTableTemplate) { this.headerTableTemplate = headerTableTemplate; } public void setFooterTableTemplate(String footerTableTemplate) { this.footerTableTemplate = footerTableTemplate; } public void setContentTableTemplate(String contentTableTemplate) { this.contentTableTemplate = contentTableTemplate; } public interface IFormat { public String format(String data) throws ParseException; } public void setDataFilter(IDatabaseWriterFilter dataFilter) { this.dataFilter = dataFilter; } }