/**
* Copyright (c) 2010, 2013 Darmstadt University of Technology.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marcel Bruch - initial API and implementation.
*/
package org.eclipse.recommenders.overrides;
import static org.eclipse.recommenders.utils.Constants.DOT_JSON;
import static org.eclipse.recommenders.utils.Zips.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.recommenders.models.IInputStreamTransformer;
import org.eclipse.recommenders.models.IUniqueName;
import org.eclipse.recommenders.models.UniqueTypeName;
import org.eclipse.recommenders.utils.IOUtils;
import org.eclipse.recommenders.utils.Openable;
import org.eclipse.recommenders.utils.Zips;
import org.eclipse.recommenders.utils.names.ITypeName;
import com.google.common.base.Optional;
/**
* A model provider that uses a single zip file to resolve and load call models from.
* <p>
* Note that this provider does not implement any pooling behavior, i.e., calls to {@link #acquireModel(UniqueTypeName)}
* may return the <b>same</b> {@link ICallModel} independent of whether {@link #releaseModel(ICallModel)} was called or
* not. Thus, these <b>models should not be shared between and used by several recommenders at the same time</b>.
*/
public class SingleZipOverrideModelProvider implements IOverrideModelProvider, Openable {
private final File models;
private ZipFile zip;
private Map<String, IInputStreamTransformer> transformers;
public SingleZipOverrideModelProvider(File models, Map<String, IInputStreamTransformer> transformers) {
this.models = models;
this.transformers = transformers;
}
@Override
public void open() throws IOException {
readFully(models);
zip = new ZipFile(models);
}
@Override
public void close() throws IOException {
closeQuietly(zip);
}
public Set<ITypeName> acquireableTypes() {
Set<ITypeName> acquireableTypesSet = Zips.types(zip.entries(), DOT_JSON);
for (Entry<String, IInputStreamTransformer> transformer : transformers.entrySet()) {
acquireableTypesSet.addAll(Zips.types(zip.entries(), DOT_JSON + "." + transformer.getKey())); //$NON-NLS-1$
}
return acquireableTypesSet;
}
@Override
public void releaseModel(IOverrideModel value) {
}
@Override
public Optional<IOverrideModel> acquireModel(IUniqueName<ITypeName> key) {
InputStream stream = null;
try {
String path = Zips.path(key.getName(), DOT_JSON);
stream = getInputStream(zip, path).orNull();
if (stream == null) {
return Optional.absent();
} else {
return Optional.of(JayesOverrideModel.load(stream, key.getName()));
}
} catch (IOException e) {
return Optional.absent();
} finally {
IOUtils.closeQuietly(stream);
}
}
private Optional<InputStream> getInputStream(ZipFile zip, String path) throws IOException {
for (Entry<String, IInputStreamTransformer> transformer : transformers.entrySet()) {
ZipEntry toTransform = zip.getEntry(path + "." + transformer.getKey()); //$NON-NLS-1$
if (toTransform == null) {
continue;
}
return Optional.of(transformer.getValue().transform(zip.getInputStream(toTransform)));
}
ZipEntry entry = zip.getEntry(path);
if (entry == null) {
return Optional.absent();
}
return Optional.of(zip.getInputStream(entry));
}
}