package org.openlca.jsonld.output;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import org.openlca.core.database.FileStore;
import org.openlca.core.database.IDatabase;
import org.openlca.core.model.Actor;
import org.openlca.core.model.Callback;
import org.openlca.core.model.Callback.Message;
import org.openlca.core.model.Category;
import org.openlca.core.model.Currency;
import org.openlca.core.model.DQSystem;
import org.openlca.core.model.Flow;
import org.openlca.core.model.FlowProperty;
import org.openlca.core.model.ImpactCategory;
import org.openlca.core.model.ImpactMethod;
import org.openlca.core.model.Location;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.NwSet;
import org.openlca.core.model.Parameter;
import org.openlca.core.model.Process;
import org.openlca.core.model.ProductSystem;
import org.openlca.core.model.Project;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.SocialIndicator;
import org.openlca.core.model.Source;
import org.openlca.core.model.UnitGroup;
import org.openlca.jsonld.EntityStore;
import com.google.gson.JsonObject;
/**
* Writes entities to an entity store (e.g. a document or zip file). It also
* writes the referenced entities to this store if they are not yet contained.
*/
public class JsonExport {
private ExportConfig conf;
public JsonExport(IDatabase database, EntityStore store) {
conf = ExportConfig.create(database, store);
}
public <T extends RootEntity> void write(T entity) {
write(entity, null);
}
public <T extends RootEntity> void write(T entity, Callback cb) {
if (entity == null)
return;
ModelType type = ModelType.forModelClass(entity.getClass());
if (type == null || entity.getRefId() == null) {
warn(cb, "no refId, or type is unknown", entity);
return;
}
if (conf.hasVisited(type, entity.getId()))
return;
Writer<T> writer = getWriter(entity, conf);
if (writer == null) {
warn(cb, "no writer found for type " + type, entity);
return;
}
try {
conf.refFn = ref -> {
write(ref, cb);
};
JsonObject obj = writer.write(entity);
conf.store.put(type, obj);
if (writer.isExportExternalFiles())
writeExternalFiles(entity, type, cb);
if (cb != null)
cb.apply(Message.info("data set exported"), entity);
} catch (Exception e) {
e.printStackTrace();
if (cb != null)
cb.apply(Message.error("failed to export data set", e), entity);
}
}
private void warn(Callback cb, String message, RootEntity entity) {
if (cb == null)
return;
cb.apply(Message.warn(message), entity);
}
private void writeExternalFiles(RootEntity entity, ModelType type,
Callback cb) {
if (entity == null || conf.db == null
|| conf.db.getFileStorageLocation() == null
|| conf.store == null)
return;
FileStore fs = new FileStore(conf.db.getFileStorageLocation());
File dir = fs.getFolder(entity);
if (dir == null || !dir.exists())
return;
try {
Path dbDir = dir.toPath();
Copy copy = new Copy(entity.getRefId(), type, dbDir);
Files.walkFileTree(dir.toPath(), copy);
} catch (Exception e) {
cb.apply(Message.error("failed to copy external files", e), entity);
}
}
public static <T extends RootEntity> JsonObject toJson(T entity,
IDatabase database) {
if (entity == null)
return new JsonObject();
Writer<T> writer = getWriter(entity, ExportConfig.create(database));
return writer.write(entity);
}
public static <T extends RootEntity> JsonObject toJson(T entity) {
if (entity == null)
return new JsonObject();
Writer<T> writer = getWriter(entity, ExportConfig.create());
return writer.write(entity);
}
@SuppressWarnings("unchecked")
private static <T extends RootEntity> Writer<T> getWriter(T entity,
ExportConfig conf) {
if (entity == null)
return null;
if (entity instanceof Actor)
return Writer.class.cast(new ActorWriter(conf));
if (entity instanceof Category)
return Writer.class.cast(new CategoryWriter(conf));
if (entity instanceof Currency)
return Writer.class.cast(new CurrencyWriter(conf));
if (entity instanceof FlowProperty)
return Writer.class.cast(new FlowPropertyWriter(conf));
if (entity instanceof Flow)
return Writer.class.cast(new FlowWriter(conf));
if (entity instanceof NwSet)
return Writer.class.cast(new NwSetWriter(conf));
if (entity instanceof ImpactCategory)
return Writer.class.cast(new ImpactCategoryWriter(conf));
if (entity instanceof ImpactMethod)
return Writer.class.cast(new ImpactMethodWriter(conf));
if (entity instanceof Location)
return Writer.class.cast(new LocationWriter(conf));
if (entity instanceof Parameter)
return Writer.class.cast(new ParameterWriter(conf));
if (entity instanceof Process)
return Writer.class.cast(new ProcessWriter(conf));
if (entity instanceof Source)
return Writer.class.cast(new SourceWriter(conf));
if (entity instanceof UnitGroup)
return Writer.class.cast(new UnitGroupWriter(conf));
if (entity instanceof SocialIndicator)
return Writer.class.cast(new SocialIndicatorWriter(conf));
if (entity instanceof ProductSystem)
return Writer.class.cast(new ProductSystemWriter(conf));
if (entity instanceof Project)
return Writer.class.cast(new ProjectWriter(conf));
if (entity instanceof DQSystem)
return Writer.class.cast(new DQSystemWriter(conf));
return null;
}
public void setExportDefaultProviders(boolean value) {
conf.exportProviders = value;
}
public void setExportReferences(boolean value) {
conf.exportReferences = value;
}
private class Copy extends SimpleFileVisitor<Path> {
private String refId;
private ModelType type;
private Path dbDir;
Copy(String refId, ModelType type, Path dbDir) {
this.refId = refId;
this.dbDir = dbDir;
this.type = type;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
String path = dbDir.relativize(file).toString().replace('\\', '/');
byte[] data = Files.readAllBytes(file);
conf.store.putBin(type, refId, path, data);
return FileVisitResult.CONTINUE;
}
}
}