package edu.brown.markov.features; import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.voltdb.catalog.ProcParameter; import org.voltdb.catalog.Procedure; import weka.core.Instance; import edu.brown.markov.FeatureExtractor; import edu.brown.utils.ClassUtil; import edu.brown.utils.PartitionEstimator; public abstract class FeatureUtil { private static final Logger LOG = Logger.getLogger(FeatureUtil.class); protected final static String DELIMITER = "-"; protected final static String SUFFIX = "Feature"; protected final static int SUFFIX_LENGTH = SUFFIX.length(); protected final static Pattern PREFIX_SPLITTER = Pattern.compile(DELIMITER); protected final static String PREFIX_FORMAT = "%s" + DELIMITER + "%02d"; /** * For the given feature key, return a new instance of that AbstractFeature * @param key * @param catalog_proc * @param p_estimator * @return */ public static AbstractFeature getFeatureForKey(String key, Procedure catalog_proc, PartitionEstimator p_estimator) { assert(key != null); assert(catalog_proc != null); assert(p_estimator != null); String featureName = FeatureUtil.getFeatureKeyPrefix(key) + "Feature"; Class<?> featureClass = ClassUtil.getClass(featureName); AbstractFeature f = (AbstractFeature)ClassUtil.newInstance( featureClass, new Object[]{ p_estimator, catalog_proc }, new Class[] { PartitionEstimator.class, Procedure.class }); return (f); } /** * Return the prefix that will be used for all attributes generated by the given Feature class * @param feature_class * @return */ public static final String getFeatureKeyPrefix(Class<? extends AbstractFeature> feature_class) { String prefix = feature_class.getSimpleName(); return (prefix.substring(0, prefix.length() - SUFFIX_LENGTH)); } /** * Return the feature key that includes the given ProcParameter index number * @param catalog_param * @return */ public static String getFeatureKeyPrefix(Class<? extends AbstractFeature> feature_class, ProcParameter catalog_param) { return (String.format(FeatureUtil.PREFIX_FORMAT, FeatureUtil.getFeatureKeyPrefix(feature_class), catalog_param.getIndex())); } /** * Return the feature key that includes the given ProcParameter index number and the array offset * @param catalog_param * @param idx * @return */ public static String getFeatureKey(Class<? extends AbstractFeature> feature_class, ProcParameter catalog_param, int idx) { return (String.format(FeatureUtil.PREFIX_FORMAT, FeatureUtil.getFeatureKeyPrefix(feature_class, catalog_param), idx)); } /** * * @param feature_key * @return */ public static final String getFeatureKeyPrefix(String feature_key) { return (PREFIX_SPLITTER.split(feature_key, 1)[0]); } /** * Return the TransactionId for a given Instance * @param inst * @return */ public static long getTransactionId(Instance inst) { String val = inst.stringValue(FeatureExtractor.TXNID_ATTRIBUTE_IDX); assert(val.isEmpty() == false) : "Missing TransactionIdFeature for Instance\n" + inst; long txn_id = -1; try { txn_id = Long.valueOf(val); } catch (NumberFormatException ex) { LOG.fatal("Invalid Instance: " + inst); throw new RuntimeException("Invalid TransactionIdFeature for Instance", ex); } assert(txn_id != -1); return (txn_id); } }