001// -------------------------------------------------------------------------------- 002// Copyright 2002-2024 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.item.server.indexer; 018 019import com.echothree.model.control.core.common.MimeTypeUsageTypes; 020import com.echothree.model.control.index.common.IndexConstants; 021import com.echothree.model.control.index.common.IndexFieldVariations; 022import com.echothree.model.control.index.common.IndexFields; 023import com.echothree.model.control.index.server.analysis.ItemAnalyzer; 024import com.echothree.model.control.index.server.indexer.BaseIndexer; 025import com.echothree.model.control.index.server.indexer.FieldTypes; 026import com.echothree.model.control.index.server.indexer.IndexerDebugFlags; 027import com.echothree.model.control.index.server.indexer.sortabledescriptionproducer.SortableDescriptionProducer; 028import com.echothree.model.control.index.server.indexer.sortabledescriptionproducer.SortableDescriptionProducerFactory; 029import com.echothree.model.control.item.server.control.ItemControl; 030import com.echothree.model.data.accounting.server.entity.ItemAccountingCategory; 031import com.echothree.model.data.core.server.entity.EntityInstance; 032import com.echothree.model.data.core.server.entity.MimeTypeUsageType; 033import com.echothree.model.data.index.server.entity.Index; 034import com.echothree.model.data.item.server.entity.Item; 035import com.echothree.model.data.item.server.entity.ItemAlias; 036import com.echothree.model.data.item.server.entity.ItemClobDescription; 037import com.echothree.model.data.item.server.entity.ItemDeliveryType; 038import com.echothree.model.data.item.server.entity.ItemDescription; 039import com.echothree.model.data.item.server.entity.ItemDescriptionType; 040import com.echothree.model.data.item.server.entity.ItemDescriptionTypeDetail; 041import com.echothree.model.data.item.server.entity.ItemDetail; 042import com.echothree.model.data.item.server.entity.ItemInventoryType; 043import com.echothree.model.data.item.server.entity.ItemStringDescription; 044import com.echothree.model.data.vendor.server.entity.ItemPurchasingCategory; 045import com.echothree.util.server.message.ExecutionErrorAccumulator; 046import com.echothree.util.server.persistence.Session; 047import java.util.List; 048import org.apache.lucene.analysis.Analyzer; 049import org.apache.lucene.document.Document; 050import org.apache.lucene.document.Field; 051import org.apache.lucene.document.LongPoint; 052import org.apache.lucene.document.SortedDocValuesField; 053import org.apache.lucene.util.BytesRef; 054 055public class ItemIndexer 056 extends BaseIndexer<Item> { 057 058 ItemControl itemControl = Session.getModelController(ItemControl.class); 059 060 List<ItemDescriptionType> itemDescriptionTypes; 061 SortableDescriptionProducer sortableDescriptionProducer; 062 063 /** Creates a new instance of ItemIndexer */ 064 public ItemIndexer(final ExecutionErrorAccumulator eea, final Index index) { 065 super(eea, index); 066 067 itemDescriptionTypes = itemControl.getItemDescriptionTypesByIncludeInIndex(); 068 sortableDescriptionProducer = SortableDescriptionProducerFactory.getInstance().getSortableDescriptionProducer(index.getLastDetail().getLanguage()); 069 } 070 071 @Override 072 protected Analyzer getAnalyzer() { 073 return new ItemAnalyzer(eea, language, entityType, entityAliasTypes, entityAttributes, tagScopes); 074 } 075 076 @Override 077 protected Item getEntity(final EntityInstance entityInstance) { 078 return itemControl.getItemByEntityInstance(entityInstance); 079 } 080 081 @Override 082 protected Document convertToDocument(final EntityInstance entityInstance, final Item item) { 083 ItemDetail itemDetail = item.getLastDetail(); 084 List<ItemAlias> itemAliases = itemControl.getItemAliasesByItem(item); 085 ItemDeliveryType itemDeliveryType = itemDetail.getItemDeliveryType(); 086 ItemInventoryType itemInventoryType = itemDetail.getItemInventoryType(); 087 ItemAccountingCategory itemAccountingCategory = itemDetail.getItemAccountingCategory(); 088 ItemPurchasingCategory itemPurchasingCategory = itemDetail.getItemPurchasingCategory(); 089 Boolean inventorySerialized = itemDetail.getInventorySerialized(); 090 Long shippingEndTime = itemDetail.getShippingEndTime(); 091 Long salesOrderEndTime = itemDetail.getSalesOrderEndTime(); 092 Long purchaseOrderStartTime = itemDetail.getPurchaseOrderStartTime(); 093 Long purchaseOrderEndTime = itemDetail.getPurchaseOrderEndTime(); 094 095 var document = newDocumentWithEntityInstanceFields(entityInstance, item.getPrimaryKey()); 096 097 document.add(new Field(IndexFields.itemName.name(), itemDetail.getItemName(), FieldTypes.NOT_STORED_TOKENIZED)); 098 document.add(new SortedDocValuesField(IndexFields.itemName.name() + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.sortable.name(), 099 new BytesRef(itemDetail.getItemName()))); 100 document.add(new Field(IndexFields.itemNameAndAliases.name(), itemDetail.getItemName(), FieldTypes.NOT_STORED_TOKENIZED)); 101 102 document.add(new Field(IndexFields.itemTypeName.name(), itemDetail.getItemType().getItemTypeName(), FieldTypes.NOT_STORED_TOKENIZED)); 103 document.add(new Field(IndexFields.itemUseTypeName.name(), itemDetail.getItemUseType().getItemUseTypeName(), FieldTypes.NOT_STORED_TOKENIZED)); 104 105 if(itemDeliveryType != null) { 106 document.add(new Field(IndexFields.itemDeliveryTypeName.name(), itemDeliveryType.getItemDeliveryTypeName(), FieldTypes.NOT_STORED_TOKENIZED)); 107 } 108 109 if(itemInventoryType != null) { 110 document.add(new Field(IndexFields.itemInventoryTypeName.name(), itemInventoryType.getItemInventoryTypeName(), FieldTypes.NOT_STORED_TOKENIZED)); 111 } 112 113 itemAliases.stream().map((itemAlias) -> { 114 document.add(new Field(IndexFields.aliases.name(), itemAlias.getAlias(), FieldTypes.NOT_STORED_TOKENIZED)); 115 return itemAlias; 116 }).map((itemAlias) -> { 117 document.add(new Field(IndexFields.itemNameAndAliases.name(), itemAlias.getAlias(), FieldTypes.NOT_STORED_TOKENIZED)); 118 return itemAlias; 119 }).forEach((itemAlias) -> { 120 document.add(new Field(itemAlias.getItemAliasType().getLastDetail().getItemAliasTypeName(), itemAlias.getAlias(), FieldTypes.NOT_STORED_TOKENIZED)); 121 }); 122 123 document.add(new Field(IndexFields.itemCategoryName.name(), itemDetail.getItemCategory().getLastDetail().getItemCategoryName(), FieldTypes.NOT_STORED_TOKENIZED)); 124 125 if(itemAccountingCategory != null) { 126 document.add(new Field(IndexFields.itemAccountingCategoryName.name(), itemDetail.getItemAccountingCategory().getLastDetail().getItemAccountingCategoryName(), FieldTypes.NOT_STORED_TOKENIZED)); 127 } 128 129 if(itemPurchasingCategory != null) { 130 document.add(new Field(IndexFields.itemPurchasingCategoryName.name(), itemDetail.getItemPurchasingCategory().getLastDetail().getItemPurchasingCategoryName(), FieldTypes.NOT_STORED_TOKENIZED)); 131 } 132 133 if(inventorySerialized != null) { 134 document.add(new Field(IndexFields.inventorySerialized.name(), itemDetail.getInventorySerialized().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 135 } 136 137 document.add(new Field(IndexFields.shippingChargeExempt.name(), itemDetail.getShippingChargeExempt().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 138 document.add(new LongPoint(IndexFields.shippingStartTime.name(), itemDetail.getShippingStartTime())); 139 if(shippingEndTime != null) { 140 document.add(new LongPoint(IndexFields.shippingEndTime.name(), shippingEndTime)); 141 } 142 document.add(new LongPoint(IndexFields.salesOrderStartTime.name(), itemDetail.getSalesOrderStartTime())); 143 if(salesOrderEndTime != null) { 144 document.add(new LongPoint(IndexFields.salesOrderEndTime.name(), salesOrderEndTime)); 145 } 146 if(purchaseOrderStartTime != null) { 147 document.add(new LongPoint(IndexFields.purchaseOrderStartTime.name(), purchaseOrderStartTime)); 148 } 149 if(purchaseOrderEndTime != null) { 150 document.add(new LongPoint(IndexFields.purchaseOrderEndTime.name(), purchaseOrderEndTime)); 151 } 152 document.add(new Field(IndexFields.allowClubDiscounts.name(), itemDetail.getAllowClubDiscounts().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 153 document.add(new Field(IndexFields.allowCouponDiscounts.name(), itemDetail.getAllowCouponDiscounts().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 154 document.add(new Field(IndexFields.allowAssociatePayments.name(), itemDetail.getAllowAssociatePayments().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 155 156 itemDescriptionTypes.forEach((itemDescriptionType) -> { 157 ItemDescription itemDescription = itemControl.getBestItemDescription(itemDescriptionType, item, language); 158 if (itemDescription != null) { 159 ItemDescriptionTypeDetail itemDescriptionTypeDetail = itemDescriptionType.getLastDetail(); 160 MimeTypeUsageType mimeTypeUsageType = itemDescriptionTypeDetail.getMimeTypeUsageType(); 161 String itemDescriptionTypeName = itemDescriptionTypeDetail.getItemDescriptionTypeName(); 162 163 if(mimeTypeUsageType == null) { 164 ItemStringDescription itemStringDescription = itemControl.getItemStringDescription(itemDescription); 165 String stringDescription = itemStringDescription.getStringDescription(); 166 167 document.add(new Field(itemDescriptionTypeName, stringDescription, FieldTypes.NOT_STORED_TOKENIZED)); 168 document.add(new Field(itemDescriptionTypeName + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.dictionary.name(), 169 stringDescription, FieldTypes.NOT_STORED_TOKENIZED)); 170 document.add(new SortedDocValuesField(itemDescriptionTypeName + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.sortable.name(), 171 new BytesRef(sortableDescriptionProducer.getSortableDescription(stringDescription)))); 172 173 if(IndexerDebugFlags.LogItemIndexing) { 174 log.info("--- " + itemDescriptionTypeName + ", stringDescription = " + stringDescription); 175 } 176 } else { 177 String mimeTypeUsageTypeName = mimeTypeUsageType.getMimeTypeUsageTypeName(); 178 179 if(mimeTypeUsageTypeName.equals(MimeTypeUsageTypes.TEXT.name())) { 180 ItemClobDescription itemClobDescription = itemControl.getItemClobDescription(itemDescription); 181 String clobDescription = itemClobDescription.getClobDescription(); 182 183 // TODO: mime type conversion to text/plain happens here 184 document.add(new Field(itemDescriptionTypeName, clobDescription, FieldTypes.NOT_STORED_TOKENIZED)); 185 186 if(IndexerDebugFlags.LogItemIndexing) { 187 log.info("--- " + itemDescriptionTypeName + ", clobDescription = " + clobDescription); 188 } 189 } // Others are not supported at this time, DOCUMENT probably should be. 190 } 191 } 192 }); 193 194 return document; 195 } 196 197}