/* * Copyright (C) 2013 Jens Pelzetter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.arsdigita.cms; import com.arsdigita.xml.XML; import java.math.BigDecimal; import org.apache.log4j.Logger; import org.xml.sax.Attributes; import org.xml.sax.helpers.DefaultHandler; /** * This is a helper tool for loading data for the RelationAttributes (Database * Driven Enums) into the database in a loader of a module. This helper class * uses a XML format for loading the enum data, which looks like this: * *
 * <ddenums>
 *     <ddenum name="...">
 *         <entry key="..." lang="..." id="...">
 *            <value>...</value>
 *            <description>...</description>
 *         <entry>
 *     </ddenum>
 * </ddenums>
 * 
* * The root element is {@code } which can appear only once per file. * The {@code } elements as child * elements. The {@code element has one attribute, {@code name} which * contains the name of the enumeration. Each {@code } may have multiple * {@code} child elements. The {@code } element has three attributes. * *
*
{@code key}
The key of the entry. This attribute is mandatory.
*
{@code lang}
The language of the entry. This attribute is * mandatory. The combination of {@code key} * and {@code lang} should be unique.
*
{@code id}
This attribute is optional and contains the * database id of the entry if necessary. The * value is maybe ignored by this import tool.
*
* * Each entry has at least a {@code } element as child. The {@code } * element contains the value of the enum entry. Optionally there can also be * an description element containing a description of the entry. * * @author Jens Pelzetter * @version $Id$ */ public class RelationAttributeImportTool { /** Internal logger instance to faciliate debugging. Enable logging output * by editing /WEB-INF/conf/log4j.properties int hte runtime environment * and set com.arsdigita.cms.RelationAttributeImportTool=DEBUG * by uncommenting or adding the line. */ private final static Logger LOGGER = Logger.getLogger(RelationAttributeImportTool.class); public void loadData(final String fileName) { XML.parseResource(fileName, new RelationAttributeXmlHandler()); } //Suppressing this warnings because they are false positives here. @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.AvoidStringBufferField"}) private class RelationAttributeXmlHandler extends DefaultHandler { private String currentEnum; private String currentKey; private String currentLang; private String currentId; private String currentValue; private String currentDesc; private StringBuffer charBuffer; public RelationAttributeXmlHandler() { super(); //Nothing } @Override public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) { if ("ddenum".equals(qName)) { currentEnum = attributes.getValue("name"); } else if ("entry".equals(qName)) { currentKey = attributes.getValue("key"); currentLang = attributes.getValue("lang"); currentId = attributes.getValue("id"); } else if ("value".equals(qName)) { //Create new StringBuffer of creating a string from the content of the element charBuffer = new StringBuffer(); } else if ("description".equals(qName)) { //Create new StringBuffer of creating a string from the content of the element charBuffer = new StringBuffer(); } } @Override public void endElement(final String uri, final String localName, final String qName) { if ("ddenum".equals(qName)) { currentEnum = ""; } else if ("entry".equals(qName)) { createEntry(); currentKey = ""; currentLang = ""; currentId = ""; currentValue = ""; currentDesc = ""; } else if ("value".equals(qName)) { //Copy the value of the StringBuffer charBuffer to currentValue currentValue = charBuffer.toString().trim(); charBuffer = new StringBuffer(); } else if ("description".equals(qName)) { //Copy the value of the StringBuffer charBuffer to currentValue currentDesc = charBuffer.toString().trim(); charBuffer = new StringBuffer(); } } @Override public void characters(final char[] chars, final int start, final int length) { if (charBuffer != null) { for(int i = start; i < start + length; i++) { charBuffer.append(chars[i]); } } } //Supressing this warning since there is no better way yet. @SuppressWarnings("PMD.NPathComplexity") private void createEntry() { if ((currentEnum == null) || currentEnum.isEmpty()) { LOGGER.warn(String.format( "Value for current enum is empty. Ignorning entry with key '%s' and lang '%s'.", currentKey, currentLang)); return; } if ((currentKey == null) || currentKey.isEmpty()) { LOGGER.warn("No key. Ignorning entry"); return; } if ((currentLang == null) || currentLang.isEmpty()) { LOGGER.warn(String.format("No lang for entry with key '%s'. Ignoring entry", currentKey)); return; } LOGGER.warn("Creating RelationAttribute entry with this values:"); LOGGER.warn(String.format("\tcurrentEnum = '%s'", currentEnum)); LOGGER.warn(String.format("\tcurrentKey = '%s'", currentKey)); LOGGER.warn(String.format("\tcurrentLang = '%s'", currentLang)); LOGGER.warn(String.format("\tcurrentValue = '%s'", currentValue)); final RelationAttribute entry = new RelationAttribute(); if ((currentId != null) && !currentId.isEmpty()) { entry.setID(new BigDecimal(currentId)); } entry.setAttribute(currentEnum); entry.setKey(currentKey); entry.setLanguage(currentLang); entry.setName(currentValue); if ((currentDesc != null) && !currentValue.isEmpty()) { entry.setDescription(currentDesc); } entry.save(); } } }