ref 11741: DataMiner - Add refresh button in operators panel
https://support.d4science.org/issues/11741 Operators refresh support is added git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-analysis/data-miner-manager-cl@167359 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
13752b61d5
commit
22b3cff88b
|
@ -2,6 +2,7 @@
|
||||||
<Changeset component="org.gcube.data.analysis.data-miner-manager-cl.1-4-0"
|
<Changeset component="org.gcube.data.analysis.data-miner-manager-cl.1-4-0"
|
||||||
date="2018-04-03">
|
date="2018-04-03">
|
||||||
<Change>Updated to support netcdf files</Change>
|
<Change>Updated to support netcdf files</Change>
|
||||||
|
<Change>Added support for operators refresh[ticket #11741]</Change>
|
||||||
</Changeset>
|
</Changeset>
|
||||||
<Changeset component="org.gcube.data.analysis.data-miner-manager-cl.1-3-0"
|
<Changeset component="org.gcube.data.analysis.data-miner-manager-cl.1-3-0"
|
||||||
date="2017-06-12">
|
date="2017-06-12">
|
||||||
|
|
|
@ -37,6 +37,17 @@ public abstract class SClient implements Serializable {
|
||||||
*/
|
*/
|
||||||
public abstract List<OperatorsClassification> getOperatorsClassifications() throws Exception;
|
public abstract List<OperatorsClassification> getOperatorsClassifications() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the list of operators and refresh them if required
|
||||||
|
*
|
||||||
|
* @param refresh
|
||||||
|
* refresh operators in cache
|
||||||
|
* @return list of operators classification
|
||||||
|
* @throws Exception
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
public abstract List<OperatorsClassification> getOperatorsClassifications(boolean refresh) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the operator by id
|
* Retrieve the operator by id
|
||||||
*
|
*
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.gcube.data.analysis.dataminermanagercl.shared.parameters.FileParamete
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.ObjectParameter;
|
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.ObjectParameter;
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.Parameter;
|
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.Parameter;
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.TabularListParameter;
|
import org.gcube.data.analysis.dataminermanagercl.shared.parameters.TabularListParameter;
|
||||||
|
import org.gcube.data.analysis.dataminermanagercl.shared.perspective.PerspectiveType;
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.process.ComputationStatus;
|
import org.gcube.data.analysis.dataminermanagercl.shared.process.ComputationStatus;
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.process.ComputationStatus.Status;
|
import org.gcube.data.analysis.dataminermanagercl.shared.process.ComputationStatus.Status;
|
||||||
import org.gcube.data.analysis.dataminermanagercl.shared.process.Operator;
|
import org.gcube.data.analysis.dataminermanagercl.shared.process.Operator;
|
||||||
|
@ -269,11 +270,16 @@ public class SClient4WPS extends SClient {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<OperatorsClassification> getOperatorsClassifications() throws ServiceException {
|
public List<OperatorsClassification> getOperatorsClassifications() throws ServiceException {
|
||||||
|
return getOperatorsClassifications(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OperatorsClassification> getOperatorsClassifications(boolean refresh) throws ServiceException{
|
||||||
|
logger.debug("getOperatorsClassifications: "+refresh);
|
||||||
LinkedHashMap<String, String> operatorsToCategoriesMap = new LinkedHashMap<>();
|
LinkedHashMap<String, String> operatorsToCategoriesMap = new LinkedHashMap<>();
|
||||||
LinkedHashMap<String, List<Operator>> categoriesToOperatorsMap = new LinkedHashMap<>();
|
LinkedHashMap<String, List<Operator>> categoriesToOperatorsMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
requestCapability();
|
requestCapability(refresh);
|
||||||
if (processesBriefs == null || processesDescriptionType == null) {
|
if (processesBriefs == null || processesDescriptionType == null) {
|
||||||
throw new ServiceException("Algorithms WPS not available!");
|
throw new ServiceException("Algorithms WPS not available!");
|
||||||
}
|
}
|
||||||
|
@ -348,14 +354,15 @@ public class SClient4WPS extends SClient {
|
||||||
|
|
||||||
List<OperatorsClassification> operatorsClass = new ArrayList<>();
|
List<OperatorsClassification> operatorsClass = new ArrayList<>();
|
||||||
|
|
||||||
OperatorsClassification op = new OperatorsClassification(Constants.UserClassificationName, categories,
|
OperatorsClassification op = new OperatorsClassification(PerspectiveType.User.getPerspective(), categories,
|
||||||
operators);
|
operators);
|
||||||
|
|
||||||
operatorsClass.add(op);
|
operatorsClass.add(op);
|
||||||
|
|
||||||
// logger.debug("OperatorClass: " + operatorsClass);
|
logger.debug("OperatorClass: " + operatorsClass);
|
||||||
return operatorsClass;
|
return operatorsClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ProcessInformations describeProcess(String processId) throws ServiceException {
|
private ProcessInformations describeProcess(String processId) throws ServiceException {
|
||||||
return describeProcess(processId, null);
|
return describeProcess(processId, null);
|
||||||
|
@ -418,7 +425,7 @@ public class SClient4WPS extends SClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestCapability() throws ServiceException {
|
private void requestCapability(boolean refresh) throws ServiceException {
|
||||||
SClient4WPSSession wpsClient = null;
|
SClient4WPSSession wpsClient = null;
|
||||||
processesDescriptionType = null;
|
processesDescriptionType = null;
|
||||||
processesBriefs = null;
|
processesBriefs = null;
|
||||||
|
@ -426,7 +433,7 @@ public class SClient4WPS extends SClient {
|
||||||
try {
|
try {
|
||||||
wpsClient = createWPSClientSession();
|
wpsClient = createWPSClientSession();
|
||||||
|
|
||||||
wpsClient.connect(wpsProcessingServlet);
|
wpsClient.connect(wpsProcessingServlet,refresh);
|
||||||
|
|
||||||
processesDescriptionType = wpsClient.getAllProcessDescriptions(wpsProcessingServlet);
|
processesDescriptionType = wpsClient.getAllProcessDescriptions(wpsProcessingServlet);
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,10 @@ public class SClient4WPSSession implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Initializes a WPS client session.
|
* Initializes a WPS client session.
|
||||||
*
|
*
|
||||||
* @param user user
|
* @param user
|
||||||
* @param password password
|
* user
|
||||||
|
* @param password
|
||||||
|
* password
|
||||||
*/
|
*/
|
||||||
public SClient4WPSSession(String user, String password) {
|
public SClient4WPSSession(String user, String password) {
|
||||||
super();
|
super();
|
||||||
|
@ -94,35 +96,75 @@ public class SClient4WPSSession implements Serializable {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public boolean connect(String url) throws WPSClientException {
|
public boolean connect(String url) throws WPSClientException {
|
||||||
|
return connect(url, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean connect(String url, boolean refresh) throws WPSClientException {
|
||||||
logger.info("CONNECT: " + url);
|
logger.info("CONNECT: " + url);
|
||||||
logger.debug("LoggedSevices: " + loggedServices.keySet());
|
logger.info("Service refresh: " + refresh);
|
||||||
if (loggedServices.containsKey(url)) {
|
if (refresh) {
|
||||||
logger.debug("Service already registered: " + url);
|
logger.debug("LoggedServices: " + loggedServices.keySet());
|
||||||
|
if (loggedServices.containsKey(url)) {
|
||||||
|
loggedServices.remove(url);
|
||||||
|
}
|
||||||
|
if(processDescriptions.containsKey(url)){
|
||||||
|
processDescriptions.remove(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
CapabilitiesDocument capsDoc = retrieveCapsViaGET(url);
|
||||||
|
if (capsDoc != null) {
|
||||||
|
logger.debug("Adding caps to logged services " + url);
|
||||||
|
loggedServices.put(url, capsDoc);
|
||||||
|
logger.debug("Logged Services key: " + loggedServices.keySet());
|
||||||
|
} else {
|
||||||
|
logger.error("CapsDoc is null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessDescriptionsDocument processDescs = describeAllProcesses(url);
|
||||||
|
if (processDescs != null && capsDoc != null) {
|
||||||
|
logger.debug("Adding processes descriptions to logged services " + url);
|
||||||
|
processDescriptions.put(url, processDescs);
|
||||||
|
logger.debug("ProcessDescriptions key: " + processDescriptions.keySet());
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger.error("ProcessDescs is null!");
|
||||||
|
}
|
||||||
|
logger.warn("retrieving caps failed, caps are null");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
logger.debug("LoggedServices: " + loggedServices.keySet());
|
||||||
|
boolean registered = loggedServices.containsKey(url);
|
||||||
|
if (registered) {
|
||||||
|
logger.debug("Service already registered: " + url);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
logger.debug("Service not registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
CapabilitiesDocument capsDoc = retrieveCapsViaGET(url);
|
||||||
|
if (capsDoc != null) {
|
||||||
|
logger.debug("Adding caps to logged services " + url);
|
||||||
|
loggedServices.put(url, capsDoc);
|
||||||
|
logger.debug("Logged Services key: " + loggedServices.keySet());
|
||||||
|
} else {
|
||||||
|
logger.error("CapsDoc is null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessDescriptionsDocument processDescs = describeAllProcesses(url);
|
||||||
|
if (processDescs != null && capsDoc != null) {
|
||||||
|
logger.debug("Adding processes descriptions to logged services " + url);
|
||||||
|
processDescriptions.put(url, processDescs);
|
||||||
|
logger.debug("ProcessDescriptions key: " + processDescriptions.keySet());
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger.error("ProcessDescs is null!");
|
||||||
|
}
|
||||||
|
logger.warn("retrieving caps failed, caps are null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
logger.debug("Service not registered");
|
|
||||||
CapabilitiesDocument capsDoc = retrieveCapsViaGET(url);
|
|
||||||
if (capsDoc != null) {
|
|
||||||
logger.debug("Adding caps to logged services " + url);
|
|
||||||
loggedServices.put(url, capsDoc);
|
|
||||||
logger.debug("Logged Services key: " + loggedServices.keySet());
|
|
||||||
} else {
|
|
||||||
logger.error("CapsDoc is null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessDescriptionsDocument processDescs = describeAllProcesses(url);
|
|
||||||
if (processDescs != null && capsDoc != null) {
|
|
||||||
logger.debug("Adding processes descriptions to logged services " + url);
|
|
||||||
processDescriptions.put(url, processDescs);
|
|
||||||
logger.debug("ProcessDescriptions key: " + processDescriptions.keySet());
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logger.error("ProcessDescs is null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.warn("retrieving caps failed, caps are null");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,7 +238,8 @@ public class SClient4WPSSession implements Serializable {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* IOException
|
* IOException
|
||||||
*/
|
*/
|
||||||
private ProcessDescriptionsDocument getProcessDescriptionsFromCache(String wpsUrl) throws IOException {
|
private ProcessDescriptionsDocument getProcessDescriptionsFromCache(String wpsUrl)
|
||||||
|
throws IOException {
|
||||||
if (!descriptionsAvailableInCache(wpsUrl)) {
|
if (!descriptionsAvailableInCache(wpsUrl)) {
|
||||||
try {
|
try {
|
||||||
connect(wpsUrl);
|
connect(wpsUrl);
|
||||||
|
@ -329,7 +372,8 @@ public class SClient4WPSSession implements Serializable {
|
||||||
* true if is raw data
|
* true if is raw data
|
||||||
* @return either an ExecuteResponseDocument or an InputStream if asked for
|
* @return either an ExecuteResponseDocument or an InputStream if asked for
|
||||||
* RawData or an Exception Report
|
* RawData or an Exception Report
|
||||||
* @throws WPSClientException WPSClientException
|
* @throws WPSClientException
|
||||||
|
* WPSClientException
|
||||||
*/
|
*/
|
||||||
private Object execute(String serverID, ExecuteDocument execute, boolean rawData) throws WPSClientException {
|
private Object execute(String serverID, ExecuteDocument execute, boolean rawData) throws WPSClientException {
|
||||||
CapabilitiesDocument caps = loggedServices.get(serverID);
|
CapabilitiesDocument caps = loggedServices.get(serverID);
|
||||||
|
@ -376,7 +420,7 @@ public class SClient4WPSSession implements Serializable {
|
||||||
logger.debug("retrieveCapsViaGET: " + url);
|
logger.debug("retrieveCapsViaGET: " + url);
|
||||||
ClientCapabiltiesRequest req = new ClientCapabiltiesRequest();
|
ClientCapabiltiesRequest req = new ClientCapabiltiesRequest();
|
||||||
url = req.getRequest(url);
|
url = req.getRequest(url);
|
||||||
|
logger.debug("url req: "+url);
|
||||||
try {
|
try {
|
||||||
String authString = user + ":" + password;
|
String authString = user + ":" + password;
|
||||||
logger.debug("auth string: " + authString);
|
logger.debug("auth string: " + authString);
|
||||||
|
@ -389,18 +433,19 @@ public class SClient4WPSSession implements Serializable {
|
||||||
connection.setRequestMethod("GET");
|
connection.setRequestMethod("GET");
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
connection.setRequestProperty("Authorization", "Basic " + encoded);
|
connection.setRequestProperty("Authorization", "Basic " + encoded);
|
||||||
|
logger.debug("Request: "+connection.toString());
|
||||||
InputStream is = connection.getInputStream();
|
InputStream is = connection.getInputStream();
|
||||||
Document doc = checkInputStream(is);
|
Document doc = checkInputStream(is);
|
||||||
CapabilitiesDocument capabilitiesDocument = CapabilitiesDocument.Factory.parse(doc, options);
|
CapabilitiesDocument capabilitiesDocument = CapabilitiesDocument.Factory.parse(doc, options);
|
||||||
return capabilitiesDocument;
|
return capabilitiesDocument;
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
e.printStackTrace();
|
logger.error(e.getLocalizedMessage(),e);
|
||||||
throw new WPSClientException("Capabilities URL seems to be unvalid: " + url, e);
|
throw new WPSClientException("Capabilities URL seems to be unvalid: " + url, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error(e.getLocalizedMessage(),e);
|
||||||
throw new WPSClientException("Error occured while retrieving capabilities from url: " + url, e);
|
throw new WPSClientException("Error occured while retrieving capabilities from url: " + url, e);
|
||||||
} catch (XmlException e) {
|
} catch (XmlException e) {
|
||||||
e.printStackTrace();
|
logger.error(e.getLocalizedMessage(),e);
|
||||||
throw new WPSClientException("Error occured while parsing XML", e);
|
throw new WPSClientException("Error occured while parsing XML", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,16 +504,17 @@ public class SClient4WPSSession implements Serializable {
|
||||||
return processDescriptionsDocument;
|
return processDescriptionsDocument;
|
||||||
|
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
logger.error("URL seems not to be valid: "+e.getLocalizedMessage(),e);
|
logger.error("URL seems not to be valid: " + e.getLocalizedMessage(), e);
|
||||||
throw new WPSClientException("URL seems not to be valid: "+e.getLocalizedMessage(), e);
|
throw new WPSClientException("URL seems not to be valid: " + e.getLocalizedMessage(), e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("Error occured while receiving data: "+e.getLocalizedMessage(),e);
|
logger.error("Error occured while receiving data: " + e.getLocalizedMessage(), e);
|
||||||
throw new WPSClientException("Error occured while receiving data: "+e.getLocalizedMessage(), e);
|
throw new WPSClientException("Error occured while receiving data: " + e.getLocalizedMessage(), e);
|
||||||
} catch (XmlException e) {
|
} catch (XmlException e) {
|
||||||
logger.error("Error occured while parsing ProcessDescription document: "+e.getLocalizedMessage(),e);
|
logger.error("Error occured while parsing ProcessDescription document: " + e.getLocalizedMessage(), e);
|
||||||
throw new WPSClientException("Error occured while parsing ProcessDescription document: "+e.getLocalizedMessage(), e);
|
throw new WPSClientException(
|
||||||
|
"Error occured while parsing ProcessDescription document: " + e.getLocalizedMessage(), e);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.error(e.getLocalizedMessage(),e);
|
logger.error(e.getLocalizedMessage(), e);
|
||||||
throw new WPSClientException(e.getLocalizedMessage(), new Exception(e));
|
throw new WPSClientException(e.getLocalizedMessage(), new Exception(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,7 +583,7 @@ public class SClient4WPSSession implements Serializable {
|
||||||
|
|
||||||
URL url = new URL(urlString);
|
URL url = new URL(urlString);
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
conn.setRequestMethod("POST");
|
conn.setRequestMethod("POST");
|
||||||
conn.setRequestProperty("Authorization", "Basic " + encoded);
|
conn.setRequestProperty("Authorization", "Basic " + encoded);
|
||||||
conn.setRequestProperty("Accept-Encoding", "gzip");
|
conn.setRequestProperty("Accept-Encoding", "gzip");
|
||||||
|
@ -550,7 +596,7 @@ public class SClient4WPSSession implements Serializable {
|
||||||
logger.debug("Read encoding GZIP");
|
logger.debug("Read encoding GZIP");
|
||||||
input = new GZIPInputStream(conn.getInputStream());
|
input = new GZIPInputStream(conn.getInputStream());
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Read encoding: "+encoding);
|
logger.debug("Read encoding: " + encoding);
|
||||||
input = conn.getInputStream();
|
input = conn.getInputStream();
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
|
|
|
@ -16,13 +16,6 @@ public class Constants {
|
||||||
|
|
||||||
public static final String DATAMINER_SERVICE_CATEGORY = "DataAnalysis";
|
public static final String DATAMINER_SERVICE_CATEGORY = "DataAnalysis";
|
||||||
public static final String DATA_MINER_SERVICE_NAME = "DataMiner";
|
public static final String DATA_MINER_SERVICE_NAME = "DataMiner";
|
||||||
|
|
||||||
|
|
||||||
public static final String[] ClassificationNames = { "User Perspective" };
|
|
||||||
// "Computation Perspective"};
|
|
||||||
public static final String UserClassificationName = ClassificationNames[0];
|
|
||||||
// public final static String computationClassificationName =
|
|
||||||
// classificationNames[1];
|
|
||||||
|
|
||||||
// WPS Data Miner
|
// WPS Data Miner
|
||||||
public static final String WPSWebProcessingService = "WebProcessingService";
|
public static final String WPSWebProcessingService = "WebProcessingService";
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.gcube.data.analysis.dataminermanagercl.shared.perspective;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Giancarlo Panichi
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum PerspectiveType {
|
||||||
|
|
||||||
|
User("User", "User Perspective"), Computation("Computation", "Computation Persperctive");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param label
|
||||||
|
* label
|
||||||
|
*/
|
||||||
|
private PerspectiveType(final String label, final String perspective) {
|
||||||
|
this.label = label;
|
||||||
|
this.perspective = perspective;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String label;
|
||||||
|
private final String perspective;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PerspectiveType [label=" + label + ", perspective=" + perspective + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPerspective() {
|
||||||
|
return perspective;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PerspectiveType getFromLabel(String label) {
|
||||||
|
if (label == null || label.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (PerspectiveType type : values()) {
|
||||||
|
if (type.label.compareToIgnoreCase(label) == 0) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PerspectiveType getFromPerspective(String perspective) {
|
||||||
|
if (perspective == null || perspective.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (PerspectiveType type : values()) {
|
||||||
|
if (type.perspective.compareToIgnoreCase(perspective) == 0) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<PerspectiveType> asList() {
|
||||||
|
List<PerspectiveType> list = Arrays.asList(values());
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue