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.util.server.string;
018
019import com.echothree.model.control.uom.server.control.UomControl;
020import com.echothree.model.control.user.server.control.UserControl;
021import com.echothree.model.data.party.server.entity.Language;
022import com.echothree.model.data.uom.server.entity.UnitOfMeasureEquivalent;
023import com.echothree.model.data.uom.server.entity.UnitOfMeasureKind;
024import com.echothree.model.data.uom.server.entity.UnitOfMeasureType;
025import com.echothree.model.data.user.server.entity.UserVisit;
026import com.echothree.util.server.persistence.Session;
027import java.util.Iterator;
028import java.util.List;
029
030public class UnitOfMeasureUtils {
031    
032    private UnitOfMeasureUtils() {
033        super();
034    }
035    
036    private static class UnitOfMeasureUtilsHolder {
037        static UnitOfMeasureUtils instance = new UnitOfMeasureUtils();
038    }
039    
040    public static UnitOfMeasureUtils getInstance() {
041        return UnitOfMeasureUtilsHolder.instance;
042    }
043    
044    private void appendMeasure(UomControl uomControl, Language language, final StringBuilder builder, final UnitOfMeasureType unitOfMeasureType, final long measure) {
045        if(builder.length() > 0)
046            builder.append(", ");
047        
048        builder.append(measure).append(' ');
049        if(measure == 1) {
050            builder.append(uomControl.getBestSingularUnitOfMeasureTypeDescription(unitOfMeasureType, language));
051        } else {
052            builder.append(uomControl.getBestPluralUnitOfMeasureTypeDescription(unitOfMeasureType, language));
053        }
054    }
055    
056    private StringBuilder formatUnitOfMeasure(UomControl uomControl, Language language, StringBuilder builder, UnitOfMeasureType unitOfMeasureType, long measure) {
057        List<UnitOfMeasureEquivalent> unitOfMeasureEquivalents = uomControl.getUnitOfMeasureEquivalentsByToUnitOfMeasureType(unitOfMeasureType);
058        boolean appended = false;
059        
060        for(var unitOfMeasureEquivalent : unitOfMeasureEquivalents) {
061            long toQuantity = unitOfMeasureEquivalent.getToQuantity();
062            
063            if(measure > toQuantity) {
064                long equivMeasure = measure / toQuantity;
065                long remainMeasure = measure % toQuantity;
066                
067                formatUnitOfMeasure(uomControl, language, builder, unitOfMeasureEquivalent.getFromUnitOfMeasureType(), equivMeasure);
068                
069                if(remainMeasure != 0) {
070                    appendMeasure(uomControl, language, builder, unitOfMeasureType, remainMeasure);
071                }
072                
073                appended = true;
074                break;
075            }
076        }
077        
078        if(!appended && measure != 0) {
079            appendMeasure(uomControl, language, builder, unitOfMeasureType, measure);
080        }
081        
082        return builder;
083    }
084    
085    private UnitOfMeasureType getLowestUnitOfMeasureType(UomControl uomControl, UnitOfMeasureType unitOfMeasureType) {
086        List<UnitOfMeasureEquivalent> unitOfMeasureEquivalents = uomControl.getUnitOfMeasureEquivalentsByFromUnitOfMeasureType(unitOfMeasureType);
087        Iterator<UnitOfMeasureEquivalent> iter = unitOfMeasureEquivalents.iterator();
088        
089        if(iter.hasNext()) {
090            UnitOfMeasureEquivalent unitOfMeasureEquivalent = iter.next();
091            
092            unitOfMeasureType = unitOfMeasureEquivalent.getToUnitOfMeasureType();
093        }
094        
095        return unitOfMeasureType;
096    }
097    
098    // TODO: This should have a cache
099    public UnitOfMeasureType getLowestUnitOfMeasureType(UomControl uomControl, UnitOfMeasureKind unitOfMeasureKind) {
100        List<UnitOfMeasureType> unitOfMeasureTypes = uomControl.getUnitOfMeasureTypesByUnitOfMeasureKind(unitOfMeasureKind);
101        Iterator<UnitOfMeasureType> iter = unitOfMeasureTypes.iterator();
102        UnitOfMeasureType unitOfMeasureType = null;
103        
104        if(iter.hasNext()) {
105            unitOfMeasureType = getLowestUnitOfMeasureType(uomControl, iter.next());
106        }
107        
108        return unitOfMeasureType;
109    }
110    
111    public String formatUnitOfMeasure(UserVisit userVisit, UnitOfMeasureKind unitOfMeasureKind, Long measure) {
112        String result = null;
113        
114        if(measure != null) {
115            var uomControl = Session.getModelController(UomControl.class);
116            var userControl = Session.getModelController(UserControl.class);
117            Language language = userControl.getPreferredLanguageFromUserVisit(userVisit);
118            UnitOfMeasureType unitOfMeasureType = getLowestUnitOfMeasureType(uomControl, unitOfMeasureKind);
119            
120            result = formatUnitOfMeasure(uomControl, language, new StringBuilder(), unitOfMeasureType, measure).toString();
121        }
122        
123        return result;
124    }
125    
126}