Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
prompto.store.solr.BaseSOLRStore Maven / Gradle / Ivy
package prompto.store.solr;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import prompto.error.InternalError;
import prompto.error.PromptoError;
import prompto.error.ReadWriteError;
import prompto.intrinsic.PromptoBinary;
import prompto.intrinsic.PromptoDate;
import prompto.intrinsic.PromptoDateTime;
import prompto.intrinsic.PromptoDbId;
import prompto.intrinsic.PromptoList;
import prompto.intrinsic.PromptoPeriod;
import prompto.intrinsic.PromptoTime;
import prompto.store.AttributeInfo;
import prompto.store.Family;
import prompto.store.IAuditMetadata;
import prompto.store.IQuery;
import prompto.store.IQueryBuilder.MatchOp;
import prompto.store.IStorable;
import prompto.store.IStorable.IDbIdFactory;
import prompto.store.IStore;
import prompto.store.IStored;
import prompto.store.IStoredIterable;
abstract class BaseSOLRStore implements IStore {
static Map typeMap = new HashMap<>();
static {
typeMap.put("uuid", Family.UUID);
typeMap.put("db-id", Family.UUID);
typeMap.put("db-ref", Family.ANY);
typeMap.put("blob", Family.BLOB);
typeMap.put("boolean", Family.BOOLEAN);
typeMap.put("text", Family.TEXT);
typeMap.put("text-key", typeMap.get("text"));
typeMap.put("text-value", typeMap.get("text"));
typeMap.put("text-words", typeMap.get("text"));
typeMap.put("version", Family.TEXT); // TODO create Version type?
typeMap.put("image", Family.IMAGE);
typeMap.put("integer", Family.INTEGER);
typeMap.put("decimal", Family.DECIMAL);
typeMap.put("date", Family.DATE);
typeMap.put("time", Family.TIME);
typeMap.put("period", Family.PERIOD);
typeMap.put("datetime", Family.DATETIME);
}
static interface IDataReader {
Object readValue(Object data) throws IOException;
}
static Map readerMap = new HashMap<>();
static {
readerMap.put("uuid", (o) -> UUID.fromString(o.toString()));
readerMap.put("db-id", readerMap.get("uuid"));
readerMap.put("db-ref", readerMap.get("uuid"));
readerMap.put("blob", (o) -> BinaryConverter.toPromptoBinary(o));
readerMap.put("boolean", (o) -> o);
readerMap.put("text", (o) -> String.valueOf(o));
readerMap.put("text-key", readerMap.get("text"));
readerMap.put("text-value", readerMap.get("text"));
readerMap.put("text-words", readerMap.get("text"));
readerMap.put("version", (o) -> o.toString());
readerMap.put("image", (o) -> BinaryConverter.toPromptoBinary(o));
readerMap.put("integer", (o) -> o);
readerMap.put("decimal", (o) -> o);
readerMap.put("period", (o) -> PromptoPeriod.parse(o.toString()));
readerMap.put("date", (o) -> PromptoDate.parse(o.toString()));
readerMap.put("time", (o) -> PromptoTime.parse(o.toString()));
readerMap.put("datetime", (o) -> PromptoDateTime.parse(o.toString()));
}
public Object readFieldData(String fieldName, Object data) throws PromptoError {
if(data==null)
return null;
String typeName = getColumnTypeName(fieldName);
if(typeName.endsWith("[]"))
return readArrayData(typeName, data);
else
return readAtomicData(typeName, data);
}
private Object readAtomicData(String typeName, Object data) {
IDataReader reader = readerMap.get(typeName);
if(reader==null)
throw new UnsupportedOperationException("read " + typeName);
try {
return reader.readValue(data);
} catch(Exception e) {
throw new ReadWriteError(e.getMessage());
}
}
@SuppressWarnings("unchecked")
private Object readArrayData(String typeName, Object data) {
if(!(data instanceof Collection))
throw new UnsupportedOperationException("data " + data.getClass().getName());
String itemTypeName = typeName.substring(0, typeName.indexOf('['));
IDataReader reader = readerMap.get(itemTypeName);
if(reader==null)
throw new UnsupportedOperationException("read " + typeName);
try {
PromptoList result = new PromptoList<>(false);
for(Object item : ((Collection)data))
result.add(reader.readValue(item));
return result;
} catch(Exception e) {
throw new ReadWriteError(e.getMessage());
}
}
ConcurrentMap columnTypeNames = new ConcurrentHashMap<>();
private String getColumnTypeName(String fieldName) throws PromptoError {
String typeName = columnTypeNames.get(fieldName);
if(typeName==null) try {
typeName = getFieldType(fieldName);
columnTypeNames.put(fieldName, typeName);
} catch(Exception e) {
throw new InternalError(e);
}
return typeName;
}
@Override
public AttributeInfo getAttributeInfo(String fieldName) throws PromptoError {
String typeName = getColumnTypeName(fieldName);
boolean multi = typeName.endsWith("[]");
if(multi)
typeName = typeName.substring(0, typeName.length()-"[]".length());
Family family = typeMap.get(typeName);
return new AttributeInfo(fieldName, family, multi, null);
}
@Override
public Class> getNativeDbIdClass() {
return UUID.class;
}
@Override
public Object newNativeDbId() {
return UUID.randomUUID();
}
@Override
public UUID convertToNativeDbId(Object dbId) {
if(dbId == null)
return null;
else if(dbId instanceof UUID)
return (UUID)dbId;
else if(dbId instanceof String)
return UUID.fromString((String)dbId);
else
return UUID.fromString(String.valueOf(dbId));
}
@Override
public void createOrUpdateAttributes(Collection attributes) throws PromptoError {
for(AttributeInfo attribute : attributes) try {
createOrUpdateAttribute(attribute);
} catch(Exception e) {
throw new InternalError(e);
}
}
private void createOrUpdateAttribute(AttributeInfo attribute) throws SolrServerException, IOException {
Map options = new HashMap<>();
options.put("indexed", true);
options.put("stored", true);
if(attribute.isCollection())
options.put("multiValued", true);
if("version".equals(attribute.getName())) {
if(!hasField("version"))
addField("version", "version", options);
} else if(attribute.getFamily()==Family.TEXT)
createOrUpdateTextColumn(attribute, options);
else if(!hasField(attribute.getName())) {
if(attribute.getFamily()==Family.CATEGORY) {
addField(attribute.getName(), "db-ref", options);
} else {
String typeName = attribute.getFamily().name().toLowerCase();
addField(attribute.getName(), typeName, options);
}
}
}
private void createOrUpdateTextColumn(AttributeInfo column, Map options) throws SolrServerException, IOException {
String fieldName = column.getName();
options = new HashMap<>(options); // use a copy
options.put("indexed", false);
options.put("stored", true);
if(!hasField(fieldName))
addField(fieldName, "text", options);
options = new HashMap<>(options); // use a copy
options.put("indexed", true);
options.put("stored", false);
SOLRAttributeInfo indexTypes = SOLRAttributeInfo.computeFieldFlags(column);
if(indexTypes!=null) {
if(indexTypes.isKey()) {
String indexFieldName = fieldName + "-" + AttributeInfo.KEY;
if(!hasField(indexFieldName))
addCopyField(indexFieldName, "text-" + AttributeInfo.KEY, options, fieldName);
}
if(indexTypes.isValue()) {
String indexFieldName = fieldName + "-" + AttributeInfo.VALUE;
if(!hasField(indexFieldName))
addCopyField(indexFieldName, "text-" + AttributeInfo.VALUE, options, fieldName);
}
if(indexTypes.isWords()) {
String indexFieldName = fieldName + "-" + AttributeInfo.WORDS;
if(!hasField(indexFieldName))
addCopyField(indexFieldName, "text-" + AttributeInfo.WORDS, options, fieldName);
}
} else
addCopyField(fieldName + "-key", "text-key", options, fieldName);
}
@Override
public void deleteAndStore(Collection deletables, Collection storables, IAuditMetadata audit) throws PromptoError {
List dbIdsToDrop = null;
if(deletables!=null && deletables.size()>0) {
dbIdsToDrop = new ArrayList<>();
for(Object dbId : deletables)
dbIdsToDrop.add(dbId.toString()); // a simple UUID
}
List docsToAdd = null;
if(storables!=null && storables.size()>0) {
docsToAdd = new ArrayList<>();
for(IStorable storable : storables) {
if(!(storable instanceof StorableDocument))
throw new IllegalStateException();
SolrInputDocument doc = ((StorableDocument)storable).getDocument();
docsToAdd.add(doc);
}
if(docsToAdd.isEmpty())
docsToAdd = null;
}
try {
if(dbIdsToDrop!=null)
dropDocuments(dbIdsToDrop);
if(docsToAdd!=null)
addDocuments(docsToAdd);
} catch(Exception e) {
throw new InternalError(e); // TODO much better
}
}
@Override
public PromptoBinary fetchBinary(PromptoDbId dbId, String attr) throws PromptoError {
SolrQuery query = new SolrQuery();
query.setQuery("dbId:" + dbId);
query.setFields(attr);
query.setRows(1);
try {
QueryResponse response = query(query);
if(response.getResults().isEmpty())
return null;
SolrDocument doc = response.getResults().get(0);
if(doc==null)
return null;
Object data = doc.getFieldValue(attr);
if(data==null)
return null;
else
return BinaryConverter.toPromptoBinary(data);
} catch(Exception e) {
throw new InternalError(e);
}
}
@Override
public IStored fetchUnique(PromptoDbId dbId) throws PromptoError {
SOLRQueryBuilder builder = new SOLRQueryBuilder();
builder.verify(new SOLRAttributeInfo(IStore.dbIdName, Family.UUID, false, null), MatchOp.EQUALS, dbId);
try {
SOLRQuery query = builder.build();
QueryResponse result = query(query.getQuery());
return getOne(result);
} catch(Exception e) {
throw new InternalError(e);
}
}
@Override
public SOLRQueryBuilder newQueryBuilder() {
return new SOLRQueryBuilder();
}
@Override
public IStored fetchOne(IQuery query) throws PromptoError {
SolrQuery q = ((SOLRQuery)query).getQuery();
try {
QueryResponse result = query(q);
return getOne(result);
} catch(Exception e) {
throw new InternalError(e);
}
}
private IStored getOne(QueryResponse result) {
if(result.getResults().isEmpty())
return null;
else
return new StoredDocument(this, result.getResults().get(0));
}
@Override
public IStoredIterable fetchMany(IQuery query) throws PromptoError {
SolrQuery q = ((SOLRQuery)query).getQuery();
try {
QueryResponse result = query(q);
return getMany(result);
} catch(Exception e) {
throw new InternalError(e);
}
}
private IStoredIterable getMany(QueryResponse response) {
return new IStoredIterable() {
@Override
public Iterator iterator() {
return new Iterator() {
int current = 0;
@Override
public IStored next() {
return new StoredDocument(BaseSOLRStore.this, response.getResults().get(current++));
}
@Override
public boolean hasNext() {
return current < count();
}
};
}
@Override
public long count() {
return response.getResults().size();
}
@Override
public long totalCount() {
return response.getResults().getNumFound();
}
};
}
@Override
public IStorable newStorable(String[] categories, IDbIdFactory factory) {
return new StorableDocument(categories, factory);
}
public abstract void createCoreIfRequired() throws SolrServerException, IOException;
public abstract void dropCoreIfExists() throws SolrServerException, IOException;
public abstract QueryResponse query(SolrQuery params) throws SolrServerException, IOException;
public void addDocuments(SolrInputDocument ... docs) throws SolrServerException, IOException {
addDocuments(Arrays.asList(docs));
}
public abstract void addDocuments(Collection docs) throws SolrServerException, IOException;
public abstract void dropDocuments(List dbIds) throws SolrServerException, IOException;
public abstract boolean hasField(String fieldName)throws SolrServerException, IOException;
public abstract void addField(String fieldName, String fieldType, Map options) throws SolrServerException, IOException;
public abstract void addCopyField(String fieldName, String fieldType, Map options, String sourceName) throws SolrServerException, IOException;
public abstract String getFieldType(String fieldName) throws SolrServerException, IOException;
public abstract void dropField(String fieldName) throws SolrServerException, IOException;
public abstract void setCommitDelay(int commitDelay) throws SolrServerException;
@Override
public long nextSequenceValue(String prefix) {
throw new UnsupportedOperationException("yet!");
}
@Override
public Map fetchConfiguration(String name) {
throw new UnsupportedOperationException("yet!");
}
@Override
public void storeConfiguration(String name, Map data) {
throw new UnsupportedOperationException("yet!");
}
@Override
public boolean isAuditEnabled() {
return false;
}
}