/*
* Copyright (C) 2007 ETH Zurich
*
* This file is part of Fosstrak (www.fosstrak.org).
*
* Fosstrak is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* Fosstrak 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 Fosstrak; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package org.fosstrak.ale.server.util;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.epcglobalinc.tdt.LevelTypeList;
import org.fosstrak.ale.server.Tag;
import org.fosstrak.ale.xsd.ale.epcglobal.ECReportGroupListMember;
import org.fosstrak.ale.xsd.ale.epcglobal.ECReportOutputSpec;
import org.fosstrak.ale.xsd.epcglobal.EPC;
import org.fosstrak.tdt.TDTEngine;
import org.fosstrak.tdt.TDTException;
/**
* utility class for various tag transformations and processings.
*
* @author swieland
*
*/
public final class TagHelper {
/** logger. */
private static final Logger LOG = Logger.getLogger(TagHelper.class);
/** instance of the TDT engine used for tag conversion. */
private static TDTEngine engine;
public static final String EXTRA_PARAMS_COMPANYPREFIXLENGTH = "companyprefixlength";
public static final String EXTRA_PARAMS_FILTER = "filter";
public static final String EXTRA_PARAMS_TAGLENGTH = "taglength";
/**
* private utility class
*/
private TagHelper() {
}
/**
* extract the binary representation of the given tag - this method is NOT performing any transformations!
* @param tag the tag.
* @return the tags binary representation.
*/
public static String getBinaryRepresentation(Tag tag) {
if ((null != tag) && (tag.getTagAsBinary() != null)) {
return tag.getTagAsBinary();
}
LOG.error("missing binary representation of the tag: " + tag);
return null;
}
/**
* determine if a tag is to be included into the output in the format raw decimal.
* @param outputSpec the report output specification.
* @return true if include, false otherwise. upon exception, false is returned.
*/
public static boolean isReportOutputSpecIncludeRawDecimal(ECReportOutputSpec outputSpec) {
try {
return outputSpec.isIncludeRawDecimal();
} catch (Exception ex) {
LOG.debug("exception while determining if tag is to be included as raw decimal, thus not including the tag: ", ex);
}
return false;
}
/**
* add a tag in raw decimal format to the group member. the given tag must be submitted with the binary format.
* @param tdt the TDT to be used for the transformation from binary to raw decimal representation.
* @param groupMember the group member where to add the transformed tag.
* @param tag the tag to be transformed.
* @return the converted tag if the tag was added, null otherwise.
*/
public static String addTagAsRawDecimal(TDTEngine tdt, ECReportGroupListMember groupMember, Tag tag) {
try {
String bin = getBinaryRepresentation(tag);
if (null != bin) {
EPC epc = new EPC();
final String converted = TagFormatHelper.formatAsRawDecimal(bin.length(), tdt.bin2dec(bin));
epc.setValue(converted);
groupMember.setRawDecimal(epc);
return converted;
}
} catch (Exception ex) {
LOG.error("caught exception during tag transformation: ", ex);
}
return null;
}
/**
* determine if a tag is to be included into the output in the format tag encoding.
* @param outputSpec the report output specification.
* @return true if include, false otherwise. upon exception, false is returned.
*/
public static boolean isReportOutputSpecIncludeTagEncoding(ECReportOutputSpec outputSpec) {
try {
return outputSpec.isIncludeTag();
} catch (Exception ex) {
LOG.debug("exception while determining if tag is to be included as tag encoding, thus not including the tag: ", ex);
}
return false;
}
/**
* add a tag in tag encoding format to the group member. the given tag must be submitted with the binary format.
* @param tdt the TDT to be used for the transformation from binary to tag encoding representation.
* @param groupMember the group member where to add the transformed tag.
* @param tag the tag to be transformed.
* @return the converted tag if the tag was added, null otherwise.
*/
public static String addTagAsTagEncoding(TDTEngine tdt, ECReportGroupListMember groupMember, Tag tag) {
try {
String bin = getBinaryRepresentation(tag);
if (null != bin) {
EPC epc = new EPC();
final String converted = convert_to_TAG_ENCODING(tag.getTagLength(), tag.getFilter(), tag.getCompanyPrefixLength(), bin, tdt);
epc.setValue(converted);
groupMember.setTag(epc);
return converted;
}
} catch (Exception ex) {
LOG.error("caught exception during tag transformation: ", ex);
}
return null;
}
/**
* determine if a tag is to be included into the output in the format raw hex.
* @param outputSpec the report output specification.
* @return true if include, false otherwise. upon exception, false is returned.
*/
public static boolean isReportOutputSpecIncludeRawHex(ECReportOutputSpec outputSpec) {
try {
return outputSpec.isIncludeRawHex();
} catch (Exception ex) {
LOG.debug("exception while determining if tag is to be included as raw hex, thus not including the tag: ", ex);
}
return false;
}
/**
* add a tag in raw hex format to the group member. the given tag must be submitted with the binary format.
* @param tdt the TDT to be used for the transformation from binary to raw hex representation.
* @param groupMember the group member where to add the transformed tag.
* @param tag the tag to be transformed.
* @return the converted tag if the tag was added, null otherwise.
*/
public static String addTagAsRawHex(TDTEngine tdt, ECReportGroupListMember groupMember, Tag tag) {
try {
String bin = getBinaryRepresentation(tag);
if (null != bin) {
EPC epc = new EPC();
final String converted = TagFormatHelper.formatAsRawHex(bin.length(), tdt.bin2hex(bin));
epc.setValue(converted);
groupMember.setRawHex(epc);
return converted;
}
} catch (Exception ex) {
LOG.error("caught exception during tag transformation: ", ex);
}
return null;
}
/**
* determine if a tag is to be included into the output in the format EPC.
* @param outputSpec the report output specification.
* @return true if include, false otherwise. upon exception, false is returned.
*/
public static boolean isReportOutputSpecIncludeEPC(ECReportOutputSpec outputSpec) {
try {
return outputSpec.isIncludeEPC();
} catch (Exception ex) {
LOG.debug("exception while determining if tag is to be included as EPC, thus not including the tag: ", ex);
}
return false;
}
/**
* add a tag in EPC format to the group member. the given tag must be submitted with the binary format.
* @param tdt the TDT to be used for the transformation from binary to EPC representation.
* @param groupMember the group member where to add the transformed tag.
* @param tag the tag to be transformed.
* @return the converted tag if the tag was added, null otherwise.
*/
public static String addTagAsEPC(TDTEngine tdt, ECReportGroupListMember groupMember, Tag tag) {
try {
String bin = getBinaryRepresentation(tag);
if (null != bin) {
EPC epc = new EPC();
final String converted = convert_to_PURE_IDENTITY(tag.getTagLength(), tag.getFilter(), tag.getCompanyPrefixLength(), bin, tdt);
epc.setValue(converted);
groupMember.setEpc(epc);
return converted;
}
} catch (Exception ex) {
LOG.error("caught exception during tag transformation: ", ex);
}
LOG.debug("instead setting tag as pure URI");
// TODO: check with the EPC/ALE Specification if this is correct.
EPC epc = new EPC();
epc.setValue(tag.getTagIDAsPureURI());
groupMember.setEpc(epc);
return tag.getTagIDAsPureURI();
}
//---------------------------------- TAG CONVERSION -----------------------------------------------
/**
* allows to inject a new instance of the TDT engine into the TagHelper.
* @param tdt the new TDT to be used.
*/
public static void setTDTEngine(TDTEngine tdt) {
engine = tdt;
}
/**
* returns a handle onto the currently used TDT engine.
* @return the used TDT engine.
*/
public static synchronized TDTEngine getTDTEngine() {
if (engine == null) {
try {
LOG.debug("Initialize TDT Engine for tag translation.");
engine = new TDTEngine();
} catch (Exception e) {
LOG.error("could not create an instance of the TDT Engine - aborting: ", e);
throw new RuntimeException("could not create an instance of the TDT Engine - aborting: ", e);
}
}
return engine;
}
/**
* converts a given input with the given TDT to the desired output format.
* @param input the tag to convert. Must be in binary format or in TAG_ENCODING.
* @param extraparms conversion parameters.
* @param outputLevel the destination format.
* @return the converted tag.
* @throws TDTException whenever a tag conversion error occurs.
*/
public static String convert(String input, Map<String, String> extraparms, LevelTypeList outputLevel, TDTEngine tdt) throws TDTException {
try {
return tdt.convert(input, extraparms, outputLevel);
} catch (NullPointerException npe) {
LOG.error("caught NullPointerException during transformation - could not perform the transformation ", npe);
throw new TDTException("caught NullPointerException during transformation - could not perform the transformation " + npe.getMessage());
}
}
/**
* converts a given tag through TDT into LEGACY format - convenience method using the TagHelpers internal TDT for the transformation.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_LEGACY(String tagLength, String filter, String companyPrefixLength, String tag) {
return convert_to_LEGACY(tagLength, filter, companyPrefixLength, tag, getTDTEngine());
}
/**
* converts a given tag through tdt into LEGACY format.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_LEGACY(String tagLength, String filter, String companyPrefixLength, String tag, TDTEngine tdt) {
LevelTypeList outputLevel = LevelTypeList.LEGACY;
Map<String, String> extraparms = createExtraParams(tagLength, filter, companyPrefixLength);
return convert(tag, extraparms, outputLevel, tdt);
}
/**
* converts a given tag through TDT into PURE_IDENTITY format - used the TagHelpers internal TDT for the transformation.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_PURE_IDENTITY(String tagLength, String filter, String companyPrefixLength, String tag) {
return convert_to_PURE_IDENTITY(tagLength, filter, companyPrefixLength, tag, getTDTEngine());
}
/**
* converts a given tag through tdt into PURE_IDENTITY format.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @param tdt the TDT to use for the transformation.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_PURE_IDENTITY(String tagLength, String filter, String companyPrefixLength, String tag, TDTEngine tdt) {
LevelTypeList outputLevel = LevelTypeList.PURE_IDENTITY;
Map<String, String> extraparms = createExtraParams(tagLength, filter, companyPrefixLength);
return convert(tag, extraparms, outputLevel, tdt);
}
/**
* convenience method to convert the given tag to TAG_ENCODING format - the TagHelpers internal TDT is used.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_TAG_ENCODING(String tagLength, String filter, String companyPrefixLength, String tag) {
return convert_to_TAG_ENCODING(tagLength, filter, companyPrefixLength, tag, getTDTEngine());
}
/**
* convert the given tag to TAG_ENCODING format.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @param tag the tag to convert in binary format or in TAG_ENCODING.
* @param tdt the TDT to use for the transformation.
* @return a converted tag or null if exception during conversion.
*/
public static String convert_to_TAG_ENCODING(String tagLength, String filter, String companyPrefixLength, String tag, TDTEngine tdt) {
LevelTypeList outputLevel = LevelTypeList.TAG_ENCODING;
Map<String, String> extraparms = createExtraParams(tagLength, filter, companyPrefixLength);
return convert(tag, extraparms, outputLevel, tdt);
}
/**
* add the given parameters to the TDT extra parameters map.
* @param tagLength the inbound taglength must be specified as "64" or "96".
* @param filter the inbound filter value must be specified - range depends on coding scheme.
* @param companyPrefixLength length of the EAN.UCC Company Prefix must be specified for GS1 coding schemes. if set to null parameter is ignored.
* @return map wrapping the parameters.
*/
public static Map<String, String> createExtraParams(String tagLength, String filter, String companyPrefixLength) {
Map<String, String> extraparms = new HashMap<String, String> ();
if (null != tagLength) {
extraparms.put(EXTRA_PARAMS_TAGLENGTH, tagLength);
}
if (null != filter) {
extraparms.put(EXTRA_PARAMS_FILTER, filter);
}
if (null != companyPrefixLength) {
extraparms.put(EXTRA_PARAMS_COMPANYPREFIXLENGTH, companyPrefixLength);
}
return extraparms;
}
}