All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
pl.fhframework.subsystems.Subsystem Maven / Gradle / Ivy
package pl.fhframework.subsystems;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import pl.fhframework.core.FhSubsystemException;
import pl.fhframework.core.FhUseCaseException;
import pl.fhframework.core.events.ISubsystemLifecycleListener;
import pl.fhframework.core.io.FhResource;
import pl.fhframework.core.security.ISystemFunctionsMapper;
import pl.fhframework.core.uc.IInitialUseCase;
import pl.fhframework.core.uc.IUseCase;
import pl.fhframework.ReflectionUtils;
import pl.fhframework.configuration.FHConfiguration;
import pl.fhframework.subsystems.config.SubsystemConfig;
import pl.fhframework.usecases.dynamic.UseCaseProcess;
import pl.fhframework.usecases.dynamic.UseCaseProcessReader;
import java.io.File;
import java.time.Instant;
import java.util.*;
public abstract class Subsystem {
static final SubsystemConfig EMPTY_CONFIG = new SubsystemConfig();
public static final String RESOURCES_DIRECTORY = "dynamicResources";
static final String ACCESS_PRIVATE = "private";
static final String ACCESS_PUBLIC = "public";
@Getter
private String label;
/**
* Subsystem name derived from module.sys file (value of the name attribute from subsystem tag element i.e )
*/
@Getter
private String name;
private String productLabel;
@Getter
private String productUUID;
private String access = ACCESS_PRIVATE;
/**
* Base path to module's xml files (i.e file [C:\home\projects\pojo\docs\target\classes\).
* Potentially this will be an overriden path passed as system property.
*/
@Getter
private FhResource basePath;
/**
* Base path to module's resources path. By default BASE_PATH/resources.
*/
@Getter
private FhResource resourcesPath;
/**
* Base file path to module resources (i.e file [C:\home\projects\pojo\docs\target\classes\).
* This is alway a real (not overriden) URL to class patch resources of this module.
*/
@Getter
private FhResource baseClassPath;
@Setter
@Getter
private FhResource configUrl;
private List _initiateUseCasesHoldersIds = new ArrayList<>();
@Getter
private List initiateUseCasesHoldersIds = Collections.unmodifiableList(_initiateUseCasesHoldersIds);
private Map idPU2SourcePU = new HashMap<>();
@Getter
@Setter
private ISystemFunctionsMapper systemFunctionsMapper;
/**
* Fully qualified names of use cases classes defined in a given module
*/
private Set moduleUseCasesNames = new HashSet<>();
/**
* Module names this module depends on.
*/
private Set dependentModulesNames = new HashSet<>();
@Setter(AccessLevel.PACKAGE)
private SubsystemConfig config;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private Instant configTimestamp;
/**
* Lifecycle listeners
*/
@Getter
private List> lifecycleListeners = new ArrayList<>();
protected Subsystem(String name) {
this(name, name);
}
protected Subsystem(String name, String label) {
this.name = name;
this.label = label;
Optional overridenPath = FHConfiguration.getOverridenSubsystemPath(name, true);
this.basePath = overridenPath.orElse(ReflectionUtils.basePath(this.getClass()));
this.resourcesPath = basePath.resolve(RESOURCES_DIRECTORY);
this.baseClassPath = ReflectionUtils.baseClassPath(this.getClass());
SubsystemConfigUpdater.updateConfigIfNeeded(this);
}
protected Subsystem(String name, String label, FhResource basePath, FhResource overridenResourcesPath, FhResource baseClassPath, String dependentModulesNames) {
this(name, label, null, null, ACCESS_PRIVATE, basePath, overridenResourcesPath, baseClassPath, dependentModulesNames);
}
protected Subsystem(String name, String label, String productLabel, String productUUID, String access, FhResource basePath, FhResource overridenResourcesPath, FhResource baseClassPath, String dependentModulesNames) {
this.name = name;
this.label = label;
this.productLabel = productLabel;
this.productUUID = productUUID;
this.access = access;
this.basePath = basePath;
if (overridenResourcesPath != null) {
this.resourcesPath = overridenResourcesPath;
} else {
this.resourcesPath = basePath.resolve(RESOURCES_DIRECTORY);
}
this.baseClassPath = baseClassPath;
this.dependentModulesNames = parseDependentModules(dependentModulesNames);
SubsystemConfigUpdater.updateConfigIfNeeded(this);
}
private Set parseDependentModules(String dependentModulesNames) {
if (!StringUtils.isEmpty(dependentModulesNames)) {
String[] dependentModules = dependentModulesNames.split(",");
return new HashSet<>(Arrays.asList(dependentModules));
}
return Collections.emptySet();
}
/**
* Returns descriptions of subsystem.
* @return class if subsystem is static, or filePath to *.sys if subsystem is dynamic
*/
public Object getSource(){
return this.getClass();
}
public long getSourceVersion(){
return (new Date()).getTime();
}
public boolean requiresUpdate(){
return false;
}
public String getBasePackage() {
return this.getClass().getPackage().getName();
}
public boolean isStatic() {
return true;
}
public String getProductLabel() {
return StringUtils.isEmpty(productLabel) ? label : productLabel;
}
public UseCaseProcess getUseCaseProcess(String useCaseId) {
try {
Class clazz = Class.forName(useCaseId);
if (IUseCase.class.isAssignableFrom(clazz)) {
return getUseCaseProcess(clazz);
}else{
throw new FhUseCaseException("Class '"+clazz.getName()+"' with id '"+useCaseId+"' is not a Use Case!");
}
} catch (ClassNotFoundException e) {
String ducFilePath = getSubsystemResourcePath(useCaseId, ".duc");
return getUseCaseProcess(ducFilePath, useCaseId);
}
}
private UseCaseProcess getUseCaseProcess(String ducFilePath, String useCaseId) {
if (ducFilePath == null){
throw new FhSubsystemException("Error while configure subsystem described by '" + getSource() + "' - couldn't find static class '" + useCaseId + "' or path to dynamic file!");
}
File file = new File(ducFilePath);
if (file.exists() && file.isFile()) {
return UseCaseProcessReader.instance.read(file);
} else {
throw new FhSubsystemException("Error while configure subsystem described by '" + getSource() + "' - couldn't find file '" + ducFilePath + "' or static class '" + useCaseId + "'");
}
}
public UseCaseProcess getUseCaseProcess(Class useCaseId){
//TODO: implement.
throw new FhSubsystemException("Functionality of indicating static use cases in dynamic subsystem is not implemented!");
}
private final Map idSource2Path = new HashMap<>();
private String getSubsystemResourcePath(String resourceId, String resourceType) {
String returnedValue = idSource2Path.get(resourceId);
if (returnedValue==null && !idSource2Path.containsKey(resourceId)) {
returnedValue = basePath.toExternalPath();
idSource2Path.put(resourceId, returnedValue);
}
return returnedValue;
}
@Override
public String toString() {
return getSource()+"{" +
"label='" + label + '\'' +
'}';
}
public void addStaticUseCaseReference(Class reference) {
String id = reference.getName();
_initiateUseCasesHoldersIds.add(id);
idPU2SourcePU.put(id, reference);
}
public void addUseCaseReference(String reference){
_initiateUseCasesHoldersIds.add(reference);
try{
Class staticClazz = (Class) Class.forName(reference);
idPU2SourcePU.put(reference, staticClazz);
} catch (ClassNotFoundException e) {
//Calculating path of described dynamic PU with given id.
String PPUFilePath = getSubsystemResourcePath(reference, ".duc");
idPU2SourcePU.put(reference, PPUFilePath);
}
}
public Object getUseCaseSource(String useCaseId){
return idPU2SourcePU.get(useCaseId);
}
private Map _classCache = new HashMap<>();
public List> getStaticUseCaseInitializersList() {
List> result = new ArrayList<>();
for (String idPU : _initiateUseCasesHoldersIds) {
Object source = getUseCaseSource(idPU);
if (source instanceof Class){
Class clazz = (Class) source;
if (IInitialUseCase.class.isAssignableFrom(clazz)) {
result.add((Class) clazz);
}
}
}
return result;
}
/**
* Adds a lifecycle listener
* @param listenerClass listener class
*/
public void addlifecycleListener(Class listenerClass) {
this.lifecycleListeners.add(listenerClass);
}
/**
* Add given use case class to given subsystem use case registry
* @param useCaseClazz use case class
*/
public void addUseCase(Class useCaseClazz) {
moduleUseCasesNames.add(useCaseClazz.getName());
}
/**
* Return unmodifiable view of module use cases
* @return module use cases
*/
public Set getModuleUseCasesNames() {
return Collections.unmodifiableSet(moduleUseCasesNames);
}
/**
* Returns true if this module contains use case with the specified name.
*
* @param fullyQualifiedUseCaseClassName use case name
* @return true if this module contains the specified use case
*/
public boolean containsUseCase(String fullyQualifiedUseCaseClassName) {
return moduleUseCasesNames.contains(fullyQualifiedUseCaseClassName);
}
/**
* Return unmodifiable view of dependent module names this module depends on
* @return dependent module names
*/
public Set getDependentModulesNames() {
return Collections.unmodifiableSet(dependentModulesNames);
}
/**
* Returns subsystem's configuration that is kept in module.xml file and may change at runtime.
* @return subsystem's configuration
*/
public SubsystemConfig getConfig() {
if (config == null) {
return EMPTY_CONFIG;
} else {
return config;
}
}
public boolean isPublic() {
return ACCESS_PUBLIC.equals(access);
}
}