001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.index.server.indexer; 018 019import com.echothree.model.control.core.common.EntityAttributeTypes; 020import com.echothree.model.control.core.server.control.AppearanceControl; 021import com.echothree.model.control.core.server.control.ComponentControl; 022import com.echothree.model.control.core.server.control.EntityAliasControl; 023import com.echothree.model.control.core.server.control.EntityTypeControl; 024import com.echothree.model.control.core.server.control.EventControl; 025import com.echothree.model.control.index.common.IndexConstants; 026import com.echothree.model.control.index.common.IndexFields; 027import com.echothree.model.control.index.common.IndexSubfields; 028import com.echothree.model.control.index.common.exception.IndexIOErrorException; 029import com.echothree.model.control.index.server.analyzer.BasicAnalyzer; 030import com.echothree.model.control.index.server.control.IndexControl; 031import com.echothree.model.control.tag.server.control.TagControl; 032import com.echothree.model.control.workflow.server.control.WorkflowControl; 033import com.echothree.model.data.core.server.entity.EntityAliasType; 034import com.echothree.model.data.core.server.entity.EntityAttribute; 035import com.echothree.model.data.core.server.entity.EntityInstance; 036import com.echothree.model.data.core.server.entity.EntityType; 037import com.echothree.model.data.index.server.entity.Index; 038import com.echothree.model.data.index.server.entity.IndexStatus; 039import com.echothree.model.data.party.server.entity.Language; 040import com.echothree.model.data.tag.server.entity.TagScope; 041import com.echothree.util.common.message.ExecutionErrors; 042import com.echothree.util.common.persistence.BasePK; 043import com.echothree.util.server.control.BaseLogic; 044import com.echothree.util.server.message.ExecutionErrorAccumulator; 045import com.echothree.util.server.persistence.BaseEntity; 046import java.io.Closeable; 047import java.io.File; 048import java.io.IOException; 049import java.nio.file.Paths; 050import java.util.List; 051import javax.inject.Inject; 052import org.apache.commons.logging.Log; 053import org.apache.commons.logging.LogFactory; 054import org.apache.lucene.analysis.Analyzer; 055import org.apache.lucene.document.Document; 056import org.apache.lucene.document.Field; 057import org.apache.lucene.document.IntPoint; 058import org.apache.lucene.document.LongPoint; 059import org.apache.lucene.index.IndexWriter; 060import org.apache.lucene.index.IndexWriterConfig; 061import org.apache.lucene.index.SerialMergeScheduler; 062import org.apache.lucene.index.Term; 063import org.apache.lucene.store.Directory; 064import org.apache.lucene.store.FSDirectory; 065 066public abstract class BaseIndexer<BE extends BaseEntity> 067 extends BaseLogic 068 implements Closeable { 069 070 @Inject 071 protected AppearanceControl appearanceControl; 072 073 @Inject 074 protected ComponentControl componentControl; 075 076 @Inject 077 protected EntityAliasControl entityAliasControl; 078 079 @Inject 080 protected EntityTypeControl entityTypeControl; 081 082 @Inject 083 protected EventControl eventControl; 084 085 @Inject 086 protected IndexControl indexControl; 087 088 @Inject 089 protected TagControl tagControl; 090 091 @Inject 092 protected WorkflowControl workflowControl; 093 094 protected Log log = LogFactory.getLog(this.getClass()); 095 096 protected ExecutionErrorAccumulator eea; 097 protected Index index; 098 099 protected Language language; 100 protected EntityType entityType; 101 protected IndexStatus indexStatus; 102 protected List<EntityAliasType> entityAliasTypes; 103 protected List<EntityAttribute> entityAttributes; 104 protected List<TagScope> tagScopes; 105 106 protected IndexWriter indexWriter; 107 108 protected BaseIndexer<BE> setup(final ExecutionErrorAccumulator eea, final Index index) { 109 this.eea = eea; 110 this.index = index; 111 112 return this; 113 } 114 115 public Index getIndex() { 116 return index; 117 } 118 119 public void open() { 120 if(indexWriter == null) { 121 var indexDetail = index.getLastDetail(); 122 123 this.language = indexDetail.getLanguage(); 124 this.entityType = indexDetail.getIndexType().getLastDetail().getEntityType(); 125 this.indexStatus = indexControl.getIndexStatusForUpdate(index); 126 this.entityAliasTypes = entityAliasControl.getEntityAliasTypesByEntityType(entityType); 127 this.entityAttributes = coreControl.getEntityAttributesByEntityType(entityType); 128 this.tagScopes = tagControl.getTagScopesByEntityType(entityType); 129 130 openIndexWriter(getAnalyzer()); 131 } 132 } 133 134 public EntityType getEntityType() { 135 return entityType; 136 } 137 138 @Override 139 public void close() { 140 if(indexWriter != null) { 141 closeIndexWriter(); 142 } 143 } 144 145 /** Index an EntityInstance in all of its Workflows. */ 146 private void indexWorkflowEntityStatuses(final Document document, final EntityInstance entityInstance) { 147 workflowControl.getWorkflowsByEntityType(entityInstance.getEntityType()).forEach((workflow) -> { 148 var workflowEntityStatuses = workflowControl.getWorkflowEntityStatusesByEntityInstance(workflow, entityInstance); 149 150 if (!workflowEntityStatuses.isEmpty()) { 151 var workflowStepNamesBuilder = new StringBuilder(); 152 153 workflowEntityStatuses.forEach((workflowEntityStatus) -> { 154 if(workflowStepNamesBuilder.length() != 0) { 155 workflowStepNamesBuilder.append(' '); 156 } 157 158 workflowStepNamesBuilder.append(workflowEntityStatus.getWorkflowStep().getLastDetail().getWorkflowStepName()); 159 }); 160 161 document.add(new Field(workflow.getLastDetail().getWorkflowName(), workflowStepNamesBuilder.toString(), FieldTypes.NOT_STORED_TOKENIZED)); 162 } 163 }); 164 } 165 166 private void indexEntityTimes(final Document document, final EntityInstance entityInstance) { 167 var entityTime = eventControl.getEntityTime(entityInstance); 168 169 if(entityTime != null) { 170 var createdTime = entityTime.getCreatedTime(); 171 var modifiedTime = entityTime.getModifiedTime(); 172 var deletedTime = entityTime.getDeletedTime(); 173 174 if(createdTime != null) { 175 document.add(new LongPoint(IndexFields.createdTime.name(), createdTime)); 176 } 177 178 if(modifiedTime != null) { 179 document.add(new LongPoint(IndexFields.modifiedTime.name(), modifiedTime)); 180 } 181 182 if(deletedTime != null) { 183 document.add(new LongPoint(IndexFields.deletedTime.name(), deletedTime)); 184 } 185 } 186 } 187 188 private void indexEntityAliases(final Document document, final EntityInstance entityInstance) { 189 var entityAliases = entityAliasControl.getEntityAliasesByEntityInstance(entityInstance); 190 191 for(var entityAlias : entityAliases) { 192 var fieldName = entityAlias.getEntityAliasType().getLastDetail().getEntityAliasTypeName(); 193 var alias = entityAlias.getAlias(); 194 195 document.add(new Field(fieldName, alias, FieldTypes.NOT_STORED_NOT_TOKENIZED)); 196 } 197 198 } 199 200 private void indexEntityAttributes(final Document document, final EntityInstance entityInstance) { 201 entityAttributes.forEach((entityAttribute) -> { 202 var entityAttributeDetail = entityAttribute.getLastDetail(); 203 var fieldName = entityAttributeDetail.getEntityAttributeName(); 204 var entityAttributeTypeName = entityAttributeDetail.getEntityAttributeType().getEntityAttributeTypeName(); 205 206 if (entityAttributeTypeName.equals(EntityAttributeTypes.BOOLEAN.name())) { 207 var entityBooleanAttribute = coreControl.getEntityBooleanAttribute(entityAttribute, entityInstance); 208 209 if(entityBooleanAttribute != null) { 210 var booleanAttribute = entityBooleanAttribute.getBooleanAttribute(); 211 if(IndexerDebugFlags.LogBaseIndexing) { 212 log.info("--- fieldName =\"" + fieldName + ", \"booleanAttribute = \"" + booleanAttribute + "\""); 213 } 214 document.add(new Field(fieldName, booleanAttribute.toString(), FieldTypes.NOT_STORED_NOT_TOKENIZED)); 215 } 216 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.NAME.name())) { 217 var entityNameAttribute = coreControl.getEntityNameAttribute(entityAttribute, entityInstance); 218 219 if(entityNameAttribute != null) { 220 var nameAttribute = entityNameAttribute.getNameAttribute(); 221 if(IndexerDebugFlags.LogBaseIndexing) { 222 log.info("--- fieldName =\"" + fieldName + ", \"nameAttribute = \"" + nameAttribute + "\""); 223 } 224 document.add(new Field(fieldName, nameAttribute, FieldTypes.NOT_STORED_NOT_TOKENIZED)); 225 } 226 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.INTEGER.name())) { 227 var entityIntegerAttribute = coreControl.getEntityIntegerAttribute(entityAttribute, entityInstance); 228 229 if(entityIntegerAttribute != null) { 230 var integerAttribute = entityIntegerAttribute.getIntegerAttribute(); 231 if(IndexerDebugFlags.LogBaseIndexing) { 232 log.info("--- fieldName =\"" + fieldName + ",\" integerAttribute = \"" + integerAttribute + "\""); 233 } 234 document.add(new IntPoint(fieldName, integerAttribute)); 235 } 236 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.LONG.name())) { 237 var entityLongAttribute = coreControl.getEntityLongAttribute(entityAttribute, entityInstance); 238 239 if(entityLongAttribute != null) { 240 var longAttribute = entityLongAttribute.getLongAttribute(); 241 if(IndexerDebugFlags.LogBaseIndexing) { 242 log.info("--- fieldName =\"" + fieldName + ",\" longAttribute = \"" + longAttribute + "\""); 243 } 244 document.add(new LongPoint(fieldName, longAttribute)); 245 } 246 } else if (language != null && entityAttributeTypeName.equals(EntityAttributeTypes.STRING.name())) { 247 var entityStringAttribute = coreControl.getEntityStringAttribute(entityAttribute, entityInstance, language); 248 249 if(entityStringAttribute != null) { 250 var stringAttribute = entityStringAttribute.getStringAttribute(); 251 if(IndexerDebugFlags.LogBaseIndexing) { 252 log.info("--- fieldName = \"" + fieldName + ",\" stringAttribute = \"" + stringAttribute + "\""); 253 } 254 document.add(new Field(fieldName, stringAttribute, FieldTypes.NOT_STORED_TOKENIZED)); 255 } 256 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.GEOPOINT.name())) { 257 var entityGeoPointAttribute = coreControl.getEntityGeoPointAttribute(entityAttribute, entityInstance); 258 259 if(entityGeoPointAttribute != null) { 260 var latitude = entityGeoPointAttribute.getLatitude(); 261 var longitude = entityGeoPointAttribute.getLongitude(); 262 var elevation = entityGeoPointAttribute.getElevation(); 263 var altitude = entityGeoPointAttribute.getAltitude(); 264 265 if(IndexerDebugFlags.LogBaseIndexing) { 266 log.info("--- fieldName = \"" + fieldName + ",\" latitude = \"" + latitude + ",\" longitude = \"" + longitude + ",\" elevation = \"" + elevation + ",\" altitude = \"" + altitude + "\""); 267 } 268 269 document.add(new IntPoint(fieldName + IndexConstants.INDEX_SUBFIELD_SEPARATOR + IndexSubfields.latitude.name(), latitude)); 270 document.add(new IntPoint(fieldName + IndexConstants.INDEX_SUBFIELD_SEPARATOR + IndexSubfields.longitude.name(), longitude)); 271 272 if(elevation != null) { 273 document.add(new LongPoint(fieldName + IndexConstants.INDEX_SUBFIELD_SEPARATOR + IndexSubfields.elevation.name(), elevation)); 274 } 275 276 if(altitude != null) { 277 document.add(new LongPoint(fieldName + IndexConstants.INDEX_SUBFIELD_SEPARATOR + IndexSubfields.altitude.name(), altitude)); 278 } 279 } 280 } else if (language != null && entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) { 281 // TODO: MIME type should be taken into account 282 var entityClobAttribute = coreControl.getEntityClobAttribute(entityAttribute, entityInstance, language); 283 284 if(entityClobAttribute != null) { 285 var clobAttribute = entityClobAttribute.getClobAttribute(); 286 if(IndexerDebugFlags.LogBaseIndexing) { 287 log.info("--- fieldName =\"" + fieldName + ",\" clobAttribute = \"" + clobAttribute + "\""); 288 } 289 document.add(new Field(fieldName, clobAttribute, FieldTypes.NOT_STORED_TOKENIZED)); 290 } 291 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.DATE.name())) { 292 var entityDateAttribute = coreControl.getEntityDateAttribute(entityAttribute, entityInstance); 293 294 if(entityDateAttribute != null) { 295 var dateAttribute = entityDateAttribute.getDateAttribute(); 296 if(IndexerDebugFlags.LogBaseIndexing) { 297 log.info("--- fieldName =\"" + fieldName + ",\" dateAttribute = \"" + dateAttribute + "\""); 298 } 299 document.add(new IntPoint(fieldName, dateAttribute)); 300 } 301 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.TIME.name())) { 302 var entityTimeAttribute = coreControl.getEntityTimeAttribute(entityAttribute, entityInstance); 303 304 if(entityTimeAttribute != null) { 305 var timeAttribute = entityTimeAttribute.getTimeAttribute(); 306 if(IndexerDebugFlags.LogBaseIndexing) { 307 log.info("--- fieldName =\"" + fieldName + ",\" dateAttribute = \"" + timeAttribute + "\""); 308 } 309 document.add(new LongPoint(fieldName, timeAttribute)); 310 } 311 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.LISTITEM.name())) { 312 var entityListItemAttribute = coreControl.getEntityListItemAttribute(entityAttribute, entityInstance); 313 314 if(entityListItemAttribute != null) { 315 var entityListItemName = entityListItemAttribute.getEntityListItem().getLastDetail().getEntityListItemName(); 316 if(IndexerDebugFlags.LogBaseIndexing) { 317 log.info("--- fieldName =\"" + fieldName + ",\" entityListItemName = \"" + entityListItemName + "\""); 318 } 319 document.add(new Field(fieldName, entityListItemName, FieldTypes.NOT_STORED_TOKENIZED)); 320 } 321 } else if (entityAttributeTypeName.equals(EntityAttributeTypes.MULTIPLELISTITEM.name())) { 322 var entityMultipleListItemAttributes = coreControl.getEntityMultipleListItemAttributes(entityAttribute, entityInstance); 323 if (entityMultipleListItemAttributes != null && !entityMultipleListItemAttributes.isEmpty()) { 324 var entityListItemNamesBuilder = new StringBuilder(); 325 entityMultipleListItemAttributes.forEach((entityMultipleListItemAttribute) -> { 326 if(entityListItemNamesBuilder.length() != 0) { 327 entityListItemNamesBuilder.append(' '); 328 } 329 330 entityListItemNamesBuilder.append(entityMultipleListItemAttribute.getEntityListItem().getLastDetail().getEntityListItemName()); 331 }); 332 var entityListItemNames = entityListItemNamesBuilder.toString(); 333 if(IndexerDebugFlags.LogBaseIndexing) { 334 log.info("--- fieldName =\"" + fieldName + ",\" entityListItemNames = \"" + entityListItemNames + "\""); 335 } 336 document.add(new Field(fieldName, entityListItemNames, FieldTypes.NOT_STORED_TOKENIZED)); 337 } 338 } 339 }); 340 } 341 342 private void indexEntityTags(final Document document, final EntityInstance entityInstance) { 343 var entityTags = tagControl.getEntityTagsByTaggedEntityInstance(entityInstance); 344 345 entityTags.stream().map((entityTag) -> entityTag.getTag().getLastDetail()).forEach((tagDetail) -> { 346 var tagScopeName = tagDetail.getTagScope().getLastDetail().getTagScopeName(); 347 var tagName = tagDetail.getTagName(); 348 349 document.add(new Field(tagScopeName, tagName, FieldTypes.NOT_STORED_TOKENIZED)); 350 }); 351 } 352 353 private void indexEntityAppearance(final Document document, final EntityInstance entityInstance) { 354 var entityAppearance = appearanceControl.getEntityAppearance(entityInstance); 355 356 if(entityAppearance != null) { 357 var entityAppearanceName = entityAppearance.getAppearance().getLastDetail().getAppearanceName(); 358 359 document.add(new Field(IndexFields.appearance.name(), entityAppearanceName, FieldTypes.NOT_STORED_TOKENIZED)); 360 } 361 } 362 363 protected void addEntityInstanceToDocument(final Document document, final EntityInstance entityInstance, final BasePK basePK) { 364 document.add(new Field(IndexFields.entityRef.name(), basePK.getEntityRef(), FieldTypes.STORED_NOT_TOKENIZED)); 365 document.add(new Field(IndexFields.entityInstanceId.name(), entityInstance.getPrimaryKey().getEntityId().toString(), FieldTypes.STORED_NOT_TOKENIZED)); 366 } 367 368 protected void addEntityInstanceFieldsToDocument(final Document document, final EntityInstance entityInstance) { 369 indexWorkflowEntityStatuses(document, entityInstance); 370 indexEntityTimes(document, entityInstance); 371 indexEntityAliases(document, entityInstance); 372 indexEntityAttributes(document, entityInstance); 373 indexEntityTags(document, entityInstance); 374 indexEntityAppearance(document, entityInstance); 375 } 376 377 protected Document newDocumentWithEntityInstanceFields(final EntityInstance entityInstance, final BasePK basePK) { 378 final var document = new Document(); 379 380 addEntityInstanceToDocument(document, entityInstance, basePK); 381 addEntityInstanceFieldsToDocument(document, entityInstance); 382 383 return document; 384 } 385 386 /** 387 * Create a Lucene IndexWriter. 388 */ 389 protected void openIndexWriter(final Analyzer analyzer) { 390 if(IndexerDebugFlags.LogBaseIndexing) { 391 log.info(">>> getIndexWriter"); 392 } 393 394 var createIndex = indexStatus.getCreatedTime() != null ? false : true; 395 396 if(createIndex) { 397 checkIndexDirectory(eea, indexStatus); 398 } 399 400 // indexCreatedTime is rechecked because if checkIndexDirectory was called, 401 // it will be set to the time the directory was created, vs. remaining null. 402 if(!hasExecutionErrors(eea)) { 403 try { 404 Directory fsDir = FSDirectory.open(Paths.get(index.getLastDetail().getDirectory())); 405 var indexWriterConfig = new IndexWriterConfig(analyzer); 406 407 indexWriterConfig.setMergeScheduler(new SerialMergeScheduler()); 408 indexWriterConfig.setOpenMode(createIndex ? IndexWriterConfig.OpenMode.CREATE : IndexWriterConfig.OpenMode.APPEND); 409 410 indexWriter = new IndexWriter(fsDir, indexWriterConfig); 411 } catch (IOException ioe1) { 412 // indexWriter will remain null, signaling that index was not able to be opened 413 if(IndexerDebugFlags.LogBaseIndexing) { 414 log.info("--- new IndexWriter failed"); 415 } 416 417 try { 418 if(indexWriter != null) { 419 indexWriter.close(); 420 } 421 } catch (IOException ioe2) { 422 // ioe2 discarded. 423 } finally { 424 indexWriter = null; 425 } 426 427 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), ioe1.getMessage()); 428 } 429 } 430 431 if(IndexerDebugFlags.LogBaseIndexing) { 432 log.info("<<< getIndexWriter"); 433 } 434 } 435 436 protected void closeIndexWriter() { 437 if(IndexerDebugFlags.LogBaseIndexing) { 438 log.info(">>> closeIndexWriter"); 439 } 440 441 try { 442 indexWriter.commit(); 443 indexWriter.close(); 444 } catch(IOException ioe) { 445 // unrecoverable error 446 // TODO: Index should be marked as possibly invalid 447 if(IndexerDebugFlags.LogBaseIndexing) { 448 log.info("--- indexWriter.close failed"); 449 } 450 451 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), ioe.getMessage()); 452 } 453 454 if(IndexerDebugFlags.LogBaseIndexing) { 455 log.info("<<< closeIndexWriter"); 456 } 457 } 458 459 private void checkIndexDirectory(final ExecutionErrorAccumulator eea, final IndexStatus indexStatus) { 460 if(IndexerDebugFlags.LogBaseIndexing) { 461 log.info("--- checkIndexDirectory, index = " + index); 462 } 463 var indexCreatedTime = indexStatus.getCreatedTime(); 464 465 if(indexCreatedTime == null) { 466 indexCreatedTime = createIndexDirectory(eea); 467 468 if(!hasExecutionErrors(eea)) { 469 indexStatus.setCreatedTime(indexCreatedTime); 470 } 471 } 472 } 473 474 private Long createIndexDirectory(final ExecutionErrorAccumulator eea) { 475 if(IndexerDebugFlags.LogBaseIndexing) { 476 log.info(">>> createIndexDirectory, index = " + index); 477 } 478 Long indexCreatedTime = null; 479 var strDirectory = index.getLastDetail().getDirectory(); 480 var directory = new File(strDirectory); 481 482 if(directory.exists()) { 483 if(directory.isDirectory()) { 484 var files = directory.listFiles(); 485 486 if(files == null) { 487 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), "listFiles failed for " + strDirectory); 488 } else { 489 var numFiles = files.length; 490 491 for(var i = 0; i < numFiles ; i++) { 492 var indivFile = files[i]; 493 494 if(indivFile.isFile()) { 495 if(!indivFile.delete()) { 496 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), "delete failed for " + indivFile.getPath()); 497 } 498 } 499 } 500 } 501 } else { 502 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), "directory isn't a directory: " + directory.getPath()); 503 } 504 } else { 505 if(!directory.mkdirs()) { 506 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), "mkdirs failed for " + directory.getPath()); 507 } 508 } 509 510 if(!hasExecutionErrors(eea)) { 511 indexCreatedTime = System.currentTimeMillis(); 512 } 513 514 if(IndexerDebugFlags.LogBaseIndexing) { 515 log.info("<<< createIndexDirectory, indexCreatedTime = " + indexCreatedTime); 516 } 517 return indexCreatedTime; 518 } 519 520 public void forceReindex() { 521 indexStatus.setCreatedTime(null); 522 } 523 524 protected Analyzer getAnalyzer() { 525 return new BasicAnalyzer(eea, language, entityType, entityAliasTypes, entityAttributes, tagScopes); 526 } 527 528 protected abstract BE getEntity(final EntityInstance entityInstance); 529 530 protected abstract Document convertToDocument(final EntityInstance entityInstance, final BE item); 531 532 protected void addEntityToIndex(final EntityInstance entityInstance, final BE baseEntity) 533 throws IOException { 534 var document = convertToDocument(entityInstance, baseEntity); 535 536 if(document != null) { 537 indexWriter.addDocument(document); 538 } 539 } 540 541 protected void removeEntityFromIndex(final BE baseEntity) 542 throws IOException { 543 indexWriter.deleteDocuments(new Term(IndexFields.entityRef.name(), baseEntity.getPrimaryKey().getEntityRef())); 544 } 545 546 public void updateIndex(final EntityInstance entityInstance) { 547 var baseEntity = getEntity(entityInstance); 548 549 if(baseEntity != null) { 550 var entityTime = eventControl.getEntityTime(entityInstance); 551 552 if(entityTime != null) { 553 var modifiedTime = entityTime.getModifiedTime(); 554 var deletedTime = entityTime.getDeletedTime(); 555 556 try { 557 if(modifiedTime != null || deletedTime != null) { 558 removeEntityFromIndex(baseEntity); 559 } 560 561 if(deletedTime == null) { 562 addEntityToIndex(entityInstance, baseEntity); 563 } 564 } catch(IOException ioe) { 565 handleExecutionError(IndexIOErrorException.class, eea, ExecutionErrors.IndexIOError.name(), ioe.getMessage()); 566 } 567 } 568 } 569 } 570 571}