001/** 
002 * Copyright (c) 2011, Regents of the University of Colorado 
003 * All rights reserved.
004 * 
005 * Redistribution and use in source and binary forms, with or without
006 * modification, are permitted provided that the following conditions are met:
007 * 
008 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
009 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
010 * Neither the name of the University of Colorado at Boulder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
011 * 
012 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
013 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
014 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
015 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
016 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
017 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
018 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
019 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
020 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
021 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
022 * POSSIBILITY OF SUCH DAMAGE. 
023 */
024package org.cleartk.ml.jar;
025
026import java.io.File;
027import java.io.FileInputStream;
028import java.io.ObjectInputStream;
029
030import org.apache.uima.UimaContext;
031import org.apache.uima.resource.ResourceInitializationException;
032import org.cleartk.ml.DataWriterFactory;
033import org.cleartk.ml.SequenceDataWriterFactory;
034import org.cleartk.ml.encoder.features.FeaturesEncoder;
035import org.cleartk.ml.encoder.features.FeaturesEncoder_ImplBase;
036import org.cleartk.ml.encoder.outcome.OutcomeEncoder;
037import org.cleartk.util.CleartkInitializationException;
038import org.cleartk.util.ReflectionUtil;
039import org.apache.uima.fit.component.initialize.ConfigurationParameterInitializer;
040import org.apache.uima.fit.descriptor.ConfigurationParameter;
041import org.apache.uima.fit.factory.initializable.Initializable;
042
043/**
044 * Superclass for {@link DataWriterFactory} and {@link SequenceDataWriterFactory} implementations
045 * that use {@link FeaturesEncoder}s and {@link OutcomeEncoder}s.
046 * 
047 * Note that it does not declare that it implements either of the DataWriterFactory interfaces.
048 * Subclasses should do this.
049 * 
050 * <br>
051 * Copyright (c) 2011, Regents of the University of Colorado <br>
052 * All rights reserved.
053 * 
054 * @author Steven Bethard
055 * @author Philip Ogren
056 */
057public abstract class EncodingDirectoryDataWriterFactory<ENCODED_FEATURES_TYPE, OUTCOME_TYPE, ENCODED_OUTCOME_TYPE>
058    extends DirectoryDataWriterFactory implements Initializable {
059
060  public static final String PARAM_LOAD_ENCODERS_FROM_FILE_SYSTEM = "loadEncodersFromFileSystem";
061
062  @ConfigurationParameter(
063      name = PARAM_LOAD_ENCODERS_FROM_FILE_SYSTEM,
064      mandatory = false,
065      description = "when true indicates that the FeaturesEncoder and "
066          + "OutcomeEncoder should be loaded from the file system "
067          + "instead of being created by the DataWriterFactory",
068      defaultValue = "false")
069  private boolean loadEncodersFromFileSystem = false;
070
071  public void initialize(UimaContext context) throws ResourceInitializationException {
072    super.initialize(context);
073    ConfigurationParameterInitializer.initialize(this, context);
074    if (loadEncodersFromFileSystem) {
075      try {
076        File encoderFile = new File(outputDirectory, FeaturesEncoder_ImplBase.ENCODERS_FILE_NAME);
077
078        if (!encoderFile.exists()) {
079          throw CleartkInitializationException.fileNotFound(encoderFile);
080        }
081
082        ObjectInputStream is = new ObjectInputStream(new FileInputStream(encoderFile));
083
084        // read the FeaturesEncoder and check the types
085        FeaturesEncoder<?> untypedFeaturesEncoder = FeaturesEncoder.class.cast(is.readObject());
086        ReflectionUtil.checkTypeParameterIsAssignable(
087            FeaturesEncoder.class,
088            "ENCODED_FEATURES_TYPE",
089            untypedFeaturesEncoder,
090            EncodingDirectoryDataWriterFactory.class,
091            "ENCODED_FEATURES_TYPE",
092            this);
093
094        // read the OutcomeEncoder and check the types
095        OutcomeEncoder<?, ?> untypedOutcomeEncoder = OutcomeEncoder.class.cast(is.readObject());
096        ReflectionUtil.checkTypeParameterIsAssignable(
097            OutcomeEncoder.class,
098            "OUTCOME_TYPE",
099            untypedOutcomeEncoder,
100            EncodingDirectoryDataWriterFactory.class,
101            "OUTCOME_TYPE",
102            this);
103        ReflectionUtil.checkTypeParameterIsAssignable(
104            OutcomeEncoder.class,
105            "ENCODED_OUTCOME_TYPE",
106            untypedOutcomeEncoder,
107            EncodingDirectoryDataWriterFactory.class,
108            "ENCODED_OUTCOME_TYPE",
109            this);
110
111        // assign the encoders to the instance variables
112        this.featuresEncoder = ReflectionUtil.uncheckedCast(untypedFeaturesEncoder);
113        this.outcomeEncoder = ReflectionUtil.uncheckedCast(untypedOutcomeEncoder);
114        is.close();
115      } catch (Exception e) {
116        throw new ResourceInitializationException(e);
117      }
118    }
119  }
120
121  protected boolean setEncodersFromFileSystem(
122      EncodingDirectoryDataWriter<?, ?, ENCODED_FEATURES_TYPE, OUTCOME_TYPE, ENCODED_OUTCOME_TYPE> dataWriter) {
123    if (this.featuresEncoder != null && this.outcomeEncoder != null) {
124      dataWriter.setFeaturesEncoder(this.featuresEncoder);
125      dataWriter.setOutcomeEncoder(this.outcomeEncoder);
126      return true;
127    }
128    return false;
129  }
130
131  protected FeaturesEncoder<ENCODED_FEATURES_TYPE> featuresEncoder = null;
132
133  protected OutcomeEncoder<OUTCOME_TYPE, ENCODED_OUTCOME_TYPE> outcomeEncoder = null;
134
135}