diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/audit/AuditEntryType.java b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/audit/AuditEntryType.java index 9d7b20c595..850694eaef 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/audit/AuditEntryType.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/audit/AuditEntryType.java @@ -28,6 +28,6 @@ public enum AuditEntryType { Grant, Revoke, Publish, Retire, Register, Unregister, - AddPolicy, RemovePolicy, UpdatePolicy, + AddPolicy, RemovePolicy, UpdatePolicy, ReorderPolicies, CreateContract, BreakContract } diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyBean.java b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyBean.java index eaefccc381..645869d42f 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyBean.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyBean.java @@ -28,6 +28,7 @@ import javax.persistence.Table; import javax.persistence.Transient; +import org.hibernate.annotations.Index; import org.jboss.errai.common.client.api.annotations.Portable; /** @@ -72,6 +73,9 @@ public class PolicyBean implements Serializable { private Date modifiedOn; @ManyToOne(fetch=FetchType.EAGER, optional=false) private PolicyDefinitionBean definition; + @Column(updatable=true, nullable=false) + @Index(name="pol_order") + private int orderIndex; /** * Constructor. @@ -247,6 +251,34 @@ public void setDefinition(PolicyDefinitionBean definition) { this.definition = definition; } + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the orderIndex + */ + public int getOrderIndex() { + return orderIndex; + } + + /** + * @param orderIndex the orderIndex to set + */ + public void setOrderIndex(int orderIndex) { + this.orderIndex = orderIndex; + } + /** * @see java.lang.Object#hashCode() */ @@ -278,18 +310,4 @@ public boolean equals(Object obj) { return true; } - /** - * @return the description - */ - public String getDescription() { - return description; - } - - /** - * @param description the description to set - */ - public void setDescription(String description) { - this.description = description; - } - } diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/summary/PolicyChainSummaryBean.java b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyChainBean.java similarity index 86% rename from apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/summary/PolicyChainSummaryBean.java rename to apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyChainBean.java index 299251460c..c29452d2ab 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/summary/PolicyChainSummaryBean.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-beans/src/main/java/org/overlord/apiman/dt/api/beans/policies/PolicyChainBean.java @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.overlord.apiman.dt.api.beans.summary; +package org.overlord.apiman.dt.api.beans.policies; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jboss.errai.common.client.api.annotations.Portable; -import org.overlord.apiman.dt.api.beans.policies.PolicyBean; /** * Models the list of policies that would get applied if a service were invoked @@ -29,7 +28,7 @@ * @author eric.wittmann@redhat.com */ @Portable -public class PolicyChainSummaryBean implements Serializable { +public class PolicyChainBean implements Serializable { private static final long serialVersionUID = -497197512733345793L; @@ -38,7 +37,7 @@ public class PolicyChainSummaryBean implements Serializable { /** * Constructor. */ - public PolicyChainSummaryBean() { + public PolicyChainBean() { } /** diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-jpa/src/main/java/org/overlord/apiman/dt/api/jpa/JpaStorage.java b/apiman-dt/apiman-dt-api/apiman-dt-api-jpa/src/main/java/org/overlord/apiman/dt/api/jpa/JpaStorage.java index f26fe0ae5a..2581909b58 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-jpa/src/main/java/org/overlord/apiman/dt/api/jpa/JpaStorage.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-jpa/src/main/java/org/overlord/apiman/dt/api/jpa/JpaStorage.java @@ -174,7 +174,7 @@ public SearchResultsBean auditEntity(String organizationId, if (paging != null) { criteria.setPaging(paging); } else { - criteria.setPage(0); + criteria.setPage(1); criteria.setPageSize(20); } criteria.setOrder("when", false); //$NON-NLS-1$ @@ -216,7 +216,7 @@ public SearchResultsBean auditUser(String userId, PagingBean if (paging != null) { criteria.setPaging(paging); } else { - criteria.setPage(0); + criteria.setPage(1); criteria.setPageSize(20); } criteria.setOrder("when", false); //$NON-NLS-1$ @@ -627,19 +627,25 @@ public List getPlanVersions(String orgId, String planId) /** * @see org.overlord.apiman.dt.api.core.IStorageQuery#getPolicies(java.lang.String, java.lang.String, java.lang.String, org.overlord.apiman.dt.api.beans.policies.PolicyType) */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "nls", "unchecked" }) @Override public List getPolicies(String organizationId, String entityId, String version, PolicyType type) throws StorageException { beginTx(); try { EntityManager entityManager = getActiveEntityManager(); - String jpql = "SELECT p from PolicyBean p WHERE p.organizationId = :orgId AND p.entityId = :entityId AND p.entityVersion = :entityVersion AND p.type = :type"; //$NON-NLS-1$ + String jpql = + "SELECT p from PolicyBean p " + + " WHERE p.organizationId = :orgId " + + " AND p.entityId = :entityId " + + " AND p.entityVersion = :entityVersion " + + " AND p.type = :type" + + " ORDER BY p.orderIndex ASC"; Query query = entityManager.createQuery(jpql); - query.setParameter("orgId", organizationId); //$NON-NLS-1$ - query.setParameter("entityId", entityId); //$NON-NLS-1$ - query.setParameter("entityVersion", version); //$NON-NLS-1$ - query.setParameter("type", type); //$NON-NLS-1$ + query.setParameter("orgId", organizationId); + query.setParameter("entityId", entityId); + query.setParameter("entityVersion", version); + query.setParameter("type", type); List rval = (List) query.getResultList(); for (PolicyBean policyBean : rval) { diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/OrganizationResourceImpl.java b/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/OrganizationResourceImpl.java index a27dea4ed0..6e266fbf3f 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/OrganizationResourceImpl.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/OrganizationResourceImpl.java @@ -46,6 +46,7 @@ import org.overlord.apiman.dt.api.beans.plans.PlanStatus; import org.overlord.apiman.dt.api.beans.plans.PlanVersionBean; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.policies.PolicyDefinitionBean; import org.overlord.apiman.dt.api.beans.policies.PolicyType; import org.overlord.apiman.dt.api.beans.search.PagingBean; @@ -59,7 +60,6 @@ import org.overlord.apiman.dt.api.beans.summary.ApplicationSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ContractSummaryBean; import org.overlord.apiman.dt.api.beans.summary.PlanSummaryBean; -import org.overlord.apiman.dt.api.beans.summary.PolicyChainSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServicePlanSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServiceSummaryBean; import org.overlord.apiman.dt.api.core.IApiKeyGenerator; @@ -806,6 +806,42 @@ public List listAppPolicies(String organizationId, String applicatio throw new SystemErrorException(e); } } + + /** + * @see org.overlord.apiman.dt.api.rest.contract.IOrganizationResource#reorderApplicationPolicies(java.lang.String, java.lang.String, java.lang.String, org.overlord.apiman.dt.api.beans.policies.PolicyChainBean) + */ + @Override + public void reorderApplicationPolicies(String organizationId, String applicationId, String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + ApplicationVersionNotFoundException, NotAuthorizedException { + if (!securityContext.hasPermission(PermissionType.svcEdit, organizationId)) + throw ExceptionFactory.notAuthorizedException(); + + ApplicationVersionBean avb; + try { + avb = query.getApplicationVersion(organizationId, applicationId, version); + } catch (StorageException e) { + throw new SystemErrorException(e); + } + if (avb == null) { + throw ExceptionFactory.applicationVersionNotFoundException(applicationId, version); + } + + try { + storage.beginTx(); + List policies = policyChain.getPolicies(); + for (PolicyBean incomingPolicy : policies) { + PolicyBean storedPolicy = this.storage.get(incomingPolicy.getId(), PolicyBean.class); + storedPolicy.setOrderIndex(incomingPolicy.getOrderIndex()); + storage.update(storedPolicy); + } + storage.createAuditEntry(AuditUtils.policiesReordered(avb, PolicyType.Application, securityContext)); + storage.commitTx(); + } catch (StorageException e) { + storage.rollbackTx(); + throw new SystemErrorException(e); + } + } /** * @see org.overlord.apiman.dt.api.rest.contract.IOrganizationResource#create(java.lang.String, org.overlord.apiman.dt.api.beans.services.ServiceBean) @@ -1262,11 +1298,47 @@ public List listServicePolicies(String organizationId, String servic } } + /** + * @see org.overlord.apiman.dt.api.rest.contract.IOrganizationResource#reorderServicePolicies(java.lang.String, java.lang.String, java.lang.String, org.overlord.apiman.dt.api.beans.policies.PolicyChainBean) + */ + @Override + public void reorderServicePolicies(String organizationId, String serviceId, String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + ServiceVersionNotFoundException, NotAuthorizedException { + if (!securityContext.hasPermission(PermissionType.svcEdit, organizationId)) + throw ExceptionFactory.notAuthorizedException(); + + ServiceVersionBean svb; + try { + svb = query.getServiceVersion(organizationId, serviceId, version); + } catch (StorageException e) { + throw new SystemErrorException(e); + } + if (svb == null) { + throw ExceptionFactory.serviceVersionNotFoundException(serviceId, version); + } + + try { + storage.beginTx(); + List policies = policyChain.getPolicies(); + for (PolicyBean incomingPolicy : policies) { + PolicyBean storedPolicy = this.storage.get(incomingPolicy.getId(), PolicyBean.class); + storedPolicy.setOrderIndex(incomingPolicy.getOrderIndex()); + storage.update(storedPolicy); + } + storage.createAuditEntry(AuditUtils.policiesReordered(svb, PolicyType.Service, securityContext)); + storage.commitTx(); + } catch (StorageException e) { + storage.rollbackTx(); + throw new SystemErrorException(e); + } + } + /** * @see org.overlord.apiman.dt.api.rest.contract.IOrganizationResource#getPolicyChain(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ @Override - public PolicyChainSummaryBean getServicePolicyChain(String organizationId, String serviceId, String version, + public PolicyChainBean getServicePolicyChain(String organizationId, String serviceId, String version, String planId) throws ServiceVersionNotFoundException, PlanNotFoundException, NotAuthorizedException { if (!securityContext.hasPermission(PermissionType.svcView, organizationId)) throw ExceptionFactory.notAuthorizedException(); @@ -1289,7 +1361,7 @@ public PolicyChainSummaryBean getServicePolicyChain(String organizationId, Strin List servicePolicies = query.getPolicies(organizationId, serviceId, version, PolicyType.Service); List planPolicies = query.getPolicies(organizationId, planId, planVersion, PolicyType.Plan); - PolicyChainSummaryBean chain = new PolicyChainSummaryBean(); + PolicyChainBean chain = new PolicyChainBean(); chain.getPolicies().addAll(planPolicies); chain.getPolicies().addAll(servicePolicies); return chain; @@ -1714,6 +1786,42 @@ public List listPlanPolicies(String organizationId, String planId, S } } + /** + * @see org.overlord.apiman.dt.api.rest.contract.IOrganizationResource#reorderPlanPolicies(java.lang.String, java.lang.String, java.lang.String, org.overlord.apiman.dt.api.beans.policies.PolicyChainBean) + */ + @Override + public void reorderPlanPolicies(String organizationId, String planId, String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + PlanVersionNotFoundException, NotAuthorizedException { + if (!securityContext.hasPermission(PermissionType.svcEdit, organizationId)) + throw ExceptionFactory.notAuthorizedException(); + + PlanVersionBean pvb; + try { + pvb = query.getPlanVersion(organizationId, planId, version); + } catch (StorageException e) { + throw new SystemErrorException(e); + } + if (pvb == null) { + throw ExceptionFactory.planVersionNotFoundException(planId, version); + } + + try { + storage.beginTx(); + List policies = policyChain.getPolicies(); + for (PolicyBean incomingPolicy : policies) { + PolicyBean storedPolicy = this.storage.get(incomingPolicy.getId(), PolicyBean.class); + storedPolicy.setOrderIndex(incomingPolicy.getOrderIndex()); + storage.update(storedPolicy); + } + storage.createAuditEntry(AuditUtils.policiesReordered(pvb, PolicyType.Plan, securityContext)); + storage.commitTx(); + } catch (StorageException e) { + storage.rollbackTx(); + throw new SystemErrorException(e); + } + } + /** * Creates a policy for the given entity (supports creating policies for applications, @@ -1745,6 +1853,20 @@ protected PolicyBean doCreatePolicy(String organizationId, String entityId, Stri } try { + SearchCriteriaBean criteria = new SearchCriteriaBean(); + criteria.addFilter("organizationId", organizationId, SearchCriteriaFilterBean.OPERATOR_EQ); //$NON-NLS-1$ + criteria.addFilter("entityId", entityId, SearchCriteriaFilterBean.OPERATOR_EQ); //$NON-NLS-1$ + criteria.addFilter("entityVersion", entityVersion, SearchCriteriaFilterBean.OPERATOR_EQ); //$NON-NLS-1$ + criteria.addFilter("type", type.name(), SearchCriteriaFilterBean.OPERATOR_EQ); //$NON-NLS-1$ + criteria.setOrder("orderIndex", false); //$NON-NLS-1$ + criteria.setPage(1); + criteria.setPageSize(1); + SearchResultsBean resultsBean = storage.find(criteria, PolicyBean.class); + int newIdx = 0; + if (!resultsBean.getBeans().isEmpty()) { + newIdx = resultsBean.getBeans().get(0).getOrderIndex() + 1; + } + bean.setId(null); bean.setName(def.getName()); bean.setCreatedBy(securityContext.getCurrentUser()); @@ -1755,6 +1877,7 @@ protected PolicyBean doCreatePolicy(String organizationId, String entityId, Stri bean.setEntityId(entityId); bean.setEntityVersion(entityVersion); bean.setType(type); + bean.setOrderIndex(newIdx); storage.create(bean); storage.createAuditEntry(AuditUtils.policyAdded(bean, type, securityContext)); storage.commitTx(); diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/audit/AuditUtils.java b/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/audit/AuditUtils.java index 9f138a28ee..700a286b08 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/audit/AuditUtils.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-rest-impl/src/main/java/org/overlord/apiman/dt/api/rest/impl/audit/AuditUtils.java @@ -595,6 +595,51 @@ public static AuditEntryBean applicationUnregistered(ApplicationVersionBean bean return entry; } + /** + * Called when the user reorders the policies in a service. + * @param svb + * @param service + * @param securityContext + */ + public static AuditEntryBean policiesReordered(ServiceVersionBean svb, PolicyType service, + ISecurityContext securityContext) { + AuditEntryBean entry = newEntry(svb.getService().getOrganizationId(), AuditEntityType.Service, securityContext); + entry.setEntityId(svb.getService().getId()); + entry.setEntityVersion(svb.getVersion()); + entry.setWhat(AuditEntryType.ReorderPolicies); + return entry; + } + + /** + * Called when the user reorders the policies in an application. + * @param avb + * @param service + * @param securityContext + */ + public static AuditEntryBean policiesReordered(ApplicationVersionBean avb, PolicyType service, + ISecurityContext securityContext) { + AuditEntryBean entry = newEntry(avb.getApplication().getOrganizationId(), AuditEntityType.Application, securityContext); + entry.setEntityId(avb.getApplication().getId()); + entry.setEntityVersion(avb.getVersion()); + entry.setWhat(AuditEntryType.ReorderPolicies); + return entry; + } + + /** + * Called when the user reorders the policies in a plan. + * @param pvb + * @param service + * @param securityContext + */ + public static AuditEntryBean policiesReordered(PlanVersionBean pvb, PolicyType service, + ISecurityContext securityContext) { + AuditEntryBean entry = newEntry(pvb.getPlan().getOrganizationId(), AuditEntityType.Plan, securityContext); + entry.setEntityId(pvb.getPlan().getId()); + entry.setEntityVersion(pvb.getVersion()); + entry.setWhat(AuditEntryType.ReorderPolicies); + return entry; + } + /** * Creates an audit entry. * @param orgId @@ -626,5 +671,5 @@ public static String asString(Set plans) { } return builder.toString(); } - + } diff --git a/apiman-dt/apiman-dt-api/apiman-dt-api-rest/src/main/java/org/overlord/apiman/dt/api/rest/contract/IOrganizationResource.java b/apiman-dt/apiman-dt-api/apiman-dt-api-rest/src/main/java/org/overlord/apiman/dt/api/rest/contract/IOrganizationResource.java index 38ee3bcd14..f8f25aa5eb 100644 --- a/apiman-dt/apiman-dt-api/apiman-dt-api-rest/src/main/java/org/overlord/apiman/dt/api/rest/contract/IOrganizationResource.java +++ b/apiman-dt/apiman-dt-api/apiman-dt-api-rest/src/main/java/org/overlord/apiman/dt/api/rest/contract/IOrganizationResource.java @@ -40,6 +40,7 @@ import org.overlord.apiman.dt.api.beans.plans.PlanBean; import org.overlord.apiman.dt.api.beans.plans.PlanVersionBean; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.search.SearchCriteriaBean; import org.overlord.apiman.dt.api.beans.search.SearchResultsBean; import org.overlord.apiman.dt.api.beans.services.ServiceBean; @@ -47,7 +48,6 @@ import org.overlord.apiman.dt.api.beans.summary.ApplicationSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ContractSummaryBean; import org.overlord.apiman.dt.api.beans.summary.PlanSummaryBean; -import org.overlord.apiman.dt.api.beans.summary.PolicyChainSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServicePlanSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServiceSummaryBean; import org.overlord.apiman.dt.api.rest.contract.exceptions.ApplicationAlreadyExistsException; @@ -250,6 +250,14 @@ public List listAppPolicies(@PathParam("organizationId") String orga throws OrganizationNotFoundException, ApplicationVersionNotFoundException, NotAuthorizedException; + @POST + @Path("{organizationId}/applications/{applicationId}/versions/{version}/reorderPolicies") + @Consumes(MediaType.APPLICATION_JSON) + public void reorderApplicationPolicies(@PathParam("organizationId") String organizationId, + @PathParam("applicationId") String applicationId, @PathParam("version") String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + ApplicationVersionNotFoundException, NotAuthorizedException; + /* * SERVICES */ @@ -375,10 +383,18 @@ public List listServicePolicies(@PathParam("organizationId") String throws OrganizationNotFoundException, ServiceVersionNotFoundException, NotAuthorizedException; + @POST + @Path("{organizationId}/services/{serviceId}/versions/{version}/reorderPolicies") + @Consumes(MediaType.APPLICATION_JSON) + public void reorderServicePolicies(@PathParam("organizationId") String organizationId, + @PathParam("serviceId") String serviceId, @PathParam("version") String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + ServiceVersionNotFoundException, NotAuthorizedException; + @GET @Path("{organizationId}/services/{serviceId}/versions/{version}/plans/{planId}/policyChain") @Produces(MediaType.APPLICATION_JSON) - public PolicyChainSummaryBean getServicePolicyChain(@PathParam("organizationId") String organizationId, + public PolicyChainBean getServicePolicyChain(@PathParam("organizationId") String organizationId, @PathParam("serviceId") String serviceId, @PathParam("version") String version, @PathParam("planId") String planId) throws ServiceVersionNotFoundException, NotAuthorizedException; @@ -505,7 +521,15 @@ public List listPlanPolicies(@PathParam("organizationId") String org @PathParam("planId") String planId, @PathParam("version") String version) throws OrganizationNotFoundException, PlanVersionNotFoundException, NotAuthorizedException; - + + @POST + @Path("{organizationId}/plans/{planId}/versions/{version}/reorderPolicies") + @Consumes(MediaType.APPLICATION_JSON) + public void reorderPlanPolicies(@PathParam("organizationId") String organizationId, + @PathParam("planId") String planId, @PathParam("version") String version, + PolicyChainBean policyChain) throws OrganizationNotFoundException, + PlanVersionNotFoundException, NotAuthorizedException; + /* * MEMBERS */ diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/001_create-policy1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/001_create-policy1.resttest index d395b9cfcb..9dd53b5c23 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/001_create-policy1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/001_create-policy1.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id: $.id +X-RestTest-BindTo-policy-id: id { "type" : "Application", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/003_create-policy2.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/003_create-policy2.resttest index 418db922b1..b69a779f2b 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/003_create-policy2.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/applications/policies/003_create-policy2.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id-2: $.id +X-RestTest-BindTo-policy-id-2: id { "type" : "Application", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/contracts/contracts/003_create-contract1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/contracts/contracts/003_create-contract1.resttest index d8190bbf9d..01b77bac75 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/contracts/contracts/003_create-contract1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/contracts/contracts/003_create-contract1.resttest @@ -10,8 +10,8 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-api-key: $.key -X-RestTest-BindTo-contractId: $.id +X-RestTest-BindTo-api-key: key +X-RestTest-BindTo-contractId: id { "application" : { diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/001_create-policy1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/001_create-policy1.resttest index 1b92e913d2..d37f3648e0 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/001_create-policy1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/001_create-policy1.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id: $.id +X-RestTest-BindTo-policy-id: id { "type" : "Plan", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/003_create-policy2.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/003_create-policy2.resttest index 8d62e24f83..2f744222b3 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/003_create-policy2.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/plans/policies/003_create-policy2.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id-2: $.id +X-RestTest-BindTo-policy-id-2: id { "type" : "Plan", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/009_create-planpolicy-1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/009_create-planpolicy-1.resttest index 9540c31096..2ee9cca898 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/009_create-planpolicy-1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/009_create-planpolicy-1.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-planpolicy1-id: $.id +X-RestTest-BindTo-planpolicy1-id: id { "type" : "Plan", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/010_create-planpolicy-2.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/010_create-planpolicy-2.resttest index 25ec07b8a3..e4b34d4d82 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/010_create-planpolicy-2.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/010_create-planpolicy-2.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-planpolicy2-id: $.id +X-RestTest-BindTo-planpolicy2-id: id { "type" : "Plan", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/011_create-servicepolicy-1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/011_create-servicepolicy-1.resttest index 6973f482d0..1da036f13e 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/011_create-servicepolicy-1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/011_create-servicepolicy-1.resttest @@ -11,7 +11,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-servicepolicy1-id: $.id +X-RestTest-BindTo-servicepolicy1-id: id { "type" : "Service", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/020_get-policychain-gold.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/020_get-policychain-gold.resttest index 2e3344b635..e4fe8cbb5f 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/020_get-policychain-gold.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/020_get-policychain-gold.resttest @@ -3,6 +3,9 @@ GET /organizations/TestOrganization/services/foo/versions/1.0/plans/Gold/policyC ---- 200 Content-Type: application/json +X-RestTest-BindTo-policy-1-id: policies[0].id +X-RestTest-BindTo-policy-2-id: policies[1].id +X-RestTest-BindTo-policy-3-id: policies[2].id { "policies" : [ diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/021_reorder-plan-policies.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/021_reorder-plan-policies.resttest new file mode 100644 index 0000000000..c2f379f326 --- /dev/null +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/021_reorder-plan-policies.resttest @@ -0,0 +1,19 @@ +POST /organizations/TestOrganization/plans/Gold/versions/1.0/reorderPolicies admin/admin +Content-Type: application/json + +{ + "policies" : [ + { + "id" : "${policy-1-id}", + "orderIndex" : 10 + }, + { + "id" : "${policy-2-id}", + "orderIndex" : 5 + } + ] +} + +---- +204 + diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/022_get-policychain-gold.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/022_get-policychain-gold.resttest new file mode 100644 index 0000000000..cdde52c333 --- /dev/null +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/policychain/022_get-policychain-gold.resttest @@ -0,0 +1,37 @@ +GET /organizations/TestOrganization/services/foo/versions/1.0/plans/Gold/policyChain admin/admin + +---- +200 +Content-Type: application/json + +{ + "policies" : [ + { + "type" : "Plan", + "organizationId" : "TestOrganization", + "entityId" : "Gold", + "entityVersion" : "1.0", + "name" : "Policy Def Two", + "description" : "Policy Def Two: Plan Policy 2", + "configuration" : "{\"message\" : \"Plan Policy 2\"}" + }, + { + "type" : "Plan", + "organizationId" : "TestOrganization", + "entityId" : "Gold", + "entityVersion" : "1.0", + "name" : "Policy Def One", + "description" : "Policy Def One: Plan Policy 1", + "configuration" : "{\"message\" : \"Plan Policy 1\"}" + }, + { + "type" : "Service", + "organizationId" : "TestOrganization", + "entityId" : "foo", + "entityVersion" : "1.0", + "name" : "Policy Def Three", + "description" : "Policy Def Three: Service Policy 1", + "configuration" : "{\"message\" : \"Service Policy 1\"}" + } + ] +} diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/publishing/create/014_create-contract1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/publishing/create/014_create-contract1.resttest index d8190bbf9d..01b77bac75 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/publishing/create/014_create-contract1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/publishing/create/014_create-contract1.resttest @@ -10,8 +10,8 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-api-key: $.key -X-RestTest-BindTo-contractId: $.id +X-RestTest-BindTo-api-key: key +X-RestTest-BindTo-contractId: id { "application" : { diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/001_create-policy1.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/001_create-policy1.resttest index 2d1ffc2c9f..04bd54640b 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/001_create-policy1.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/001_create-policy1.resttest @@ -12,7 +12,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id: $.id +X-RestTest-BindTo-policy-id: id { "type" : "Service", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/003_create-policy2.resttest b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/003_create-policy2.resttest index c4daf3ad94..74e71168af 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/003_create-policy2.resttest +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plan-data/services/policies/003_create-policy2.resttest @@ -12,7 +12,7 @@ Content-Type: application/json ---- 200 Content-Type: application/json -X-RestTest-BindTo-policy-id-2: $.id +X-RestTest-BindTo-policy-id-2: id { "type" : "Service", diff --git a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plans/policychain-testPlan.xml b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plans/policychain-testPlan.xml index 9d1d96bf55..1ce882ab8a 100644 --- a/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plans/policychain-testPlan.xml +++ b/apiman-dt/apiman-dt-test/apiman-dt-test-api/src/test/resources/test-plans/policychain-testPlan.xml @@ -18,6 +18,8 @@ test-plan-data/policychain/020_get-policychain-gold.resttest + test-plan-data/policychain/021_reorder-plan-policies.resttest + test-plan-data/policychain/022_get-policychain-gold.resttest \ No newline at end of file diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/AppMessages.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/AppMessages.java index f98eaef835..45478de810 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/AppMessages.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/AppMessages.java @@ -375,6 +375,9 @@ public class AppMessages { public static final String ACTIVITY_UPDATE_SERVICE = "activity.update-service"; //$NON-NLS-1$ @TranslationKey(defaultValue = "updated a policy in") public static final String ACTIVITY_UPDATE_POLICY = "activity.update-policy"; //$NON-NLS-1$ + @TranslationKey(defaultValue = "reordered policies in") + public static final String ACTIVITY_REORDER_POLICIES = "activity.reorder-policies"; //$NON-NLS-1$ + @TranslationKey(defaultValue = "Policy added:") public static final String ACTIVITY_DATA_POLICY_ADDED = "activity.data.policy-added"; //$NON-NLS-1$ @@ -420,4 +423,6 @@ public class AppMessages { @TranslationKey(defaultValue = "The service was retired from the Gateway and can no longer be used.") public static final String SERVICE_STATUS_RETIRED = "service.status.retired"; //$NON-NLS-1$ + @TranslationKey(defaultValue = "Move Policy Here") + public static final String MOVE_POLICY = "move-policy"; //$NON-NLS-1$ } diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/events/PoliciesReorderedEvent.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/events/PoliciesReorderedEvent.java new file mode 100644 index 0000000000..faf4d42599 --- /dev/null +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/events/PoliciesReorderedEvent.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.overlord.apiman.dt.ui.client.local.events; + +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.GwtEvent; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.event.shared.HasHandlers; + +/** + * Event fired when the user reorders the policies for an entity. + * + * @author eric.wittmann@redhat.com + */ +public class PoliciesReorderedEvent extends GwtEvent { + + /** + * Handler for {@link PoliciesReorderedEvent}. + */ + public static interface Handler extends EventHandler { + + /** + * Called when {@link PoliciesReorderedEvent} is fired. + * + * @param event the {@link PoliciesReorderedEvent} that was fired + */ + public void onPoliciesReordered(PoliciesReorderedEvent event); + } + + /** + * Indicates if a widget supports ok/cancel. + */ + public static interface HasPoliciesReorderedHandlers extends HasHandlers { + + /** + * Adds a handler to the widget. + * @param handler + */ + public HandlerRegistration addPoliciesReorderedHandler(Handler handler); + + } + + private static Type TYPE; + + /** + * Fires the event. + * @param source + * @param contract + */ + public static PoliciesReorderedEvent fire(HasHandlers source) { + PoliciesReorderedEvent event = new PoliciesReorderedEvent(); + if (TYPE != null) + source.fireEvent(event); + return event; + } + + /** + * Gets the type associated with this event. + * + * @return returns the handler type + */ + public static Type getType() { + if (TYPE == null) { + TYPE = new Type(); + } + return TYPE; + } + + /** + * Constructor. + */ + public PoliciesReorderedEvent() { + } + + /** + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /** + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(Handler handler) { + handler.onPoliciesReordered(this); + } +} diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/AppPoliciesPage.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/AppPoliciesPage.java index 6c487ac0c2..013e572809 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/AppPoliciesPage.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/AppPoliciesPage.java @@ -25,8 +25,10 @@ import org.jboss.errai.ui.shared.api.annotations.DataField; import org.jboss.errai.ui.shared.api.annotations.Templated; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.policies.PolicyType; import org.overlord.apiman.dt.ui.client.local.AppMessages; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent; import org.overlord.apiman.dt.ui.client.local.events.RemovePolicyEvent; import org.overlord.apiman.dt.ui.client.local.pages.common.PolicyList; import org.overlord.apiman.dt.ui.client.local.services.rest.IRestInvokerCallback; @@ -69,6 +71,12 @@ public void onRemovePolicy(RemovePolicyEvent event) { doRemovePolicy(event.getPolicy()); } }); + policies.addPoliciesReorderedHandler(new PoliciesReorderedEvent.Handler() { + @Override + public void onPoliciesReordered(PoliciesReorderedEvent event) { + doReorderPolicies(); + } + }); } /** @@ -134,6 +142,31 @@ public void onError(Throwable error) { }); } + /** + * Reorder the policies according to the user's actions. + */ + protected void doReorderPolicies() { + PolicyChainBean chain = new PolicyChainBean(); + chain.getPolicies().addAll(policies.getValue()); + int weight = 0; + for (PolicyBean policyBean : chain.getPolicies()) { + policyBean.setOrderIndex(weight++); + // trim it down a bit (info not needed) + policyBean.setDefinition(null); + policyBean.setDescription(null); + policyBean.setConfiguration(null); + } + rest.reorderApplicationPolicies(org, versionBean.getApplication().getId(), versionBean.getVersion(), chain, new IRestInvokerCallback() { + @Override + public void onSuccess(Void response) { + } + @Override + public void onError(Throwable error) { + dataPacketError(error); + } + }); + } + /** * @see org.overlord.apiman.dt.ui.client.local.pages.AbstractPage#getPageTitle() */ diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ConsumerServicePage.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ConsumerServicePage.java index a3cf202844..056dba49d5 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ConsumerServicePage.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ConsumerServicePage.java @@ -27,9 +27,9 @@ import org.jboss.errai.ui.shared.api.annotations.DataField; import org.jboss.errai.ui.shared.api.annotations.Templated; import org.overlord.apiman.dt.api.beans.orgs.OrganizationBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.services.ServiceBean; import org.overlord.apiman.dt.api.beans.services.ServiceVersionBean; -import org.overlord.apiman.dt.api.beans.summary.PolicyChainSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServicePlanSummaryBean; import org.overlord.apiman.dt.api.rest.contract.exceptions.ServiceVersionNotFoundException; import org.overlord.apiman.dt.ui.client.local.AppMessages; @@ -119,9 +119,9 @@ public void onShowPolicyChain(ShowPolicyChainEvent event) { * @param planId */ protected void onShowPolicyChain(final String planId) { - rest.getServicePlanPolicyChain(organizationBean.getId(), serviceBean.getId(), versionBean.getVersion(), planId, new IRestInvokerCallback() { + rest.getServicePlanPolicyChain(organizationBean.getId(), serviceBean.getId(), versionBean.getVersion(), planId, new IRestInvokerCallback() { @Override - public void onSuccess(PolicyChainSummaryBean response) { + public void onSuccess(PolicyChainBean response) { plans.renderPolicyChain(planId, response); } @Override diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/PlanPoliciesPage.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/PlanPoliciesPage.java index 1cca846e47..1415762930 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/PlanPoliciesPage.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/PlanPoliciesPage.java @@ -25,8 +25,10 @@ import org.jboss.errai.ui.shared.api.annotations.DataField; import org.jboss.errai.ui.shared.api.annotations.Templated; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.policies.PolicyType; import org.overlord.apiman.dt.ui.client.local.AppMessages; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent; import org.overlord.apiman.dt.ui.client.local.events.RemovePolicyEvent; import org.overlord.apiman.dt.ui.client.local.pages.common.PolicyList; import org.overlord.apiman.dt.ui.client.local.services.rest.IRestInvokerCallback; @@ -69,6 +71,12 @@ public void onRemovePolicy(RemovePolicyEvent event) { doRemovePolicy(event.getPolicy()); } }); + policies.addPoliciesReorderedHandler(new PoliciesReorderedEvent.Handler() { + @Override + public void onPoliciesReordered(PoliciesReorderedEvent event) { + doReorderPolicies(); + } + }); } /** @@ -135,6 +143,31 @@ public void onError(Throwable error) { }); } + /** + * Reorder the policies according to the user's actions. + */ + protected void doReorderPolicies() { + PolicyChainBean chain = new PolicyChainBean(); + chain.getPolicies().addAll(policies.getValue()); + int weight = 0; + for (PolicyBean policyBean : chain.getPolicies()) { + policyBean.setOrderIndex(weight++); + // trim it down a bit (info not needed) + policyBean.setDefinition(null); + policyBean.setDescription(null); + policyBean.setConfiguration(null); + } + rest.reorderPlanPolicies(org, versionBean.getPlan().getId(), versionBean.getVersion(), chain, new IRestInvokerCallback() { + @Override + public void onSuccess(Void response) { + } + @Override + public void onError(Throwable error) { + dataPacketError(error); + } + }); + } + /** * @see org.overlord.apiman.dt.ui.client.local.pages.AbstractPage#getPageTitle() */ diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ServicePoliciesPage.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ServicePoliciesPage.java index ef1a607c4f..e19a4537e5 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ServicePoliciesPage.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/ServicePoliciesPage.java @@ -25,8 +25,10 @@ import org.jboss.errai.ui.shared.api.annotations.DataField; import org.jboss.errai.ui.shared.api.annotations.Templated; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.policies.PolicyType; import org.overlord.apiman.dt.ui.client.local.AppMessages; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent; import org.overlord.apiman.dt.ui.client.local.events.RemovePolicyEvent; import org.overlord.apiman.dt.ui.client.local.pages.common.PolicyList; import org.overlord.apiman.dt.ui.client.local.services.rest.IRestInvokerCallback; @@ -69,8 +71,14 @@ public void onRemovePolicy(RemovePolicyEvent event) { doRemovePolicy(event.getPolicy()); } }); + policies.addPoliciesReorderedHandler(new PoliciesReorderedEvent.Handler() { + @Override + public void onPoliciesReordered(PoliciesReorderedEvent event) { + doReorderPolicies(); + } + }); } - + /** * @see org.overlord.apiman.dt.ui.client.local.pages.AbstractServicePage#doLoadPageData() */ @@ -134,6 +142,31 @@ public void onError(Throwable error) { }); } + /** + * Reorder the policies according to the user's actions. + */ + protected void doReorderPolicies() { + PolicyChainBean chain = new PolicyChainBean(); + chain.getPolicies().addAll(policies.getValue()); + int weight = 0; + for (PolicyBean policyBean : chain.getPolicies()) { + policyBean.setOrderIndex(weight++); + // trim it down a bit (info not needed) + policyBean.setDefinition(null); + policyBean.setDescription(null); + policyBean.setConfiguration(null); + } + rest.reorderServicePolicies(org, versionBean.getService().getId(), versionBean.getVersion(), chain, new IRestInvokerCallback() { + @Override + public void onSuccess(Void response) { + } + @Override + public void onError(Throwable error) { + dataPacketError(error); + } + }); + } + /** * @see org.overlord.apiman.dt.ui.client.local.pages.AbstractPage#getPageTitle() */ diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/ActivityList.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/ActivityList.java index d0baa85b27..dc0989fbf7 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/ActivityList.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/ActivityList.java @@ -359,6 +359,8 @@ private String createWhat(AuditEntryBean auditEntryBean) { } case UpdatePolicy: return i18n.format(AppMessages.ACTIVITY_UPDATE_POLICY); + case ReorderPolicies: + return i18n.format(AppMessages.ACTIVITY_REORDER_POLICIES); default: return "??"; //$NON-NLS-1$ } diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/PolicyList.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/PolicyList.java index 776f6636e8..d913ea1320 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/PolicyList.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/common/PolicyList.java @@ -15,8 +15,10 @@ */ package org.overlord.apiman.dt.ui.client.local.pages.common; +import java.util.ArrayList; import java.util.List; +import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; import javax.inject.Inject; @@ -25,14 +27,14 @@ import org.jboss.errai.ui.nav.client.local.TransitionAnchorFactory; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; import org.overlord.apiman.dt.ui.client.local.AppMessages; -import org.overlord.apiman.dt.ui.client.local.events.MoveItemDownEvent; -import org.overlord.apiman.dt.ui.client.local.events.MoveItemDownEvent.HasMoveItemDownHandlers; -import org.overlord.apiman.dt.ui.client.local.events.MoveItemUpEvent; -import org.overlord.apiman.dt.ui.client.local.events.MoveItemUpEvent.HasMoveItemUpHandlers; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent.Handler; +import org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent.HasPoliciesReorderedHandlers; import org.overlord.apiman.dt.ui.client.local.events.RemovePolicyEvent; import org.overlord.apiman.dt.ui.client.local.events.RemovePolicyEvent.HasRemovePolicyHandlers; import org.overlord.apiman.dt.ui.client.local.pages.EditPolicyPage; import org.overlord.apiman.dt.ui.client.local.pages.UserRedirectPage; +import org.overlord.apiman.dt.ui.client.local.services.LoggerService; import org.overlord.apiman.dt.ui.client.local.services.NavigationHelperService; import org.overlord.apiman.dt.ui.client.local.util.Formatting; import org.overlord.apiman.dt.ui.client.local.util.MultimapUtil; @@ -40,11 +42,22 @@ import org.overlord.commons.gwt.client.local.widgets.FontAwesomeIcon; import org.overlord.commons.gwt.client.local.widgets.SpanPanel; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; +import com.google.gwt.event.dom.client.MouseEvent; +import com.google.gwt.event.dom.client.MouseMoveEvent; +import com.google.gwt.event.dom.client.MouseMoveHandler; +import com.google.gwt.event.dom.client.MouseUpEvent; +import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.FlowPanel; @@ -61,19 +74,22 @@ */ @Dependent public class PolicyList extends FlowPanel implements HasValue>, HasRemovePolicyHandlers, - HasMoveItemDownHandlers, HasMoveItemUpHandlers { + HasPoliciesReorderedHandlers { @Inject protected NavigationHelperService navHelper; @Inject protected TranslationService i18n; @Inject - TransitionAnchorFactory toEditPolicyFactory; + protected TransitionAnchorFactory toEditPolicyFactory; @Inject - TransitionAnchorFactory toUserFactory; - - private List policies; + protected TransitionAnchorFactory toUserFactory; + @Inject + protected LoggerService logger; + private boolean filtered; + private boolean empty; + private DropPlaceholder dropHolder; /** * Constructor. @@ -81,6 +97,11 @@ public class PolicyList extends FlowPanel implements HasValue>, public PolicyList() { getElement().setClassName("apiman-policies"); //$NON-NLS-1$ } + + @PostConstruct + protected void postConstruct() { + dropHolder = new DropPlaceholder(); + } /** * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) @@ -89,21 +110,13 @@ public PolicyList() { public HandlerRegistration addValueChangeHandler(ValueChangeHandler> handler) { return super.addHandler(handler, ValueChangeEvent.getType()); } - - /** - * @see org.overlord.apiman.dt.ui.client.local.events.MoveItemDownEvent.HasMoveItemDownHandlers#addMoveItemDownHandler(org.overlord.apiman.dt.ui.client.local.events.MoveItemDownEvent.Handler) - */ - @Override - public HandlerRegistration addMoveItemDownHandler(MoveItemDownEvent.Handler handler) { - return super.addHandler(handler, MoveItemDownEvent.getType()); - } /** - * @see org.overlord.apiman.dt.ui.client.local.events.MoveItemUpEvent.HasMoveItemUpHandlers#addMoveItemUpHandler(org.overlord.apiman.dt.ui.client.local.events.MoveItemUpEvent.Handler) + * @see org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent.HasPoliciesReorderedHandlers#addPoliciesReorderedHandler(org.overlord.apiman.dt.ui.client.local.events.PoliciesReorderedEvent.Handler) */ @Override - public HandlerRegistration addMoveItemUpHandler(MoveItemUpEvent.Handler handler) { - return super.addHandler(handler, MoveItemUpEvent.getType()); + public HandlerRegistration addPoliciesReorderedHandler(Handler handler) { + return super.addHandler(handler, PoliciesReorderedEvent.getType()); } /** @@ -119,6 +132,15 @@ public HandlerRegistration addRemovePolicyHandler(RemovePolicyEvent.Handler hand */ @Override public List getValue() { + List policies = new ArrayList(); + if (!empty) { + for (int i = 0; i < getWidgetCount(); i++) { + PolicyRow pr = (PolicyRow) getWidget(i); + PolicyBean policy = pr.getPolicy(); +// policy.setIndex(i); + policies.add(policy); + } + } return policies; } @@ -144,21 +166,22 @@ public void setValue(List value) { */ @Override public void setValue(List value, boolean fireEvents) { - policies = value; clear(); - refresh(); + refresh(value); } /** * Refresh the display with the current value. */ - public void refresh() { + public void refresh(List policies) { if (policies != null && !policies.isEmpty()) { for (PolicyBean bean : policies) { Widget row = createPolicyRow(bean); add(row); } + empty = false; } else { + empty = true; add(createNoEntitiesWidget()); } } @@ -177,21 +200,31 @@ protected NoEntitiesWidget createNoEntitiesWidget() { * Creates a single policy row. * @param bean */ - private Widget createPolicyRow(PolicyBean bean) { - FlowPanel container = new FlowPanel(); - container.getElement().setClassName("container-fluid"); //$NON-NLS-1$ - container.getElement().addClassName("apiman-summaryrow"); //$NON-NLS-1$ + private Widget createPolicyRow(final PolicyBean bean) { + PolicyRow container = new PolicyRow(bean); - FlowPanel row = new FlowPanel(); - container.add(row); + final FlowPanel row = new FlowPanel(); row.getElement().setClassName("row"); //$NON-NLS-1$ - + + // Grabber + Label grabber = new Label(); + grabber.getElement().setDraggable(Element.DRAGGABLE_TRUE); + grabber.getElement().setClassName("grabber"); //$NON-NLS-1$ + grabber.getElement().getStyle().setHeight(48, Unit.PX); + row.add(grabber); + createIconColumn(bean, row); createSummaryColumn(bean, row); createActionColumn(bean, row); - container.add(new HTMLPanel("
")); //$NON-NLS-1$ + container.add(row); + + PolicyDragHandler handler = new PolicyDragHandler(grabber, container); + grabber.addMouseDownHandler(handler); + grabber.addMouseUpHandler(handler); + grabber.addMouseMoveHandler(handler); + return container; } @@ -200,16 +233,16 @@ private Widget createPolicyRow(PolicyBean bean) { * @param bean * @param row */ - protected void createIconColumn(PolicyBean bean, FlowPanel row) { + protected FlowPanel createIconColumn(final PolicyBean bean, final FlowPanel row) { FlowPanel col = new FlowPanel(); row.add(col); - col.setStyleName("col-md-1"); //$NON-NLS-1$ - col.addStyleName("col-no-padding"); //$NON-NLS-1$ + col.setStyleName("col"); //$NON-NLS-1$ FontAwesomeIcon icon = new FontAwesomeIcon(bean.getDefinition().getIcon(), true); - icon.getElement().addClassName("movable"); //$NON-NLS-1$ icon.getElement().addClassName("apiman-policy-icon"); //$NON-NLS-1$ col.add(icon); + + return col; } /** @@ -220,8 +253,8 @@ protected void createIconColumn(PolicyBean bean, FlowPanel row) { protected void createSummaryColumn(final PolicyBean bean, FlowPanel row) { FlowPanel col = new FlowPanel(); row.add(col); - col.setStyleName("col-md-9"); //$NON-NLS-1$ - col.addStyleName("col-no-padding"); //$NON-NLS-1$ + col.getElement().setClassName("col"); //$NON-NLS-1$ + col.getElement().addClassName("col-70"); //$NON-NLS-1$ FlowPanel titleDiv = new FlowPanel(); titleDiv.getElement().setClassName(""); //$NON-NLS-1$ @@ -274,8 +307,8 @@ protected void createSummaryColumn(final PolicyBean bean, FlowPanel row) { protected void createActionColumn(final PolicyBean bean, FlowPanel row) { FlowPanel col = new FlowPanel(); row.add(col); - col.setStyleName("col-md-2"); //$NON-NLS-1$ - col.addStyleName("col-no-padding"); //$NON-NLS-1$ + col.setStyleName("col"); //$NON-NLS-1$ + col.addStyleName("pull-right"); //$NON-NLS-1$ SpanPanel sp = new SpanPanel(); col.add(sp); @@ -304,5 +337,196 @@ public void onClick(ClickEvent event) { protected boolean isFiltered() { return filtered; } + + /** + * Called when the user begins dragging a policy. + * @param event + * @param row + */ + protected void onStartDragging(MouseEvent event, PolicyRow row) { + int index = getWidgetIndex(row); + insert(dropHolder, index); + + // put the row at the end of the list and then fix its position + remove(row); + add(row); + row.getElement().getStyle().setPosition(Position.FIXED); + row.getElement().getStyle().setWidth(getElement().getClientWidth(), Unit.PX); + row.getElement().getStyle().setOpacity(0.85); + row.getElement().getStyle().setBackgroundColor("white"); //$NON-NLS-1$ + row.getElement().getStyle().setLeft(event.getClientX(), Unit.PX); + } + + /** + * Called when the user drags a policy. + * @param event + * @param row + */ + protected void onDragging(MouseEvent event, PolicyRow row) { + row.getElement().getStyle().setTop(event.getClientY() - 20, Unit.PX); + + Widget w = getHoverWidget(event); + if (w != null && w != dropHolder) { + int index = getWidgetIndex(w); + remove(dropHolder); + insert(dropHolder, index); + } + } + + /** + * Figures out which widget in the list is being hovered over (using + * only the Y coordinate of the event. + * @param event + */ + private Widget getHoverWidget(MouseEvent event) { + int y = event.getClientY(); + for (int i = 0; i < getWidgetCount(); i++) { + Widget widget = getWidget(i); + int widgetTop = widget.getAbsoluteTop(); + int widgetBottom = widgetTop + widget.getOffsetHeight(); + if (y >= widgetTop && y <= widgetBottom) { + return widget; + } + } + return null; + } + + /** + * Called when the user drops a policy. + * @param event + * @param row + */ + protected void onDrop(MouseEvent event, PolicyRow row) { + row.getElement().getStyle().clearLeft(); + row.getElement().getStyle().clearTop(); + row.getElement().getStyle().clearPosition(); + row.getElement().getStyle().clearOpacity(); + row.getElement().getStyle().clearBackgroundColor(); + + int dropIndex = getWidgetIndex(dropHolder); + remove(dropHolder); + remove(row); + insert(row, dropIndex); + + PoliciesReorderedEvent.fire(this); + } + + /** + * A single row in the list. + */ + private class PolicyRow extends FlowPanel { + + private PolicyBean policy; + + /** + * Constructor. + */ + public PolicyRow(PolicyBean policy) { + setPolicy(policy); + getElement().setClassName("container-fluid"); //$NON-NLS-1$ + getElement().addClassName("apiman-summaryrow"); //$NON-NLS-1$ + } + + /** + * @return the policy + */ + public PolicyBean getPolicy() { + return policy; + } + + /** + * @param policy the policy to set + */ + public void setPolicy(PolicyBean policy) { + this.policy = policy; + } + } + + /** + * A simple widget showing where a policy would be placed if the + * user were to drop it. + * + * @author eric.wittmann@redhat.com + */ + private class DropPlaceholder extends FlowPanel { + + /** + * Constructor. + */ + public DropPlaceholder() { + getElement().setClassName("container-fluid"); //$NON-NLS-1$ + getElement().addClassName("drop-target"); //$NON-NLS-1$ + + add(new Label(i18n.format(AppMessages.MOVE_POLICY))); + } + + } + + /** + * A simple drag handler used for dragging around a policy to re-order it. + */ + private class PolicyDragHandler implements MouseDownHandler, MouseMoveHandler, MouseUpHandler { + + private boolean isClicked; + private boolean isDragging; + private Widget dragTarget; + private PolicyRow dragRow; + + /** + * Constructor. + * @param widget + * @param row + * @param policy + */ + public PolicyDragHandler(Widget widget, PolicyRow row) { + dragTarget = widget; + dragRow = row; + } + + /** + * @see com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt.event.dom.client.MouseUpEvent) + */ + @Override + public void onMouseUp(MouseUpEvent event) { + if (isDragging) { + onDrop(event, dragRow); + } + + isClicked = false; + isDragging = false; + Event.releaseCapture(dragTarget.getElement()); + } + + /** + * @see com.google.gwt.event.dom.client.MouseMoveHandler#onMouseMove(com.google.gwt.event.dom.client.MouseMoveEvent) + */ + @Override + public void onMouseMove(MouseMoveEvent event) { + // If mouse is not down, ignore + if (!isClicked) + return; + if (!isDragging) { + isDragging = true; + onStartDragging(event, dragRow); + } + + onDragging(event, dragRow); + } + + /** + * @see com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google.gwt.event.dom.client.MouseDownEvent) + */ + @Override + public void onMouseDown(MouseDownEvent event) { + isClicked = true; + isDragging = false; + + // Capture mouse and prevent event from going up + event.preventDefault(); + Event.setCapture(dragTarget.getElement()); + + // Initialize other state we need as we drag/drop + } + } } diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/consumer/ConsumerServicePlanList.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/consumer/ConsumerServicePlanList.java index 49aea64b24..60bf7985e3 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/consumer/ConsumerServicePlanList.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/pages/consumer/ConsumerServicePlanList.java @@ -26,7 +26,7 @@ import javax.inject.Inject; import org.jboss.errai.ui.client.local.spi.TranslationService; -import org.overlord.apiman.dt.api.beans.summary.PolicyChainSummaryBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.summary.ServicePlanSummaryBean; import org.overlord.apiman.dt.ui.client.local.AppMessages; import org.overlord.apiman.dt.ui.client.local.events.CreateContractEvent; @@ -216,7 +216,7 @@ public void onClick(ClickEvent event) { * @param planId * @param chain */ - public void renderPolicyChain(final String planId, final PolicyChainSummaryBean chain) { + public void renderPolicyChain(final String planId, final PolicyChainBean chain) { FlowPanel chainPanel = this.chainIndex.get(planId); chainPanel.clear(); PolicyChain policyChain = policyChainFactory.get(); diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/services/RestInvokerService.java b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/services/RestInvokerService.java index 41d8f1c6cf..14a8a1bf4d 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/services/RestInvokerService.java +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/services/RestInvokerService.java @@ -36,6 +36,7 @@ import org.overlord.apiman.dt.api.beans.plans.PlanBean; import org.overlord.apiman.dt.api.beans.plans.PlanVersionBean; import org.overlord.apiman.dt.api.beans.policies.PolicyBean; +import org.overlord.apiman.dt.api.beans.policies.PolicyChainBean; import org.overlord.apiman.dt.api.beans.policies.PolicyDefinitionBean; import org.overlord.apiman.dt.api.beans.policies.PolicyType; import org.overlord.apiman.dt.api.beans.search.SearchCriteriaBean; @@ -46,7 +47,6 @@ import org.overlord.apiman.dt.api.beans.summary.ContractSummaryBean; import org.overlord.apiman.dt.api.beans.summary.OrganizationSummaryBean; import org.overlord.apiman.dt.api.beans.summary.PlanSummaryBean; -import org.overlord.apiman.dt.api.beans.summary.PolicyChainSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServicePlanSummaryBean; import org.overlord.apiman.dt.api.beans.summary.ServiceSummaryBean; import org.overlord.apiman.dt.api.rest.contract.IActionResource; @@ -380,6 +380,17 @@ public void getApplicationPolicies(String organizationId, String applicationId, CallbackAdapter> adapter = new CallbackAdapter>(callback); organizations.call(adapter, adapter).listAppPolicies(organizationId, applicationId, version); } + + /** + * Reorders the application's policies. + * @param callback + */ + public void reorderApplicationPolicies(String organizationId, String applicationId, String version, + PolicyChainBean policyChain, IRestInvokerCallback callback) { + CallbackAdapter adapter = new CallbackAdapter(callback); + organizations.call(adapter, adapter).reorderApplicationPolicies(organizationId, applicationId, + version, policyChain); + } /** * Gets the application activity. @@ -528,6 +539,16 @@ public void getServicePolicies(String organizationId, String serviceId, String v CallbackAdapter> adapter = new CallbackAdapter>(callback); organizations.call(adapter, adapter).listServicePolicies(organizationId, serviceId, version); } + + /** + * Reorders the service's policies. + * @param callback + */ + public void reorderServicePolicies(String organizationId, String serviceId, String version, + PolicyChainBean policyChain, IRestInvokerCallback callback) { + CallbackAdapter adapter = new CallbackAdapter(callback); + organizations.call(adapter, adapter).reorderServicePolicies(organizationId, serviceId, version, policyChain); + } /** * Gets the activity information for the service. @@ -568,8 +589,8 @@ public void getServiceVersionActivity(String organizationId, String serviceId, S * @param planId */ public void getServicePlanPolicyChain(String organizationId, String serviceId, String version, - String planId, IRestInvokerCallback callback) { - CallbackAdapter adapter = new CallbackAdapter(callback); + String planId, IRestInvokerCallback callback) { + CallbackAdapter adapter = new CallbackAdapter(callback); organizations.call(adapter, adapter).getServicePolicyChain(organizationId, serviceId, version, planId); } @@ -693,6 +714,16 @@ public void getPlanPolicies(String organizationId, String planId, String version organizations.call(adapter, adapter).listPlanPolicies(organizationId, planId, version); } + /** + * Reorders the plan's policies. + * @param callback + */ + public void reorderPlanPolicies(String organizationId, String planId, String version, + PolicyChainBean policyChain, IRestInvokerCallback callback) { + CallbackAdapter adapter = new CallbackAdapter(callback); + organizations.call(adapter, adapter).reorderPlanPolicies(organizationId, planId, version, policyChain); + } + /** * Creates a new plan. * @param organizationId diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/site/plan-policies.html b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/site/plan-policies.html index 1c64c7a270..80c421bcc8 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/site/plan-policies.html +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/java/org/overlord/apiman/dt/ui/client/local/site/plan-policies.html @@ -77,13 +77,13 @@
-
-
- +
+
+
-
+
@@ -98,18 +98,24 @@ Service usage will be tracked and limited to 1000 requests per day per user.
-
+

+ +
+
Move Policy Here
+
+
-
+
+
-
+
@@ -125,7 +131,7 @@ at a contracted rate of $5 per month per user, regardless of usage.
-
+
diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/apiman.css b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/apiman.css index 50115ab47d..d15039ecaf 100644 --- a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/apiman.css +++ b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/apiman.css @@ -8,6 +8,13 @@ body { text-transform: capitalize; } +.grabber { + background-image: url(images/grabber.png); + background-repeat: repeat-y; + cursor: move; + width: 10px; +} + .italic { font-style: italic; } @@ -705,6 +712,28 @@ ol.breadcrumb { .apiman-policies .apiman-summaryrow hr { clear: both; } +.apiman-policies .row .col { + float: left; + margin-left: 10px; +} +.apiman-policies .row .col-70 { + width: 70%; +} +.apiman-policies .row .grabber { + float: left; + margin-right: 10px; +} +.apiman-policies .drop-target { + padding: 5px 0px 10px 0px; +} +.apiman-policies .drop-target div { + padding: 10px; + text-align: center; + font-size: 18px; + line-height: 32px; + color: rgb(63, 146, 210); + border: 1px dashed #987; +} .apiman-apis .apiman-summaryrow { margin-bottom: 5px; diff --git a/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/images/grabber.png b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/images/grabber.png new file mode 100644 index 0000000000..dfefe6a412 Binary files /dev/null and b/apiman-dt/apiman-dt-ui/apiman-dt-ui-war/src/main/webapp/css/images/grabber.png differ diff --git a/apiman-test/apiman-test-common/pom.xml b/apiman-test/apiman-test-common/pom.xml index c8530cce40..f400197714 100644 --- a/apiman-test/apiman-test-common/pom.xml +++ b/apiman-test/apiman-test-common/pom.xml @@ -10,6 +10,10 @@ + + org.mvel + mvel2 + org.codehaus.jackson jackson-core-asl diff --git a/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestPlanRunner.java b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestPlanRunner.java index 3ad8f824c0..252e821d53 100644 --- a/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestPlanRunner.java +++ b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestPlanRunner.java @@ -49,6 +49,10 @@ import org.codehaus.jackson.node.ObjectNode; import org.codehaus.jackson.node.TextNode; import org.junit.Assert; +import org.mvel2.MVEL; +import org.mvel2.integration.PropertyHandler; +import org.mvel2.integration.PropertyHandlerFactory; +import org.mvel2.integration.VariableResolverFactory; import org.overlord.apiman.test.common.plan.TestGroupType; import org.overlord.apiman.test.common.plan.TestPlan; import org.overlord.apiman.test.common.plan.TestType; @@ -303,30 +307,25 @@ private void bindVariables(JsonNode actualJson, RestTest restTest) { /** * Evaluates the given expression against the given JSON object. * - * TODO replace with MVEL - * * @param bindExpression * @param json */ - private String evaluate(String bindExpression, JsonNode json) { - String [] segments = bindExpression.split("\\."); //$NON-NLS-1$ - JsonNode currentNode = json; - for (String segment : segments) { - if (segment.startsWith("$[")) { //$NON-NLS-1$ - throw new RuntimeException("Not yet implemented: bind value in array response."); //$NON-NLS-1$ - } else if ("$".equals(segment)) { //$NON-NLS-1$ - currentNode = json; - } else { - if (segment.contains("[")) { //$NON-NLS-1$ - throw new RuntimeException("Not yet implemented: bind value from array."); //$NON-NLS-1$ - } - currentNode = currentNode.get(segment); - if (currentNode == null) { - return null; - } + private String evaluate(String bindExpression, final JsonNode json) { + PropertyHandlerFactory.registerPropertyHandler(ObjectNode.class, new PropertyHandler() { + @Override + public Object setProperty(String name, Object contextObj, VariableResolverFactory variableFactory, + Object value) { + throw new RuntimeException("Not supported!"); //$NON-NLS-1$ } - } - return currentNode.asText(); + + @Override + public Object getProperty(String name, Object contextObj, VariableResolverFactory variableFactory) { + ObjectNode node = (ObjectNode) contextObj; + TestVariableResolver resolver = new TestVariableResolver(node, name); + return resolver.getValue(); + } + }); + return String.valueOf(MVEL.eval(bindExpression, new TestVariableResolverFactory(json))); } /** diff --git a/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolver.java b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolver.java new file mode 100644 index 0000000000..7d90dc7938 --- /dev/null +++ b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolver.java @@ -0,0 +1,114 @@ +/* + * Copyright 2014 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.overlord.apiman.test.common.util; + +import java.util.ArrayList; +import java.util.List; + +import org.codehaus.jackson.JsonNode; +import org.mvel2.integration.VariableResolver; + +/** + * A json variable resolver. + * + * @author eric.wittmann@redhat.com + */ +public class TestVariableResolver implements VariableResolver { + + private static final long serialVersionUID = 1L; + + private JsonNode node; + private String fieldName; + + /** + * Constructor. + * @param node + * @param fieldName + */ + public TestVariableResolver(JsonNode node, String fieldName) { + this.node = node; + this.fieldName = fieldName; + } + + /** + * @see org.mvel2.integration.VariableResolver#getName() + */ + @Override + public String getName() { + return fieldName; + } + + /** + * @see org.mvel2.integration.VariableResolver#getType() + */ + @Override + public Class getType() { + return Object.class; + } + + /** + * @see org.mvel2.integration.VariableResolver#setStaticType(java.lang.Class) + */ + @SuppressWarnings("rawtypes") + @Override + public void setStaticType(Class type) { + } + + /** + * @see org.mvel2.integration.VariableResolver#getFlags() + */ + @Override + public int getFlags() { + return 0; + } + + /** + * @see org.mvel2.integration.VariableResolver#getValue() + */ + @Override + public Object getValue() { + JsonNode varNode = node.get(fieldName); + if (varNode.isObject()) { + return varNode; + } else if (varNode.isArray()) { + List rval = new ArrayList(); + for (int idx = 0; idx < varNode.size(); idx++) { + JsonNode idxNode = varNode.get(idx); + rval.add(idxNode); + } + return rval; + } else if (varNode.isNull()) { + return null; + } else if (varNode.isBoolean()) { + return varNode.asBoolean(); + } else if (varNode.isTextual()) { + return varNode.asText(); + } else if (varNode.isInt()) { + return varNode.asInt(); + } else if (varNode.isDouble()) { + return varNode.asDouble(); + } + return varNode; + } + + /** + * @see org.mvel2.integration.VariableResolver#setValue(java.lang.Object) + */ + @Override + public void setValue(Object value) { + } + +} diff --git a/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolverFactory.java b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolverFactory.java new file mode 100644 index 0000000000..10680e9f04 --- /dev/null +++ b/apiman-test/apiman-test-common/src/main/java/org/overlord/apiman/test/common/util/TestVariableResolverFactory.java @@ -0,0 +1,140 @@ +/* + * Copyright 2014 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.overlord.apiman.test.common.util; + +import java.util.Set; + +import org.codehaus.jackson.JsonNode; +import org.mvel2.integration.VariableResolver; +import org.mvel2.integration.impl.BaseVariableResolverFactory; + +/** + * MVEL resolver for jackson parsed json. + * + * @author eric.wittmann@redhat.com + */ +public class TestVariableResolverFactory extends BaseVariableResolverFactory { + + private static final long serialVersionUID = 6176871022243088981L; + + JsonNode node; + + /** + * Constructor. + */ + public TestVariableResolverFactory(JsonNode node) { + this.node = node; + } + + /** + * @see org.mvel2.integration.VariableResolverFactory#createVariable(java.lang.String, java.lang.Object) + */ + @Override + public VariableResolver createVariable(String name, Object value) { + return null; + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#createIndexedVariable(int, java.lang.String, java.lang.Object) + */ + @Override + public VariableResolver createIndexedVariable(int index, String name, Object value) { + return null; + } + + /** + * @see org.mvel2.integration.VariableResolverFactory#createVariable(java.lang.String, java.lang.Object, java.lang.Class) + */ + @Override + public VariableResolver createVariable(String name, Object value, Class type) { + return null; + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#createIndexedVariable(int, java.lang.String, java.lang.Object, java.lang.Class) + */ + @Override + public VariableResolver createIndexedVariable(int index, String name, Object value, Class type) { + return null; + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#setIndexedVariableResolver(int, org.mvel2.integration.VariableResolver) + */ + @Override + public VariableResolver setIndexedVariableResolver(int index, VariableResolver variableResolver) { + return null; + } + + /** + * @see org.mvel2.integration.VariableResolverFactory#isTarget(java.lang.String) + */ + @Override + public boolean isTarget(String name) { + return variableResolvers.containsKey(name); + } + + /** + * @see org.mvel2.integration.VariableResolverFactory#isResolveable(java.lang.String) + */ + @Override + public boolean isResolveable(String name) { + if (variableResolvers.containsKey(name)) { + return true; + } + if (node.isObject() && node.get(name) != null) { + variableResolvers.put(name, new TestVariableResolver(node, name)); + return true; + } + if (nextFactory != null) { + return nextFactory.isResolveable(name); + } + return false; + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#getVariableResolver(java.lang.String) + */ + @Override + public VariableResolver getVariableResolver(String name) { + VariableResolver vr = variableResolvers.get(name); + return vr != null ? vr : (nextFactory == null ? null : nextFactory.getVariableResolver(name)); + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#getKnownVariables() + */ + @Override + public Set getKnownVariables() { + return variableResolvers.keySet(); + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#variableIndexOf(java.lang.String) + */ + @Override + public int variableIndexOf(String name) { + return 0; + } + + /** + * @see org.mvel2.integration.impl.BaseVariableResolverFactory#isIndexedFactory() + */ + @Override + public boolean isIndexedFactory() { + return false; + } +}