diff --git a/.gitignore b/.gitignore index 4988713..89688bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .idea -store +/store # Compiled class file *.class diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaData.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaData.java new file mode 100644 index 0000000..54c46d2 --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaData.java @@ -0,0 +1,125 @@ +package io.drift.core.store; + +import io.drift.core.store.storage.StorageId; +import io.drift.core.store.storage.StoragePath; + +import java.time.LocalDateTime; +import java.util.Map; + +public class MetaData { + + private StorageId storageId; + + private LocalDateTime timeStamp; + + private String type; + + private String description; + + private StoragePath path; + + private Map additionalMetaData; + + public MetaData(StorageId storageId, LocalDateTime timeStamp, String type, String description, StoragePath path, Map additionalMetaData) { + this.storageId = storageId; + this.timeStamp = timeStamp; + this.type = type; + this.description = description; + this.path = path; + this.additionalMetaData = additionalMetaData; + } + + public StorageId getStorageId() { + return storageId; + } + + public void setStorageId(StorageId storageId) { + this.storageId = storageId; + } + + public LocalDateTime getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(LocalDateTime timeStamp) { + this.timeStamp = timeStamp; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public StoragePath getPath() { + return path; + } + + public void setPath(StoragePath path) { + this.path = path; + } + + public Map getAdditionalMetaData() { + return additionalMetaData; + } + + public void setAdditionalMetaData(Map additionalMetaData) { + this.additionalMetaData = additionalMetaData; + } + + static public class Builder { + private StorageId storageId; + private LocalDateTime timeStamp; + private String type; + private String description; + private StoragePath path; + private Map additionalMetaData; + + public Builder withStorageId(StorageId storageId) { + this.storageId = storageId; + return this; + } + + public Builder withTimeStamp(LocalDateTime timeStamp) { + this.timeStamp = timeStamp; + return this; + } + + public Builder withType(String type) { + this.type = type; + return this; + } + + public Builder withDescription(String description) { + this.description = description; + return this; + } + + public Builder withPath(StoragePath path) { + this.path = path; + return this; + } + + public Builder withAdditionalMetaData(Map additionalMetaData) { + this.additionalMetaData = additionalMetaData; + return this; + } + + public MetaData build() { + return new MetaData(storageId, timeStamp, type, description, path, additionalMetaData); + } + } + + static public Builder builder() { return new Builder(); } + +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaDataStore.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaDataStore.java new file mode 100644 index 0000000..231c5a7 --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/MetaDataStore.java @@ -0,0 +1,34 @@ +package io.drift.core.store; + +public class MetaDataStore { +/* + private final MetaDataStorage metaDataStorage; + private final + + public MetaDataStore(MetaDataStorage metaDataStorage) { + this.metaDataStorage = metaDataStorage; + } + + public MetaModelManager getMetaDataManager() { + return metaModelCreation; + } + + public MetaModel getMetaModel(StoragePath storageId) throws ModelStoreException { + Class metaModelClass = MetaModel.class; + Serializer metamodelSerializer = serialization.forClass(metaModelClass); + String metaContent = storage.forPath(storageId).readMetaContent(storageId); + return (MetaModel) metamodelSerializer.loadModel(metaContent, metaModelClass); + } + + public void store() { + MetaModelCreator metaModelCreator = metaModelCreation.forModelClass(modelClass); + if (metaModelCreator != null) { + MetaModel metaModel = metaModelCreator.createFrom(model); + Serializer metaDataSerializer = serialization.forClass(metaModel.getClass()); + String metaContent = metaDataSerializer.from(metaModel); + storage.forPath(storageId).writeMetaContent(storageId, metaContent); + } + } +*/ + +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/AbstractJacksonModelSerializer.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/AbstractJacksonModelSerializer.java new file mode 100644 index 0000000..2f7d98d --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/AbstractJacksonModelSerializer.java @@ -0,0 +1,44 @@ +package io.drift.core.store.serialization; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.drift.core.store.storage.Storable; + +import java.io.IOException; + +abstract public class AbstractJacksonModelSerializer extends Serializer{ + + protected ObjectMapper objectMapper; + + public AbstractJacksonModelSerializer(String format) { + super(format); + initMapper(); + } + + protected abstract void initMapper(); + + @Override + public String from(Storable storable) throws StorableSerializationException { + try { + return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(storable); + } catch (JsonProcessingException e) { + throw new StorableSerializationException(e); + } + } + + @Override + public Storable loadModel(String content, Class storableClass) + throws StorableSerializationException { + try { + return objectMapper.readValue(content, storableClass); + } catch (IOException e) { + throw new StorableSerializationException(e); + } + } + + public void registerModule(Module module) { + objectMapper.registerModule(module); + } + +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/YamlModelSerializer.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/YamlModelSerializer.java new file mode 100644 index 0000000..3cb930c --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/serialization/YamlModelSerializer.java @@ -0,0 +1,28 @@ +package io.drift.core.store.serialization; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; + +public class YamlModelSerializer extends AbstractJacksonModelSerializer{ + + public static String YAML_FORMAT = "yaml"; + + public YamlModelSerializer() { + super(YAML_FORMAT); + } + + protected void initMapper() { + + YAMLFactory yamlFactory = new YAMLFactory(); + yamlFactory.configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, true); + + objectMapper = new ObjectMapper(yamlFactory); + objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage.java new file mode 100644 index 0000000..39b2489 --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage.java @@ -0,0 +1,143 @@ +package io.drift.core.store.storage; + +import io.drift.core.store.MetaData; +import io.drift.core.store.ModelStoreException; +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.*; +import org.apache.lucene.index.*; +import org.apache.lucene.search.*; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Timestamp; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static io.drift.core.store.storage.StoragePath.fromExternal; + +public class LuceneMetaDataStorage implements MetaDataStorage{ + + public static final Path DEFAULT_LUCENE_INDEX_PATH = Paths.get("store", "index"); + + public static final String PATH_FIELD_NAME = "path"; + public static final String TIME_STAMP_FIELD_NAME = "timeStamp"; + public static final String DESCRIPTION_FIELD_NAME = "description"; + public static final String ID_FIELD_NAME = "id"; + + private IndexWriter writer; + private Directory index; + private Path indexPath; + + public LuceneMetaDataStorage(Path indexPath) { + this.indexPath = indexPath; + setup(); + } + + public LuceneMetaDataStorage() { + this(DEFAULT_LUCENE_INDEX_PATH); + } + + public void setup() { + try { + index = FSDirectory.open(indexPath); + StandardAnalyzer analyzer = new StandardAnalyzer(); + IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); + writer = new IndexWriter(index, indexWriterConfig); + writer.commit(); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public void writeMetaData(MetaData metaData) throws ModelStoreException { + try { + Document document = new Document(); + + String id = metaData.getStorageId().getId(); + + document.add(new StringField(ID_FIELD_NAME, id , Field.Store.YES)); + if (metaData.getDescription() != null) + document.add(new TextField(DESCRIPTION_FIELD_NAME, metaData.getDescription(), Field.Store.YES)); + if (metaData.getTimeStamp() != null) + document.add(new TextField(TIME_STAMP_FIELD_NAME, DateTools.dateToString(Timestamp.valueOf(metaData.getTimeStamp()), DateTools.Resolution.SECOND), Field.Store.YES)); + document.add(new TextField(PATH_FIELD_NAME, metaData.getPath().toExternal(), Field.Store.YES)); + + writer.updateDocument(withId(id), document); + writer.commit(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + private Term withId(String id) { + return new Term(ID_FIELD_NAME, id); + } + + @Override + public MetaData readMetaData(StorageId storageId) throws ModelStoreException { + try (IndexReader indexReader = DirectoryReader.open(index)){ + + IndexSearcher searcher = new IndexSearcher(indexReader); + Query query = new TermQuery(withId(storageId.getId())); + + TopDocs topDocs = searcher.search(query, 1); + Document document = toLuceneDocument(topDocs.scoreDocs[0], searcher); + + return toMetaData(document); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + public MetaData toMetaData(Document document) { + return MetaData.builder() + .withStorageId(new StorageId(document.get(ID_FIELD_NAME))) + .withDescription(document.get(DESCRIPTION_FIELD_NAME)) + .withPath(fromExternal(document.get(PATH_FIELD_NAME))) + .build(); + } + + @Override + public List forParentPath(StoragePath parentPath) throws ModelStoreException { + try { + IndexReader indexReader = DirectoryReader.open(index); + IndexSearcher searcher = new IndexSearcher(indexReader); + + Term term = new Term(PATH_FIELD_NAME, parentPath.toExternal()); + Query query = new TermQuery(term); + TopDocs topDocs = searcher.search(query, 1024); + + return Stream.of(topDocs.scoreDocs) + .map(scoreDoc -> toLuceneDocument(scoreDoc, searcher)) + .map(this::toMetaData) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + public Document toLuceneDocument(ScoreDoc scoreDoc, IndexSearcher searcher) { + try { + return searcher.doc(scoreDoc.doc); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public void shutDown() { + try { + writer.close(); + index.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage2.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage2.java new file mode 100644 index 0000000..34cc85c --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/LuceneMetaDataStorage2.java @@ -0,0 +1,4 @@ +package io.drift.core.store.storage; + +public class LuceneMetaDataStorage2 { +} diff --git a/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/MetaDataStorage.java b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/MetaDataStorage.java new file mode 100644 index 0000000..992ee80 --- /dev/null +++ b/drift-core/drift-core-domain/src/main/java/io/drift/core/store/storage/MetaDataStorage.java @@ -0,0 +1,17 @@ +package io.drift.core.store.storage; + +import io.drift.core.store.MetaData; +import io.drift.core.store.ModelStoreException; + +import java.util.List; + +public interface MetaDataStorage { + + void writeMetaData(MetaData metaData) throws ModelStoreException; + + MetaData readMetaData(StorageId storageId) throws ModelStoreException; + + List forParentPath(StoragePath parentPath) throws ModelStoreException; + + void shutDown(); +}