diff --git a/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java b/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java index 0610c7d39..2fca5b7de 100644 --- a/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java +++ b/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java @@ -84,10 +84,12 @@ import java.text.DecimalFormat; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import com.carrotsearch.hppc.IntArrayList; @@ -139,7 +141,6 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.document.Document; -import org.apache.lucene.document.LongPoint; import org.apache.lucene.index.IndexCommit; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.LeafReaderContext; @@ -195,42 +196,91 @@ public class SolrInformationServer implements InformationServer /** * A specialization of {@link SolrInputDocument} which allows to represent a partial document (used for issuing * atomic update requests) and interact with it using the same interface of a full document. + * + * The semantic is a little bit specialised so this class it's not meant to be reused outside + * the {@link SolrInformationServer}. + * + * Three methods have been overridden in order to fulfil the following behaviour: + * + * */ - class PartialSolrInputDocument extends SolrInputDocument + static class PartialSolrInputDocument extends SolrInputDocument { @Override + @SuppressWarnings("unchecked") public void addField(String name, Object value) { - mutate(name, value, "set"); - } + Map> fieldModifier = + (Map>)computeIfAbsent(name, k -> { + remove(name); + setField(name, newFieldModifier("add")); -// @Override -// public void setField(String name, Object value) -// { -// mutate(name, value, "set"); -// } + return getField(name); + }).getValue(); + + ofNullable(value) + .ifPresent(v -> fieldModifier.computeIfAbsent( + fieldModifier.keySet().iterator().next(), + LAZY_EMPTY_MUTABLE_LIST).add(v)); + } @Override public SolrInputField removeField(String name) { - setField(name, newFieldModifier()); + setField(name, newFieldModifier("set")); return getField(name); } - @SuppressWarnings("unchecked") - private void mutate(String name, Object value, String op) + /** + * Creates a new field modifier description for inserting an atomic update command within a document. + * + * @return the field modifier (a {@link Map} instance with a null value associated to the "set" command). + */ + private Map> newFieldModifier(String op) { - Map> fieldModifier = - (Map>)computeIfAbsent(name, k -> { - setField(name, newFieldModifier()); - return getField(name); - }).getValue(); - - ofNullable(value).ifPresent(v -> fieldModifier.computeIfAbsent(op, LAZY_EMPTY_MUTABLE_LIST).add(v)); + return new HashMap<>() + {{ + put(op, null); + }}; } } private static final Log LOGGER = new Log(SolrInformationServer.class); + private static final String NO_SITE = "_REPOSITORY_"; private static final String SHARED_FILES = "_SHARED_FILES_"; @@ -239,13 +289,12 @@ public class SolrInformationServer implements InformationServer private static final String LATEST_APPLIED_CONTENT_VERSION_ID = "LATEST_APPLIED_CONTENT_VERSION_ID"; private static final String LAST_INCOMING_CONTENT_VERSION_ID = "LAST_INCOMING_CONTENT_VERSION_ID"; - private static final long CONTENT_OUTDATED_MARKER = -10L; - private static final long CONTENT_UPDATED_MARKER = -20L; - - private static final String CONTENT_LOCALE = "content@s__locale@{http://www.alfresco.org/model/content/1.0}content"; + private static final long CONTENT_OUTDATED_MARKER = -10; + private static final long CONTENT_UPDATED_MARKER = -20; + private static final String CONTENT_LOCALE_FIELD = "content@s__locale@{http://www.alfresco.org/model/content/1.0}content"; private static final Set ID_AND_CONTENT_VERSION_ID_AND_CONTENT_LOCALE = - new HashSet<>(asList(FIELD_SOLR4_ID, LATEST_APPLIED_CONTENT_VERSION_ID, CONTENT_LOCALE)); + new HashSet<>(asList(FIELD_SOLR4_ID, LATEST_APPLIED_CONTENT_VERSION_ID, CONTENT_LOCALE_FIELD)); private static final String INDEX_CAP_ID = "TRACKER!STATE!CAP"; @@ -548,7 +597,7 @@ public class SolrInformationServer implements InformationServer .set(CommonParams.ROWS, 0) .set(FacetParams.FACET, true) //.add(FacetParams.FACET_QUERY, "{!frange key='UPDATED' l=0}sub(LAST_INCOMING_CONTENT_VERSION_ID,LATEST_APPLIED_CONTENT_VERSION_ID)") - .add(FacetParams.FACET_QUERY, "{!key='OUTDATED'}LATEST_APPLIED_CONTENT_VERSION_ID:{-10L TO -10L}"); + .add(FacetParams.FACET_QUERY, "{!key='OUTDATED'}LATEST_APPLIED_CONTENT_VERSION_ID:{-10 TO -10}"); SolrQueryResponse response = cloud.getResponse(nativeRequestHandler, request, params); @@ -827,9 +876,9 @@ public class SolrInformationServer implements InformationServer String idString = id.stringValue(); TenantAclIdDbId tenantAndDbId = AlfrescoSolrDataModel.decodeNodeDocumentId(idString); - ofNullable(document.getField(CONTENT_LOCALE)) + ofNullable(document.getField(CONTENT_LOCALE_FIELD)) .map(IndexableField::stringValue) - .ifPresent(value -> tenantAndDbId.setProperty(CONTENT_LOCALE, value)); + .ifPresent(value -> tenantAndDbId.setProperty(CONTENT_LOCALE_FIELD, value)); tenantAndDbId.setProperty( LATEST_APPLIED_CONTENT_VERSION_ID, @@ -1739,7 +1788,7 @@ public class SolrInformationServer implements InformationServer docRef.aclId, docRef.dbId)); - if (docRef.optionalBag.containsKey(CONTENT_LOCALE)) + if (docRef.optionalBag.containsKey(CONTENT_LOCALE_FIELD)) { addContentToDoc(docRef, doc, docRef.dbId); } @@ -1752,7 +1801,6 @@ public class SolrInformationServer implements InformationServer .map(Long::parseLong) .orElse(CONTENT_UPDATED_MARKER); - markAsContentInSynch(doc, latestAppliedVersionId); // Add to index @@ -1765,7 +1813,7 @@ public class SolrInformationServer implements InformationServer LOGGER.debug( "Text content of Document DBID={} has been marked as updated (latest content version ID = {})", docRef.dbId, - latestAppliedVersionId); + (latestAppliedVersionId == CONTENT_UPDATED_MARKER ? "N.A." : latestAppliedVersionId)); } finally { @@ -1906,7 +1954,6 @@ public class SolrInformationServer implements InformationServer LOGGER.debug("Document size (fields) after getting fields from node {} metadata: {}", metadata.getId(), document.size()); populateProperties( - metadata.getId(), metadata.getProperties(), isContentIndexedForNode(metadata.getProperties()), document, @@ -1919,12 +1966,12 @@ public class SolrInformationServer implements InformationServer private void populateFields(NodeMetaData metadata, SolrInputDocument doc) { - doc.addField(FIELD_TYPE, metadata.getType().toString()); + doc.setField(FIELD_TYPE, metadata.getType().toString()); notNullOrEmpty(metadata.getAspects()) .stream() .filter(Objects::nonNull) .forEach(aspect -> { - doc.addField(FIELD_ASPECT, aspect.toString()); + doc.setField(FIELD_ASPECT, aspect.toString()); if(aspect.equals(ContentModel.ASPECT_GEOGRAPHIC)) { Optional latitude = @@ -1943,7 +1990,7 @@ public class SolrInformationServer implements InformationServer if (latitude.isPresent() && longitude.isPresent()) { - doc.addField(FIELD_GEO, latitude.get() + ", " + longitude.get()); + doc.setField(FIELD_GEO, latitude.get() + ", " + longitude.get()); } else { @@ -1951,16 +1998,16 @@ public class SolrInformationServer implements InformationServer } } }); - doc.addField(FIELD_ISNODE, "T"); - doc.addField(FIELD_TENANT, AlfrescoSolrDataModel.getTenantId(metadata.getTenantDomain())); + doc.setField(FIELD_ISNODE, "T"); + doc.setField(FIELD_TENANT, AlfrescoSolrDataModel.getTenantId(metadata.getTenantDomain())); updatePathRelatedFields(metadata, doc); updateNamePathRelatedFields(metadata, doc); updateAncestorRelatedFields(metadata, doc); - doc.addField(FIELD_PARENT_ASSOC_CRC, metadata.getParentAssocsCrc()); + doc.setField(FIELD_PARENT_ASSOC_CRC, metadata.getParentAssocsCrc()); - ofNullable(metadata.getOwner()).ifPresent(owner -> doc.addField(FIELD_OWNER, owner)); + ofNullable(metadata.getOwner()).ifPresent(owner -> doc.setField(FIELD_OWNER, owner)); StringBuilder qNameBuffer = new StringBuilder(); StringBuilder assocTypeQNameBuffer = new StringBuilder(); @@ -1974,15 +2021,15 @@ public class SolrInformationServer implements InformationServer } qNameBuffer.append(ISO9075.getXPathName(childAssocRef.getQName())); assocTypeQNameBuffer.append(ISO9075.getXPathName(childAssocRef.getTypeQName())); - doc.addField(FIELD_PARENT, childAssocRef.getParentRef().toString()); + doc.setField(FIELD_PARENT, childAssocRef.getParentRef().toString()); if (childAssocRef.isPrimary()) { if(doc.getField(FIELD_PRIMARYPARENT) == null) { - doc.addField(FIELD_PRIMARYPARENT, childAssocRef.getParentRef().toString()); - doc.addField(FIELD_PRIMARYASSOCTYPEQNAME, ISO9075.getXPathName(childAssocRef.getTypeQName())); - doc.addField(FIELD_PRIMARYASSOCQNAME, ISO9075.getXPathName(childAssocRef.getQName())); + doc.setField(FIELD_PRIMARYPARENT, childAssocRef.getParentRef().toString()); + doc.setField(FIELD_PRIMARYASSOCTYPEQNAME, ISO9075.getXPathName(childAssocRef.getTypeQName())); + doc.setField(FIELD_PRIMARYASSOCQNAME, ISO9075.getXPathName(childAssocRef.getQName())); } else { @@ -2042,7 +2089,6 @@ public class SolrInformationServer implements InformationServer } static void populateProperties( - long id, Map properties, boolean contentIndexingHasBeenRequestedForThisNode, SolrInputDocument document, @@ -2057,6 +2103,10 @@ public class SolrInformationServer implements InformationServer markAsContentInSynch(document); } + final BiConsumer setValue = document::setField; + final BiConsumer addValue = document::addField; + final BiConsumer collectName = (name, value) -> addFieldIfNotSet(document, name); + for (Entry property : properties.entrySet()) { QName propertyQName = property.getKey(); @@ -2070,36 +2120,43 @@ public class SolrInformationServer implements InformationServer if (value instanceof StringPropertyValue) { dataModel.getIndexedFieldNamesForProperty(propertyQName).getFields() - .forEach(field -> addStringProperty(document, field, (StringPropertyValue) value, properties)); + .forEach(field -> addStringProperty(setValue.andThen(collectName), field, (StringPropertyValue) value, properties)); } else if (value instanceof MLTextPropertyValue) { dataModel.getIndexedFieldNamesForProperty(propertyQName).getFields() - .forEach(field -> addMLTextProperty(document, field, (MLTextPropertyValue) value)); + .forEach(field -> addMLTextProperty(setValue.andThen(collectName), field, (MLTextPropertyValue) value)); } else if (value instanceof ContentPropertyValue) { - addContentProperty(document, propertyQName, (ContentPropertyValue) value, contentIndexingIsEnabled); + addContentProperty(setValue.andThen(collectName), document, propertyQName, (ContentPropertyValue) value, contentIndexingIsEnabled); } else if (value instanceof MultiPropertyValue) { MultiPropertyValue typedValue = (MultiPropertyValue) value; + clearFields( + document, + dataModel.getIndexedFieldNamesForProperty(propertyQName).getFields() + .stream() + .map(FieldInstance::getField) + .collect(Collectors.toList())); + for (PropertyValue singleValue : typedValue.getValues()) { if (singleValue instanceof StringPropertyValue) { dataModel.getIndexedFieldNamesForProperty(propertyQName).getFields() - .forEach(field -> addStringProperty(document, field, (StringPropertyValue) singleValue, properties)); + .forEach(field -> addStringProperty(addValue.andThen(collectName), field, (StringPropertyValue) singleValue, properties)); } else if (singleValue instanceof MLTextPropertyValue) { dataModel.getIndexedFieldNamesForProperty(propertyQName).getFields() - .forEach(field -> addMLTextProperty(document, field, (MLTextPropertyValue) singleValue)); + .forEach(field -> addMLTextProperty(addValue.andThen(collectName), field, (MLTextPropertyValue) singleValue)); } else if (singleValue instanceof ContentPropertyValue) { - addContentProperty(document, propertyQName, (ContentPropertyValue) singleValue, contentIndexingIsEnabled); + addContentProperty(addValue.andThen(collectName), document, propertyQName, (ContentPropertyValue) singleValue, contentIndexingIsEnabled); } } } @@ -2162,29 +2219,6 @@ public class SolrInformationServer implements InformationServer } } - /** - * Gets the field name used in Solr for the specified content property. - * Assumes that the first defined field in Solr is the "right one". - * @param propertyQName the content property qualified name - * @param type the content property field type, i.e. DOCID - * @return a String representing the name of the field in Solr or null if not found - */ - private static String getSolrFieldNameForContentPropertyMetadata(QName propertyQName, AlfrescoSolrDataModel.ContentFieldType type) - { - IndexedField indexedField = AlfrescoSolrDataModel.getInstance().getIndexedFieldForContentPropertyMetadata(propertyQName, type); - List fields = indexedField.getFields(); - String fieldName = null; - if (fields != null && !fields.isEmpty()) - { - FieldInstance instance = fields.get(0); - if (instance != null) - { - fieldName = instance.getField(); - } - } - return fieldName; - } - private void addContentPropertyMetadata( SolrInputDocument doc, QName propertyQName, @@ -2194,26 +2228,16 @@ public class SolrInformationServer implements InformationServer IndexedField indexedField = dataModel.getIndexedFieldForContentPropertyMetadata(propertyQName, type); for (FieldInstance fieldInstance : indexedField.getFields()) { - // The atomic update always sets (and therefore replaces) the field value because even if we have the - // multivalued and the single value field in the schema, the previous code removed the old field value: - // - // doc.removeField(fieldInstance.getField()); - // - // before adding the new value. In addition, it seems the current implementation of the call above: - // - // dataModel.getIndexedFieldForContentPropertyMetadata(propertyQName, type); - // - // always returns the (s)ingle value field version. switch(type) { case TRANSFORMATION_EXCEPTION: - doc.addField(fieldInstance.getField(), textContentResponse.getTransformException()); + doc.setField(fieldInstance.getField(), textContentResponse.getTransformException()); break; case TRANSFORMATION_STATUS: - doc.addField(fieldInstance.getField(), textContentResponse.getStatus().name()); + doc.setField(fieldInstance.getField(), textContentResponse.getStatus().name()); break; case TRANSFORMATION_TIME: - doc.addField(fieldInstance.getField(), textContentResponse.getTransformDuration()); + doc.setField(fieldInstance.getField(), textContentResponse.getTransformDuration()); break; // Skips the ones that require the ContentPropertyValue default: @@ -2223,31 +2247,31 @@ public class SolrInformationServer implements InformationServer } private static void addContentPropertyMetadata( - SolrInputDocument doc, + BiConsumer consumer, QName propertyQName, ContentPropertyValue contentPropertyValue, AlfrescoSolrDataModel.ContentFieldType type) { - IndexedField indexedField = AlfrescoSolrDataModel.getInstance().getIndexedFieldForContentPropertyMetadata( - propertyQName, type); + IndexedField indexedField = + AlfrescoSolrDataModel.getInstance().getIndexedFieldForContentPropertyMetadata(propertyQName, type); for (FieldInstance fieldInstance : indexedField.getFields()) { switch(type) { case DOCID: - doc.addField(fieldInstance.getField(), contentPropertyValue.getId()); + consumer.accept(fieldInstance.getField(), contentPropertyValue.getId()); break; case ENCODING: - doc.addField(fieldInstance.getField(), contentPropertyValue.getEncoding()); + consumer.accept(fieldInstance.getField(), contentPropertyValue.getEncoding()); break; case LOCALE: - doc.addField(fieldInstance.getField(), contentPropertyValue.getLocale().toString()); + consumer.accept(fieldInstance.getField(), contentPropertyValue.getLocale().toString()); break; case MIMETYPE: - doc.addField(fieldInstance.getField(), contentPropertyValue.getMimetype()); + consumer.accept(fieldInstance.getField(), contentPropertyValue.getMimetype()); break; case SIZE: - doc.addField(fieldInstance.getField(), contentPropertyValue.getLength()); + consumer.accept(fieldInstance.getField(), contentPropertyValue.getLength()); break; // Skips the ones that require the text content response default: @@ -2293,8 +2317,8 @@ public class SolrInformationServer implements InformationServer private static void markAsContentInSynch(SolrInputDocument document, Long id) { long contentVersionId = ofNullable(id).orElse(CONTENT_UPDATED_MARKER); - document.addField(LATEST_APPLIED_CONTENT_VERSION_ID, contentVersionId); - document.addField(LAST_INCOMING_CONTENT_VERSION_ID, contentVersionId); + document.setField(LATEST_APPLIED_CONTENT_VERSION_ID, contentVersionId); + document.setField(LAST_INCOMING_CONTENT_VERSION_ID, contentVersionId); } /** @@ -2362,16 +2386,17 @@ public class SolrInformationServer implements InformationServer } private static void addContentProperty( + BiConsumer consumer, SolrInputDocument document, QName propertyName, ContentPropertyValue propertyValue, boolean contentIndexingEnabled) { - addContentPropertyMetadata(document, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.DOCID); - addContentPropertyMetadata(document, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.SIZE); - addContentPropertyMetadata(document, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.LOCALE); - addContentPropertyMetadata(document, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.MIMETYPE); - addContentPropertyMetadata(document, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.ENCODING); + addContentPropertyMetadata(consumer, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.DOCID); + addContentPropertyMetadata(consumer, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.SIZE); + addContentPropertyMetadata(consumer, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.LOCALE); + addContentPropertyMetadata(consumer, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.MIMETYPE); + addContentPropertyMetadata(consumer, propertyName, propertyValue, AlfrescoSolrDataModel.ContentFieldType.ENCODING); if (contentIndexingEnabled) { @@ -2381,9 +2406,8 @@ public class SolrInformationServer implements InformationServer private void addContentToDoc(TenantAclIdDbId docRef, SolrInputDocument doc, long dbId) throws AuthenticationException, IOException { - - String locale = (String) docRef.optionalBag.get(CONTENT_LOCALE); - String qNamePart = CONTENT_LOCALE.substring(AlfrescoSolrDataModel.CONTENT_S_LOCALE_PREFIX.length()); + String locale = (String) docRef.optionalBag.get(CONTENT_LOCALE_FIELD); + String qNamePart = CONTENT_LOCALE_FIELD.substring(AlfrescoSolrDataModel.CONTENT_S_LOCALE_PREFIX.length()); QName propertyQName = QName.createQName(qNamePart); addContentPropertyToDocUsingAlfrescoRepository(doc, propertyQName, dbId, locale); } @@ -2461,11 +2485,11 @@ public class SolrInformationServer implements InformationServer ? Map.of("set", "\u0000" + locale + "\u0000" + textContent) : textContent); - addFieldIfNotSet(doc, field); + addFieldIfNotSet(doc, field.getField()); }); } - private static void addMLTextProperty(SolrInputDocument doc, FieldInstance field, MLTextPropertyValue mlTextPropertyValue) + private static void addMLTextProperty(BiConsumer consumer, FieldInstance field, MLTextPropertyValue mlTextPropertyValue) { if (mlTextPropertyValue == null) { @@ -2480,7 +2504,7 @@ public class SolrInformationServer implements InformationServer final String propValue = mlTextPropertyValue.getValue(locale); if((locale == null)) { - continue; + continue; } StringBuilder builder = new StringBuilder(propValue.length() + 16); @@ -2488,7 +2512,7 @@ public class SolrInformationServer implements InformationServer if(!field.isSort()) { - doc.addField(field.getField(), builder.toString()); + consumer.accept(field.getField(), builder.toString()); } if (sort.length() > 0) @@ -2500,18 +2524,23 @@ public class SolrInformationServer implements InformationServer if(field.isSort()) { - doc.addField(field.getField(), sort.toString()); + consumer.accept(field.getField(), sort.toString()); } } else { - notNullOrEmpty(mlTextPropertyValue.getLocales()) - .stream() - .filter(Objects::nonNull) - .map(mlTextPropertyValue::getValue) - .forEach(value -> doc.addField(field.getField(), value)); + List localisedValues = + notNullOrEmpty(mlTextPropertyValue.getLocales()) + .stream() + .filter(Objects::nonNull) + .map(mlTextPropertyValue::getValue) + .collect(Collectors.toList()); + + if (!localisedValues.isEmpty()) + { + consumer.accept(field.getField(), localisedValues); + } } - addFieldIfNotSet(doc, field); } @Override @@ -3008,6 +3037,7 @@ public class SolrInformationServer implements InformationServer } } + // TODO: Ci serve ancora??? private void lock(Object id) throws IOException { long startTime = System.currentTimeMillis(); @@ -3087,7 +3117,9 @@ public class SolrInformationServer implements InformationServer doc.setField(FIELD_VERSION, 0); // Here is used add in order to make sure that the atomic update happens + doc.removeField(FIELD_DBID); doc.addField(FIELD_DBID, metadata.getId()); + doc.setField(FIELD_LID, metadata.getNodeRef().toString()); doc.setField(FIELD_INTXID, metadata.getTxnId()); doc.setField(FIELD_DOC_TYPE, docType); @@ -3595,7 +3627,13 @@ public class SolrInformationServer implements InformationServer private Query dirtyOrNewContentQuery() { - Query onlyDirtyDocuments = LegacyNumericRangeQuery.newLongRange(LAST_INCOMING_CONTENT_VERSION_ID, CONTENT_OUTDATED_MARKER, CONTENT_OUTDATED_MARKER, true, true); + Query onlyDirtyDocuments = + LegacyNumericRangeQuery.newLongRange( + LAST_INCOMING_CONTENT_VERSION_ID, + CONTENT_OUTDATED_MARKER, + CONTENT_OUTDATED_MARKER, + true, + true); Query onlyDocuments = new TermQuery(new Term(FIELD_DOC_TYPE, DOC_TYPE_NODE)); return new BooleanQuery.Builder() @@ -3686,44 +3724,49 @@ public class SolrInformationServer implements InformationServer } } - private static void addStringProperty(SolrInputDocument doc, FieldInstance field, StringPropertyValue property, Map properties) + private static void addStringProperty(BiConsumer consumer, FieldInstance field, StringPropertyValue property, Map properties) { if(field.isLocalised()) { Locale locale = ofNullable(properties.get(ContentModel.PROP_LOCALE)) - .map(StringPropertyValue.class::cast) - .map(StringPropertyValue::getValue) - .map(value -> DefaultTypeConverter.INSTANCE.convert(Locale.class, value)) - .orElse(I18NUtil.getLocale()); + .map(StringPropertyValue.class::cast) + .map(StringPropertyValue::getValue) + .map(value -> DefaultTypeConverter.INSTANCE.convert(Locale.class, value)) + .orElse(I18NUtil.getLocale()); - doc.addField(field.getField(), "\u0000" + locale.toString() + "\u0000" + property.getValue()); + consumer.accept(field.getField(), "\u0000" + locale.toString() + "\u0000" + property.getValue()); } else { - doc.addField(field.getField(), property.getValue()); + consumer.accept(field.getField(), property.getValue()); } - - addFieldIfNotSet(doc, field); } - // TODO: Dubbio generale, sto cambiando la semantica dell'addField, che in realtà - // dovrebbe aggiungere ma il partial mi fa un "set" e quindi rimpiazza - private static void addFieldIfNotSet(SolrInputDocument doc, FieldInstance field) - { -// Object existingValue = doc.get(FIELD_FIELDS); -// ofNullable(existingValue) -// .ifPresentOrElse(value -> { -// if (value instanceof Map) -// { +// private static void addStringProperty(SolrInputDocument doc, FieldInstance field, StringPropertyValue property, Map properties) +// { +// if(field.isLocalised()) +// { +// Locale locale = +// ofNullable(properties.get(ContentModel.PROP_LOCALE)) +// .map(StringPropertyValue.class::cast) +// .map(StringPropertyValue::getValue) +// .map(value -> DefaultTypeConverter.INSTANCE.convert(Locale.class, value)) +// .orElse(I18NUtil.getLocale()); // -// } else -// { -// final Map fieldModifier = new HashMap<>() -// } -// }); - // TODO: qua il partial doc mi mette un set ma io devo aggiungere e deduplicare - doc.addField(FIELD_FIELDS, field.getField()); +// doc.addField(field.getField(), "\u0000" + locale.toString() + "\u0000" + property.getValue()); +// } +// else +// { +// doc.addField(field.getField(), property.getValue()); +// } +// +// addFieldIfNotSet(doc, field); +// } + + private static void addFieldIfNotSet(SolrInputDocument doc, String name) + { + doc.addField(FIELD_FIELDS, name); } private boolean mayHaveChildren(NodeMetaData nodeMetaData) @@ -3800,20 +3843,12 @@ public class SolrInformationServer implements InformationServer return searchers; } - /** - * Creates a new field modifier description for inserting an atomic update command within a document. - * - * @return the field modifier (a {@link Map} instance with a null value associated to the "set" command). - */ - private Map> newFieldModifier() + private static void clearFields(SolrInputDocument document, List fields) { - return new HashMap<>() - {{ - put("set", null); - }}; + notNullOrEmpty(fields).forEach(document::removeField); } - private void clearFields(SolrInputDocument document, String... fields) + private static void clearFields(SolrInputDocument document, String... fields) { stream(notNullOrEmpty(fields)).forEach(document::removeField); } diff --git a/search-services/alfresco-search/src/main/java/org/alfresco/solr/tracker/MetadataTracker.java b/search-services/alfresco-search/src/main/java/org/alfresco/solr/tracker/MetadataTracker.java index 3862ebd30..0776006b6 100644 --- a/search-services/alfresco-search/src/main/java/org/alfresco/solr/tracker/MetadataTracker.java +++ b/search-services/alfresco-search/src/main/java/org/alfresco/solr/tracker/MetadataTracker.java @@ -770,9 +770,9 @@ public class MetadataTracker extends CoreStatePublisher implements Tracker private int indexBatchOfTransactions(List txBatch) throws AuthenticationException, IOException, JSONException { int nodeCount = 0; - ArrayList nonEmptyTxs = new ArrayList<>(txBatch.size()); + List nonEmptyTxs = new ArrayList<>(txBatch.size()); GetNodesParameters gnp = new GetNodesParameters(); - ArrayList txIds = new ArrayList(); + List txIds = new ArrayList<>(); for (Transaction tx : txBatch) { if (tx.getUpdates() > 0 || tx.getDeletes() > 0) @@ -786,7 +786,7 @@ public class MetadataTracker extends CoreStatePublisher implements Tracker gnp.setStoreProtocol(storeRef.getProtocol()); gnp.setStoreIdentifier(storeRef.getIdentifier()); updateShardProperty(); - shardProperty.ifPresent(p -> gnp.setShardProperty(p)); + shardProperty.ifPresent(gnp::setShardProperty); gnp.setCoreName(coreName); List nodes = client.getNodes(gnp, Integer.MAX_VALUE); @@ -848,17 +848,15 @@ public class MetadataTracker extends CoreStatePublisher implements Tracker private List filterNodes(List nodes) { - ArrayList filteredList = new ArrayList(nodes.size()); + List filteredList = new ArrayList<>(nodes.size()); for(Node node : nodes) { - if(docRouter.routeNode(shardCount, shardInstance, node)) { filteredList.add(node); } else { - if(node.getStatus() == SolrApiNodeStatus.UPDATED) { Node doCascade = new Node(); diff --git a/search-services/alfresco-search/src/test/java/org/alfresco/solr/AbstractAlfrescoSolrIT.java b/search-services/alfresco-search/src/test/java/org/alfresco/solr/AbstractAlfrescoSolrIT.java index 299cb351d..72b724bd8 100644 --- a/search-services/alfresco-search/src/test/java/org/alfresco/solr/AbstractAlfrescoSolrIT.java +++ b/search-services/alfresco-search/src/test/java/org/alfresco/solr/AbstractAlfrescoSolrIT.java @@ -546,10 +546,12 @@ public abstract class AbstractAlfrescoSolrIT implements SolrTestFiles, AlfrescoS totalHits = topDocs.totalHits; if (topDocs.totalHits == expectedNumFound) { + LOG.warn("Query \"" + query + "\" returned " + totalHits + " as expected"); return; } else { + LOG.warn("Query \"" + query + "\" returned " + totalHits + ", expected " + expectedNumFound); Thread.sleep(2000); } } diff --git a/search-services/alfresco-search/src/test/java/org/alfresco/solr/AlfrescoSolrUtils.java b/search-services/alfresco-search/src/test/java/org/alfresco/solr/AlfrescoSolrUtils.java index 6e330203d..81130eb60 100644 --- a/search-services/alfresco-search/src/test/java/org/alfresco/solr/AlfrescoSolrUtils.java +++ b/search-services/alfresco-search/src/test/java/org/alfresco/solr/AlfrescoSolrUtils.java @@ -613,7 +613,7 @@ public class AlfrescoSolrUtils { final boolean isContentIndexedForNode = true; final boolean transformContentFlag = true; - SolrInformationServer.populateProperties(dbid, properties, isContentIndexedForNode, doc, transformContentFlag); + SolrInformationServer.populateProperties(properties, isContentIndexedForNode, doc, transformContentFlag); addContentToDoc(doc, content); } diff --git a/search-services/alfresco-search/src/test/java/org/alfresco/solr/query/afts/requestHandler/AFTSRequestHandlerIT.java b/search-services/alfresco-search/src/test/java/org/alfresco/solr/query/afts/requestHandler/AFTSRequestHandlerIT.java index 131bd8dce..60130e956 100644 --- a/search-services/alfresco-search/src/test/java/org/alfresco/solr/query/afts/requestHandler/AFTSRequestHandlerIT.java +++ b/search-services/alfresco-search/src/test/java/org/alfresco/solr/query/afts/requestHandler/AFTSRequestHandlerIT.java @@ -106,16 +106,9 @@ public class AFTSRequestHandlerIT extends AbstractRequestHandlerIT implements Qu @Test public void primaryParentField() { - assertResponseCardinality(FIELD_PRIMARYPARENT, "\"" + TEST_NODEREF + "\"", 2); } - @Test - public void ftsStatusField() - { - assertResponseCardinality(FIELD_FTSSTATUS, "\"New\"", 2); - } - @Test public void dbIdField() { diff --git a/search-services/alfresco-search/src/test/resources/log4j.xml b/search-services/alfresco-search/src/test/resources/log4j.xml index c887aa815..be048ddb9 100644 --- a/search-services/alfresco-search/src/test/resources/log4j.xml +++ b/search-services/alfresco-search/src/test/resources/log4j.xml @@ -7,6 +7,11 @@ + + + + + -