From bd3e4778c0f56255b2432ebba17f52e4cc7b055f Mon Sep 17 00:00:00 2001 From: Benjamin Phillippe Date: Wed, 6 Nov 2013 14:02:10 -0600 Subject: [PATCH] Issue #1678 Added support for stored query publishing and invocation on the registry Change-Id: Ia06e5e674a2ce7d0fe7e5cb9d23cce6e2237545f Former-commit-id: 0abf4050148a9bfb47d32b927697f829fdd65e6d [formerly b84235a80a35572d6a868aee11b8f6c616ef44df] [formerly b5db1f38c397b7684079e4311a67aea97b0109d4 [formerly d7d985926351d933c0bd10a3a5fd88ef4305853b]] Former-commit-id: b5db1f38c397b7684079e4311a67aea97b0109d4 Former-commit-id: 1a492a564b7fd5de8bfcf47abbd4c67e4a3759f5 --- .../web/IRegistryDataAccessService.java | 10 + .../constants/CanonicalQueryTypes.java | 21 +- .../res/spring/webservices.xml | 5 + .../web/RegistryDataAccessService.java | 12 + .../web/RegistryQueryDefinitionService.java | 201 ++++++++++++++++ ...raytheon.uf.edex.registry.ebxml.properties | 2 +- .../services/query/RegistryQueryUtil.java | 25 ++ .../web/registry/federation/status.html | 40 +++- .../web/registry/navigation.html | 2 + .../web/registry/registryUtil.js | 32 ++- .../registry/services/query/DefineQuery.html | 215 ++++++++++++++++++ 11 files changed, 554 insertions(+), 11 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryQueryDefinitionService.java create mode 100644 edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/services/query/DefineQuery.html diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/web/IRegistryDataAccessService.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/web/IRegistryDataAccessService.java index 2b7f9ef988..ffaba2126d 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/web/IRegistryDataAccessService.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/web/IRegistryDataAccessService.java @@ -41,6 +41,7 @@ import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResp * 10/8/2013 1682 bphillip Added rest functions for use with the query web interface * 10/23/2013 2385 bphillip restoreSubscriptions throws JAXBException * 10/30/2013 1538 bphillip Moved data delivery specific servics out of registry plugin + * 11/7/2013 1678 bphillip Added get custom query method * * * @author bphillip @@ -73,6 +74,15 @@ public interface IRegistryDataAccessService { @Path("getQueries") public String getValidQueries(); + /** + * Gets the list of non-canonical query types contained in the registry + * + * @return The non-canonical query definitions + */ + @GET + @Path("getCustomQueries") + public String getCustomQueries(); + /** * Gets the valid parameters for a given query definition * diff --git a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/constants/CanonicalQueryTypes.java b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/constants/CanonicalQueryTypes.java index 8a91645569..a2f9158e97 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/constants/CanonicalQueryTypes.java +++ b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/constants/CanonicalQueryTypes.java @@ -19,6 +19,9 @@ **/ package com.raytheon.uf.common.registry.constants; +import java.util.Arrays; +import java.util.List; + /** * * Registry canonical query types @@ -31,6 +34,7 @@ package com.raytheon.uf.common.registry.constants; * ------------ ---------- ----------- -------------------------- * 4/9/2013 1802 bphillip Initial implementation * 9/18/2013 1705 bphillip Added GetReferencedObject canonical query + * 11/7/2013 1678 bphillip Added list of all canonical query types * * * @author bphillip @@ -50,20 +54,14 @@ public class CanonicalQueryTypes { public static final String GET_CLASSIFICATION_SCHEMES_BY_ID = "urn:oasis:names:tc:ebxml-regrep:query:GetClassificationSchemesById"; - public static final String EXPORT_OBJECT = "urn:oasis:names:tc:ebxml-regrep:query:ExportObject"; - public static final String GET_CHILDREN_BY_PARENT_ID = "urn:oasis:names:tc:ebxml-regrep:query:GetChildrenByParentId"; public static final String GET_REGISTRY_PACKAGES_BY_MEMBER_ID = "urn:oasis:names:tc:ebxml-regrep:query:GetRegistryPackagesByMemberId"; - public static final String FIND_ALL_MY_OBJECTS = "urn:oasis:names:tc:ebxml-regrep:query:FindAllMyObjects"; - public static final String GARBAGE_COLLECTOR = "urn:oasis:names:tc:ebxml-regrep:query:GarbageCollector"; public static final String BASIC_QUERY = "urn:oasis:names:tc:ebxml-regrep:query:BasicQuery"; - public static final String EXTRINSIC_OBJECT_QUERY = "urn:oasis:names:tc:ebxml-regrep:query:ExtrinsicObjectQuery"; - public static final String FIND_ASSOCIATIONS = "urn:oasis:names:tc:ebxml-regrep:query:FindAssociations"; public static final String FIND_ASSOCIATED_OBJECTS = "urn:oasis:names:tc:ebxml-regrep:query:FindAssociatedObjects"; @@ -80,4 +78,15 @@ public class CanonicalQueryTypes { public static final String GET_REFERENCED_OBJECT = "urn:oasis:names:tc:ebxml-regrep:query:GetReferencedObject"; + public static final List CANONICAL_QUERY_TYPES = Arrays + .asList(new String[] { GET_OBJECT_BY_ID, GET_OBJECTS_BY_LID, + GET_AUDIT_TRAIL_BY_LID, GET_AUDIT_TRAIL_BY_TIME_INTERVAL, + GET_AUDIT_TRAIL_BY_ID, GET_CLASSIFICATION_SCHEMES_BY_ID, + GET_CHILDREN_BY_PARENT_ID, + GET_REGISTRY_PACKAGES_BY_MEMBER_ID, GARBAGE_COLLECTOR, + BASIC_QUERY, FIND_ASSOCIATIONS, FIND_ASSOCIATED_OBJECTS, + ADHOC_QUERY, KEYWORD_SEARCH, REGISTRY_PACKAGE_SELECTOR, + CLASSIFICATION_SCHEME_SELECTOR, GET_NOTIFICATION, + GET_REFERENCED_OBJECT }); + } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/res/spring/webservices.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/res/spring/webservices.xml index da959022fa..88515e0fff 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/res/spring/webservices.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/res/spring/webservices.xml @@ -31,6 +31,10 @@ + + + + @@ -42,6 +46,7 @@ + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryDataAccessService.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryDataAccessService.java index facfc8c8ca..ff1c5e77a9 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryDataAccessService.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryDataAccessService.java @@ -50,6 +50,7 @@ import org.springframework.transaction.annotation.Transactional; import com.raytheon.uf.common.datadelivery.registry.web.IRegistryDataAccessService; import com.raytheon.uf.common.registry.RegistryException; +import com.raytheon.uf.common.registry.constants.CanonicalQueryTypes; import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResponse; import com.raytheon.uf.common.serialization.JAXBManager; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -60,6 +61,7 @@ import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.registry.ebxml.dao.QueryDefinitionDao; import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao; +import com.raytheon.uf.edex.registry.ebxml.services.query.RegistryQueryUtil; /** * @@ -75,6 +77,7 @@ import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao; * 9/20/2013 2385 bphillip Added subscription backup functions * 10/2/2013 2385 bphillip Fixed subscription backup queries * 10/8/2013 1682 bphillip Added query queries + * 11/7/2013 1678 bphillip Added getCustomQueries method * * * @author bphillip @@ -147,6 +150,15 @@ public class RegistryDataAccessService implements IRegistryDataAccessService { return builder.toString(); } + @Override + @GET + @Path("getCustomQueries") + public String getCustomQueries() { + List ids = queryDefinitionDao.getQueryIds(); + ids.removeAll(CanonicalQueryTypes.CANONICAL_QUERY_TYPES); + return RegistryQueryUtil.formatArrayString(ids.toArray()); + } + @Override @GET @Path("getParametersForQuery/{queryId}") diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryQueryDefinitionService.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryQueryDefinitionService.java new file mode 100644 index 0000000000..58180a4510 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/web/RegistryQueryDefinitionService.java @@ -0,0 +1,201 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.datadelivery.registry.web; + +import java.math.BigInteger; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.InternationalStringType; +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ParameterType; +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.QueryDefinitionType; +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType; +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.StringQueryExpressionType; + +import org.springframework.transaction.annotation.Transactional; + +import com.raytheon.uf.common.registry.constants.CanonicalQueryTypes; +import com.raytheon.uf.common.registry.constants.RegistryObjectTypes; +import com.raytheon.uf.common.registry.constants.StatusTypes; +import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao; +import com.raytheon.uf.edex.registry.ebxml.services.query.RegistryQueryUtil; +import com.raytheon.uf.edex.registry.ebxml.services.query.RegistryQueryUtil.PARAMETER_DATA_TYPE; + +/** + * + * REST Services used to manage registry query definitions + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 11/7/2013     1678       bphillip    Initial Creation
+ * 
+ * + * @author bphillip + * @version 1 + **/ +@Path(RegistryQueryDefinitionService.REGISTRY_DEFINE_QUERY_PATH) +@Transactional +public class RegistryQueryDefinitionService { + + /** The path to this set of services */ + protected static final String REGISTRY_DEFINE_QUERY_PATH = "/defineQuery/"; + + /** Data access object for registry objects */ + private RegistryObjectDao registryObjectDao; + + /** + * Gets the valid data types for query parameters + * + * @return The valid parameter data types + */ + @GET + @Path("getParameterDataTypes") + public String getParameterDataTypes() { + return RegistryQueryUtil + .formatArrayString(PARAMETER_DATA_TYPE.values()); + } + + /** + * Gets the valid query languages + * + * @return The valid query languages + */ + @GET + @Path("getQueryLanguages") + public String getQueryLanguages() { + return RegistryQueryUtil + .formatArrayString(registryObjectDao + .executeHQLQuery( + "SELECT obj.code FROM ClassificationNodeType obj where id like 'urn:oasis:names:tc:ebxml-regrep:QueryLanguage:%'") + .toArray()); + } + + /** + * Stores the query definition to the registry + * + * @param params + * The query definition tokens + * @return The status message + */ + @GET + @Path("storeQuery/{params}") + public String storeQuery(@PathParam("params") String params) { + StringBuilder response = new StringBuilder(); + QueryDefinitionType queryDef = new QueryDefinitionType(); + String[] tokens = params.split(",", -1); + if (tokens.length < 4) { + throw new IllegalArgumentException( + "Argument to storeQuery must contain at least 4 comma delimited tokens!"); + } + for (int i = 0; i < tokens.length; i++) { + tokens[i] = tokens[i].trim(); + } + String queryName = tokens[0]; + String queryDescription = tokens[1]; + String queryLangCode = tokens[2]; + String queryExpression = tokens[3]; + queryDef.setId(queryName); + queryDef.setLid(queryName); + queryDef.setName(new InternationalStringType(queryName)); + queryDef.setDescription(new InternationalStringType(queryDescription)); + queryDef.setObjectType(RegistryObjectTypes.QUERY_DEFINITION); + queryDef.setStatus(StatusTypes.APPROVED); + if (!queryExpression.isEmpty()) { + StringQueryExpressionType expr = new StringQueryExpressionType(); + String queryLanguage = (String) registryObjectDao + .executeHQLQuery( + "SELECT id FROM ClassificationNodeType obj where obj.code=:code", + "code", queryLangCode).get(0); + expr.setQueryLanguage(queryLanguage); + expr.setValue(queryExpression); + queryDef.setQueryExpression(expr); + } + for (int i = 4; i < tokens.length && !tokens[4].isEmpty(); i += 6) { + if ((i + 5) >= tokens.length) { + throw new IllegalArgumentException( + "Incomplete parameter submitted to storeQuery!"); + } + ParameterType param = new ParameterType(); + param.setParameterName(tokens[i]); + param.setName(new InternationalStringType(tokens[i])); + if (!tokens[i + 1].isEmpty()) { + param.setDescription(new InternationalStringType(tokens[i + 1])); + } + if (!tokens[i + 2].isEmpty()) { + param.setDataType(tokens[i + 2]); + } + if (!tokens[i + 3].isEmpty()) { + param.setDefaultValue(tokens[i + 3]); + } + if (!tokens[i + 4].isEmpty()) { + param.setMinOccurs(new BigInteger(tokens[i + 4])); + } + if (!tokens[i + 5].isEmpty()) { + param.setMaxOccurs(new BigInteger(tokens[i + 5])); + } + queryDef.getParameter().add(param); + } + registryObjectDao.createOrUpdate(queryDef); + + response.append("Successfully created Query Definition: ").append( + queryDef.getId()); + return response.toString(); + } + + /** + * Deletes the selected query from the registry + * + * @param queryId + * The ID of the query to delete from the registry + * @return Status message whether the query was deleted + */ + @GET + @Path("deleteQuery/{queryId}") + public String deleteQuery(@PathParam("queryId") String queryId) { + + if (queryId == null || queryId.isEmpty()) { + return "A query id must be specified"; + } + + // Check to make sure we're not trying to delete a canonical query + if (CanonicalQueryTypes.CANONICAL_QUERY_TYPES.contains(queryId)) { + return "Cannot delete canonical query!"; + } + RegistryObjectType queryObj = registryObjectDao.getById(queryId); + if (queryObj == null) { + return "Query Definition [" + queryId + + "] not present in registry!"; + } + + registryObjectDao.delete(queryObj); + return "Successfully deleted query: " + queryId; + } + + public void setRegistryObjectDao(RegistryObjectDao registryObjectDao) { + this.registryObjectDao = registryObjectDao; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties index bac6c8310d..f122663cd7 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties @@ -14,4 +14,4 @@ ebxml-email.enabled=false ebxml-notification-batch-size=50 # Configuration of thread pool used to handle web service requests ebxml-webserver-min-threads=2 -ebxml-webserver-max-threads=10 \ No newline at end of file +ebxml-webserver-max-threads=5 \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/query/RegistryQueryUtil.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/query/RegistryQueryUtil.java index e4f2bfa498..c31ede2abd 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/query/RegistryQueryUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/query/RegistryQueryUtil.java @@ -21,7 +21,9 @@ package com.raytheon.uf.edex.registry.ebxml.services.query; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.datatype.DatatypeConfigurationException; @@ -51,6 +53,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlExceptionUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 10/8/2013 1682 bphillip Initial implementation + * 11/7/2013 1678 bphillip Added formatArrayString * * * @author bphillip @@ -70,6 +73,12 @@ public class RegistryQueryUtil { private static final Pattern REPLACE_LIKE_CHARS_PATTERN = Pattern .compile("\\?"); + /** + * Pattern used to format the string representation of arrays + */ + private static final Pattern ARRAY_STRING_PATTERN = Pattern + .compile("(\\[)(.*)(\\])"); + /** * Replaces the registry character wilcard (?) with the database wildcard * (_) @@ -224,4 +233,20 @@ public class RegistryQueryUtil { } } + + /** + * Formats the string representation of an array as a comma separated list + * + * @param arrayString + * The array string to format + * @return The formatted string + */ + public static String formatArrayString(Object[] arr) { + String arrayString = Arrays.toString(arr); + Matcher matcher = ARRAY_STRING_PATTERN.matcher(arrayString); + if (matcher.find()) { + return matcher.group(2); + } + return arrayString; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/federation/status.html b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/federation/status.html index f061c21e30..7f1252ae1e 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/federation/status.html +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/federation/status.html @@ -1,3 +1,37 @@ + + + @@ -68,7 +102,7 @@
My Registry is Subscribed To: - +Retrieving Registry List...

@@ -76,7 +110,7 @@ Registries Subscribing to My Registry: - +Retrieving Registry List...

@@ -87,7 +121,7 @@
Object Types Currently Replicated: - +Retrieving Object List...

diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/navigation.html b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/navigation.html index b6c188b673..701d08abe5 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/navigation.html +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/navigation.html @@ -56,6 +56,8 @@ Date Ticket# Engineer Description Query Interface
+ Define Query +
Subscription Backup
Federation Status diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/registryUtil.js b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/registryUtil.js index d18e21c681..41ec5d9945 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/registryUtil.js +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/registryUtil.js @@ -1,4 +1,34 @@ - +/* +This software was developed and / or modified by Raytheon Company, +pursuant to Contract DG133W-05-CQ-1067 with the US Government. + +U.S. EXPORT CONTROLLED TECHNICAL DATA +This software product contains export-restricted data whose +export/transfer/disclosure is restricted by U.S. law. Dissemination +to non-U.S. persons whether in the United States or abroad requires +an export license or other authorization. + +Contractor Name: Raytheon Company +Contractor Address: 6825 Pine Street, Suite 340 + Mail Stop B8 + Omaha, NE 68106 + 402.291.0100 + +See the AWIPS II Master Rights File ("Master Rights File.pdf") for +further licensing information. + +Navigation pane containing links + +SOFTWARE HISTORY + +Date Ticket# Engineer Description +------------ ---------- ----------- -------------------------- +10/15/2013 1682 bphillip Initial implementation + + +@author bphillip +@version 1 +*/ function callRestService(url,arg){ var url = "http://"+window.location.host+"/"+url diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/services/query/DefineQuery.html b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/services/query/DefineQuery.html new file mode 100644 index 0000000000..be98a2cfc8 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/web/registry/services/query/DefineQuery.html @@ -0,0 +1,215 @@ + + + + + + + + + + + + Registry Query Definition Manager + + + + +

Remove Custom Query Definition

+ + + + + +
Query Name
+
+ +

+
+

Define New Query Definition

+Query Definition +
+ + + + + + + + + + + + + + + + + +
Query Name
Query Description
Query Language
Query Expression
+

+Query Parameter Definition + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Description
Data Type
Default Value
Min Occurrences
Max Occurrences
+

+Defined Parameters +
+None +

+ + + + + + +