li.strolch.search.StrolchSearch Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of agent Show documentation
Show all versions of agent Show documentation
Strolch Agent which is the runtime for Strolch
The newest version!
package li.strolch.search;
import static li.strolch.model.StrolchModelConstants.INTERNAL;
import static li.strolch.model.Tags.AGENT;
import java.util.Collection;
import java.util.ResourceBundle;
import java.util.stream.Stream;
import li.strolch.exception.StrolchAccessDeniedException;
import li.strolch.handler.operationslog.OperationsLog;
import li.strolch.model.Locator;
import li.strolch.model.StrolchModelConstants;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.log.LogMessage;
import li.strolch.model.log.LogMessageState;
import li.strolch.model.log.LogSeverity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.model.Restrictable;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.utils.I18nMessage;
import li.strolch.utils.dbc.DBC;
/**
* Class to perform searches on Strolch elements
*
* @param
*/
public abstract class StrolchSearch
implements SearchExpressions, SearchPredicates, Restrictable {
private String privilegeValue;
private SearchExpression expression;
public StrolchSearch() {
this.privilegeValue = getClass().getName();
}
protected abstract SearchNavigator getNavigator();
/**
* Used to configure the navigator, i.e. which type
of root elements are to be queried
*
* @param types the types of elements to search
*
* @return this for chaining
*/
public abstract StrolchSearch types(String... types);
/**
* Allows to implement the search expression in one method, or to prepare a project specific search expression
*/
protected void define() {
// default is no-op
}
/**
* Adds the given {@link SearchExpression} to the current search
*
* @param expression the {@link SearchExpression} to add to this search
*
* @return this for chaining
*/
public StrolchSearch where(SearchExpression expression) {
if (this.expression == null)
this.expression = expression;
else
this.expression = this.expression.and(expression);
return this;
}
/**
* Marks this search as an internal search, thus allowing it to be performed without the authenticated user having
* the specific privilege, provided the {@link StrolchModelConstants#INTERNAL} flag is on the search privilege
*
* @return this object for chaining
*/
public StrolchSearch internal() {
this.privilegeValue = INTERNAL;
return this;
}
/**
* Performs the actual search, by first validating the privilege context
*
* @param tx the TX on which to perform the search
*
* @return the search result
*/
public abstract RootElementSearchResult search(StrolchTransaction tx);
protected Stream prepareSearch(StrolchTransaction tx) {
try {
tx.getPrivilegeContext().validateAction(this);
} catch (AccessDeniedException e) {
String username = tx.getUsername();
if (tx.getContainer().hasComponent(OperationsLog.class)) {
String realmName = tx.getRealmName();
String searchName = this.privilegeValue.equals(INTERNAL) ? (getClass().getName() + " (INTERNAL)") :
this.privilegeValue;
LogMessage logMessage = new LogMessage(realmName, username,
Locator.valueOf(AGENT, PrivilegeHandler.class.getSimpleName(), getPrivilegeName(), searchName),
LogSeverity.Exception, LogMessageState.Information, ResourceBundle.getBundle("strolch-agent"),
"agent.search.failed.access.denied").value("user", username).value("search", searchName)
.withException(e);
OperationsLog operationsLog = tx.getContainer().getComponent(OperationsLog.class);
operationsLog.addMessage(logMessage);
}
String searchName = this.privilegeValue.equals(INTERNAL) ? (getClass().getSimpleName() + " (INTERNAL)") :
getClass().getSimpleName();
I18nMessage i18n = new I18nMessage(
ResourceBundle.getBundle("strolch-agent", tx.getCertificate().getLocale()),
"agent.search.failed.access.denied").value("user", username).value("search", searchName);
throw new StrolchAccessDeniedException(tx.getCertificate(), this, i18n, e);
}
// first prepare
define();
// then validate navigator
DBC.PRE.assertNotNull("navigation not set! Call types()", getNavigator());
Stream stream = getNavigator().navigate(tx);
if (this.expression != null)
stream = stream.filter(e -> this.expression.matches(e));
return stream;
}
/**
* Performs the actual search on the given input list
*
* @return the search result
*/
public RootElementSearchResult search(Collection input) {
// first prepare
define();
Stream stream = input.stream();
if (this.expression != null)
stream = stream.filter(e -> this.expression.matches(e));
return new RootElementSearchResult<>(stream);
}
/**
* Performs the actual search on the given input stream
*
* @return the search result
*/
public RootElementSearchResult search(Stream input) {
// first prepare
define();
Stream stream = input;
if (this.expression != null)
stream = stream.filter(e -> this.expression.matches(e));
return new RootElementSearchResult<>(stream);
}
/**
* @see li.strolch.privilege.model.Restrictable#getPrivilegeName()
*/
@Override
public String getPrivilegeName() {
return StrolchSearch.class.getName();
}
/**
* @see li.strolch.privilege.model.Restrictable#getPrivilegeValue()
*/
@Override
public Object getPrivilegeValue() {
return this.privilegeValue;
}
}