// Path: src/main/java/net/semanticmetadata/lire/solr/features/DoubleFeatureCosineDistance.java
// public class DoubleFeatureCosineDistance extends GenericGlobalDoubleFeature {
//     @Override
//     public double getDistance(LireFeature feature) {
//         return MetricsUtils.cosineDistance(getFeatureVector(), feature.getFeatureVector());
//     }
// 
//     @Override
//     public byte[] getByteArrayRepresentation() {
//         int numDimensions = 0;
//         LinkedList<Double> d = new LinkedList<>();
//         double[] data = getFeatureVector();
//         for (int i = 0, dataLength = data.length; i < dataLength; i++) {
//             double datum = data[i];
//             if (datum != 0) {
//                 d.add((double) i);
//                 d.add(datum);
//                 numDimensions++;
//             }
//         }
//         d.addFirst((double) data.length);
//         numDimensions = 0; // re-using a variable.
//         double[] s = new double[d.size()];
//         for (Iterator<Double> iterator = d.iterator(); iterator.hasNext(); ) {
//             s[numDimensions++] = iterator.next();
//         }
//         return SerializationUtils.toByteArray(s);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData) {
//         setByteArrayRepresentation(featureData, 0, featureData.length);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData, int offset, int length) {
//         double[] s = SerializationUtils.toDoubleArray(featureData, offset, length);
//         double[] data = new double[(int) s[0]];
//         for (int i = 1; i < s.length; i+=2) {
//             data[(int) s[i]] = s[i+1];
//         }
//         setData(data);
//     }
// }
// 
// Path: src/main/java/net/semanticmetadata/lire/solr/features/ShortFeatureCosineDistance.java
// public class ShortFeatureCosineDistance extends GenericGlobalShortFeature {
//     @Override
//     public double getDistance(LireFeature feature) {
//         return MetricsUtils.cosineDistance(getFeatureVector(), feature.getFeatureVector());
//     }
// 
//     @Override
//     public byte[] getByteArrayRepresentation() {
//         int numDimensions = 0;
//         LinkedList<Short> d = new LinkedList<>();
//         for (int i = 0, dataLength = data.length; i < dataLength; i++) {
//             short datum = data[i];
//             if (datum != 0) {
//                 d.add((short) i);
//                 d.add(datum);
//                 numDimensions++;
//             }
//         }
//         d.addFirst((short) data.length);
//         numDimensions = 0; // re-using a variable.
//         short[] s = new short[d.size()];
//         for (Iterator<Short> iterator = d.iterator(); iterator.hasNext(); ) {
//             s[numDimensions++] = iterator.next();
//         }
//         return SerializationUtils.toByteArray(s);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData) {
//         setByteArrayRepresentation(featureData, 0, featureData.length);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData, int offset, int length) {
//         short[] s = SerializationUtils.toShortArray(featureData, offset, length);
//         data = new short[s[0]];
//         for (int i = 1; i < s.length; i+=2) {
//             data[s[i]] = s[i+1];
//         }
//     }
// }


import net.semanticmetadata.lire.imageanalysis.features.GenericDoubleLireFeature;
import net.semanticmetadata.lire.imageanalysis.features.GlobalFeature;
import net.semanticmetadata.lire.imageanalysis.features.global.*;
import net.semanticmetadata.lire.imageanalysis.features.global.joint.JointHistogram;
import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPCEDD;
import net.semanticmetadata.lire.solr.features.DoubleFeatureCosineDistance;
import net.semanticmetadata.lire.solr.features.ShortFeatureCosineDistance;
import java.util.HashMap;
import java.util.Iterator;
     * @param featureFieldName the name of the field containing the histogram
     * @return the class for the given field or null if not registered.
     */
    public static Class getClassForFeatureField(String featureFieldName) {
        return featureFieldToClass.get(featureFieldName);
    }

    /**
     * Returns the feature's histogram field for a given hash field.
     * @param hashFieldName the name of the hash field
     * @return the name or null if the feature is not registered.
     */
    public static String getFeatureFieldName(String hashFieldName) {
        return hashFieldToFeatureField.get(hashFieldName);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Registered features:\n");
        sb.append("code\thash field\tfeature field\tclass\n");
        for (Iterator<String> iterator = codeToClass.keySet().iterator(); iterator.hasNext(); ) {
            String code = iterator.next();
            sb.append(code);
            sb.append('\t');
            sb.append(code + hashFieldPostfix);
            sb.append('\t');
            sb.append(code+featureFieldPostfix);
            sb.append('\t');
            sb.append(codeToClass.get(code).getName());
// Path: src/main/java/net/semanticmetadata/lire/solr/features/DoubleFeatureCosineDistance.java
// public class DoubleFeatureCosineDistance extends GenericGlobalDoubleFeature {
//     @Override
//     public double getDistance(LireFeature feature) {
//         return MetricsUtils.cosineDistance(getFeatureVector(), feature.getFeatureVector());
//     }
// 
//     @Override
//     public byte[] getByteArrayRepresentation() {
//         int numDimensions = 0;
//         LinkedList<Double> d = new LinkedList<>();
//         double[] data = getFeatureVector();
//         for (int i = 0, dataLength = data.length; i < dataLength; i++) {
//             double datum = data[i];
//             if (datum != 0) {
//                 d.add((double) i);
//                 d.add(datum);
//                 numDimensions++;
//             }
//         }
//         d.addFirst((double) data.length);
//         numDimensions = 0; // re-using a variable.
//         double[] s = new double[d.size()];
//         for (Iterator<Double> iterator = d.iterator(); iterator.hasNext(); ) {
//             s[numDimensions++] = iterator.next();
//         }
//         return SerializationUtils.toByteArray(s);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData) {
//         setByteArrayRepresentation(featureData, 0, featureData.length);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData, int offset, int length) {
//         double[] s = SerializationUtils.toDoubleArray(featureData, offset, length);
//         double[] data = new double[(int) s[0]];
//         for (int i = 1; i < s.length; i+=2) {
//             data[(int) s[i]] = s[i+1];
//         }
//         setData(data);
//     }
// }
// 
// Path: src/main/java/net/semanticmetadata/lire/solr/features/ShortFeatureCosineDistance.java
// public class ShortFeatureCosineDistance extends GenericGlobalShortFeature {
//     @Override
//     public double getDistance(LireFeature feature) {
//         return MetricsUtils.cosineDistance(getFeatureVector(), feature.getFeatureVector());
//     }
// 
//     @Override
//     public byte[] getByteArrayRepresentation() {
//         int numDimensions = 0;
//         LinkedList<Short> d = new LinkedList<>();
//         for (int i = 0, dataLength = data.length; i < dataLength; i++) {
//             short datum = data[i];
//             if (datum != 0) {
//                 d.add((short) i);
//                 d.add(datum);
//                 numDimensions++;
//             }
//         }
//         d.addFirst((short) data.length);
//         numDimensions = 0; // re-using a variable.
//         short[] s = new short[d.size()];
//         for (Iterator<Short> iterator = d.iterator(); iterator.hasNext(); ) {
//             s[numDimensions++] = iterator.next();
//         }
//         return SerializationUtils.toByteArray(s);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData) {
//         setByteArrayRepresentation(featureData, 0, featureData.length);
//     }
// 
//     @Override
//     public void setByteArrayRepresentation(byte[] featureData, int offset, int length) {
//         short[] s = SerializationUtils.toShortArray(featureData, offset, length);
//         data = new short[s[0]];
//         for (int i = 1; i < s.length; i+=2) {
//             data[s[i]] = s[i+1];
//         }
//     }
// }


// Path: src/main/java/net/semanticmetadata/lire/solr/FeatureRegistry.java
import net.semanticmetadata.lire.imageanalysis.features.GenericDoubleLireFeature;
import net.semanticmetadata.lire.imageanalysis.features.GlobalFeature;
import net.semanticmetadata.lire.imageanalysis.features.global.*;
import net.semanticmetadata.lire.imageanalysis.features.global.joint.JointHistogram;
import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPCEDD;
import net.semanticmetadata.lire.solr.features.DoubleFeatureCosineDistance;
import net.semanticmetadata.lire.solr.features.ShortFeatureCosineDistance;
import java.util.HashMap;
import java.util.Iterator;

     * @param featureFieldName the name of the field containing the histogram
     * @return the class for the given field or null if not registered.
     */
    public static Class getClassForFeatureField(String featureFieldName) {
        return featureFieldToClass.get(featureFieldName);
    }

    /**
     * Returns the feature's histogram field for a given hash field.
     * @param hashFieldName the name of the hash field
     * @return the name or null if the feature is not registered.
     */
    public static String getFeatureFieldName(String hashFieldName) {
        return hashFieldToFeatureField.get(hashFieldName);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Registered features:\n");
        sb.append("code\thash field\tfeature field\tclass\n");
        for (Iterator<String> iterator = codeToClass.keySet().iterator(); iterator.hasNext(); ) {
            String code = iterator.next();
            sb.append(code);
            sb.append('\t');
            sb.append(code + hashFieldPostfix);
            sb.append('\t');
            sb.append(code+featureFieldPostfix);
            sb.append('\t');
            sb.append(codeToClass.get(code).getName());
            sb.append('\n');