package de.lmu.ifi.dbs.elki.datasource.filter; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.List; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; /** * Abstract base class for simple conversion filters such as normalizations and projections. * * @author Erich Schubert * * @param Input object type * @param Input object type */ public abstract class AbstractConversionFilter implements ObjectFilter { /** * A standard implementation of the filter process. First of all, all suitable * representations are found. Then (if {@link #prepareStart} returns true), * the data is processed read-only in a first pass. * * In the main pass, each object is then filtered using * {@link #filterSingleObject}. * * @param objects Objects to filter * @return Filtered bundle */ @Override public MultipleObjectsBundle filter(MultipleObjectsBundle objects) { if(objects.dataLength() == 0) { return objects; } MultipleObjectsBundle bundle = new MultipleObjectsBundle(); for(int r = 0; r < objects.metaLength(); r++) { @SuppressWarnings("unchecked") SimpleTypeInformation type = (SimpleTypeInformation) objects.meta(r); @SuppressWarnings("unchecked") final List column = (List) objects.getColumn(r); if(!getInputTypeRestriction().isAssignableFromType(type)) { bundle.appendColumn(type, column); continue; } // Get the replacement type information @SuppressWarnings("unchecked") final SimpleTypeInformation castType = (SimpleTypeInformation) type; // When necessary, perform an initialization scan if(prepareStart(castType)) { for(Object o : column) { @SuppressWarnings("unchecked") final I obj = (I) o; prepareProcessInstance(obj); } prepareComplete(); } @SuppressWarnings("unchecked") final List castColumn = (List) column; bundle.appendColumn(convertedType(castType), castColumn); // Normalization scan for(int i = 0; i < objects.dataLength(); i++) { @SuppressWarnings("unchecked") final I obj = (I) column.get(i); final O normalizedObj = filterSingleObject(obj); castColumn.set(i, normalizedObj); } } return bundle; } /** * Normalize a single instance. * * You can implement this as UnsupportedOperationException if you override * both public "normalize" functions! * * @param obj Database object to normalize * @return Normalized database object */ protected abstract O filterSingleObject(I obj); /** * Get the input type restriction used for negotiating the data query. * * @return Type restriction */ protected abstract SimpleTypeInformation getInputTypeRestriction(); /** * Get the output type from the input type after conversion. * * @param in input type restriction * @return output type restriction */ protected abstract SimpleTypeInformation convertedType(SimpleTypeInformation in); /** * Return "true" when the normalization needs initialization (two-pass filtering!). * * @param in Input type information * @return true or false */ protected boolean prepareStart(SimpleTypeInformation in) { return false; } /** * Process a single object during initialization. * * @param obj Object to process */ protected void prepareProcessInstance(I obj) { throw new AbortException("ProcessInstance not implemented, but prepareStart true?"); } /** * Complete the initialization phase. */ protected void prepareComplete() { // optional - default NOOP. } }