001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 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.control;
018
019import com.echothree.model.control.core.server.control.CoreControl;
020import com.echothree.model.data.core.server.entity.EntityInstance;
021import com.echothree.util.common.exception.BaseException;
022import com.echothree.util.common.message.Message;
023import com.echothree.util.common.persistence.BasePK;
024import com.echothree.util.server.message.ExecutionErrorAccumulator;
025import com.echothree.util.server.message.SecurityMessageAccumulator;
026import com.echothree.util.server.persistence.BaseEntity;
027import com.echothree.util.server.persistence.Session;
028import com.echothree.util.server.persistence.ThreadSession;
029import java.lang.reflect.InvocationTargetException;
030import javax.inject.Inject;
031
032public abstract class BaseLogic {
033
034    @Inject
035    protected CoreControl coreControl;
036
037    protected BaseLogic() {
038        super();
039    }
040
041    public Session getSession() {
042        return ThreadSession.currentSession();
043    }
044    
045    public void addExecutionError(final ExecutionErrorAccumulator eea, final String key, final Object... values) {
046        if(eea != null) {
047            eea.addExecutionError(key, values);
048        }
049    }
050
051    public void addSecurityMessage(final SecurityMessageAccumulator sma, final String key, final Object... values) {
052        if(sma != null) {
053            sma.addSecurityMessage(key, values);
054        }
055    }
056
057    public EntityInstance getEntityInstanceByBasePK(final BasePK pk) {
058        return coreControl.getEntityInstanceByBasePK(pk);
059    }
060
061    public EntityInstance getEntityInstanceByBaseEntity(final BaseEntity baseEntity) {
062        return coreControl.getEntityInstanceByBaseEntity(baseEntity);
063    }
064
065    // If eea is specified, we'll consider this to be a non-fatal error, and add this error to it. Otherwise, if a BaseException class
066    // is specified, we'll instantiate it and throw it. If neither was specified, the error cannot be handled - abort.
067    public void handleExecutionError(final Class<? extends BaseException> exceptionClass, final ExecutionErrorAccumulator eea, final String key, final Object... values) {
068        var message = new Message(key, values);
069
070        if(eea == null) {
071            if(exceptionClass != null) {
072                try {
073                    throw exceptionClass.getConstructor(Message.class).newInstance(message);
074                } catch (NoSuchMethodException nsme) {
075                    throw new RuntimeException(nsme);
076                } catch (InstantiationException ie) {
077                    throw new RuntimeException(ie);
078                } catch (IllegalAccessException iae) {
079                    throw new RuntimeException(iae);
080                } catch (InvocationTargetException ite) {
081                    throw new RuntimeException(ite);
082                }
083            } else {
084                throw new RuntimeException("BaseException or ExecutionErrorAccumulator must be specified");
085            }
086        } else {
087            eea.addExecutionError(message);
088        }
089    }
090    
091    // If sma is specified, we'll consider this to be a non-fatal error, and add this error to it. Otherwise, if a BaseException class
092    // is specified, we'll instantiate it and throw it. If neither was specified, the error cannot be handled - abort.
093    public void handleSecurityMessage(final Class<? extends BaseException> exceptionClass, final SecurityMessageAccumulator sma, final String key, final Object... values) {
094        var message = new Message(key, values);
095
096        if(sma == null) {
097            if(exceptionClass != null) {
098                try {
099                    throw exceptionClass.getConstructor(Message.class).newInstance(message);
100                } catch (NoSuchMethodException nsme) {
101                    throw new RuntimeException(nsme);
102                } catch (InstantiationException ie) {
103                    throw new RuntimeException(ie);
104                } catch (IllegalAccessException iae) {
105                    throw new RuntimeException(iae);
106                } catch (InvocationTargetException ite) {
107                    throw new RuntimeException(ite);
108                }
109            } else {
110                throw new RuntimeException("BaseException or SecurityMessageAccumulator must be specified");
111            }
112        } else {
113            sma.addSecurityMessage(message);
114        }
115    }
116    
117    // This is only safe to use if all function are using handleError. If eea is null in that case, an Exception will be thrown, and this
118    // code will never be needed. Otherwise, eea will be checked and the value of hasExecutionErrors() returned.
119    public boolean hasExecutionErrors(final ExecutionErrorAccumulator eea) {
120        var hasExecutionErrors = false;
121        
122        if(eea != null) {
123            hasExecutionErrors = eea.hasExecutionErrors();
124        }
125        
126        return hasExecutionErrors;
127    }
128
129}