}
 
         result.addResult(validatePolicies(data, dbsub, subgrp));
+        result.addResult(validateSupportedTypes(data, subgrp));
         container.addResult(result);
 
         return result.isValid();
         BeanValidationResult result = new BeanValidationResult(subgrp.getPdpType(), subgrp);
 
         for (ToscaPolicyTypeIdentifier type : subgrp.getSupportedPolicyTypes()) {
-            if (data.getPolicyType(type) == null) {
+            if (!type.getName().endsWith(".*") && data.getPolicyType(type) == null) {
                 result.addResult(new ObjectValidationResult("policy type", type, ValidationStatus.INVALID,
                                 "unknown policy type"));
             }
                 result.addResult(new ObjectValidationResult(POLICY_RESULT_NAME, ident, ValidationStatus.INVALID,
                                 "unknown policy"));
 
-            } else if (!subgrp.getSupportedPolicyTypes().contains(policy.getTypeIdentifier())) {
+            } else if (!isPolicySupported(subgrp.getSupportedPolicyTypes(), policy.getTypeIdentifier())) {
                 result.addResult(new ObjectValidationResult(POLICY_RESULT_NAME, ident, ValidationStatus.INVALID,
                                 "not a supported policy for the subgroup"));
 
 
         return (group, subgroup) -> {
 
-            if (!subgroup.getSupportedPolicyTypes().contains(desiredType)) {
+            if (!isPolicySupported(subgroup.getSupportedPolicyTypes(), desiredType)) {
                 // doesn't support the desired policy type
                 return false;
             }
         };
     }
 
+    /**
+     * Determines if a policy type is supported.
+     *
+     * @param supportedTypes supported policy types, any of which may end with ".*"
+     * @param desiredType policy type of interest
+     * @return {@code true} if the policy type is supported, {@code false} otherwise
+     */
+    private boolean isPolicySupported(List<ToscaPolicyTypeIdentifier> supportedTypes,
+                    ToscaPolicyTypeIdentifier desiredType) {
+
+        if (supportedTypes.contains(desiredType)) {
+            return true;
+        }
+
+        String desiredTypeName = desiredType.getName();
+        for (ToscaPolicyTypeIdentifier type : supportedTypes) {
+            String supType = type.getName();
+            if (supType.endsWith(".*") && desiredTypeName.startsWith(supType.substring(0, supType.length() - 1))) {
+                // matches everything up to, AND INCLUDING, the "."
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Determines if a subgroup already contains the desired policy.
      *
 
         PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
         subgrp.setDesiredInstanceCount(30);
         subgrp.getPolicies().add(new ToscaPolicyIdentifier(POLICY2_NAME, POLICY1_VERSION));
-        subgrp.getSupportedPolicyTypes().add(new ToscaPolicyTypeIdentifier("typeX", "9.8.7"));
+        subgrp.getSupportedPolicyTypes().add(new ToscaPolicyTypeIdentifier("typeX.*", "9.8.7"));
 
         when(dao.getFilteredPolicyList(any()))
                         .thenReturn(loadPolicies("createGroupNewPolicy.json"))
         assertGroupUpdateOnly(group);
     }
 
+    /**
+     * Tests addSubgroup() when the new subgroup has a wild-card policy type.
+     *
+     * @throws Exception if an error occurs
+     */
+    @Test
+    public void testAddSubGroupWildCardPolicyType() throws Exception {
+        when(dao.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyListWildCard.json"));
+        when(dao.getPolicyTypeList("some.*", "2.3.4")).thenReturn(Collections.emptyList());
+
+        PdpGroups groups = loadPdpGroups("createGroupsWildCard.json");
+        PdpGroup group = loadPdpGroups("createGroups.json").getGroups().get(0);
+        when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+        prov.createOrUpdateGroups(groups);
+
+        PdpGroup newgrp = groups.getGroups().get(0);
+
+        PdpSubGroup newsub = newgrp.getPdpSubgroups().get(1);
+        newsub.setCurrentInstanceCount(0);
+        newsub.setPdpInstances(new ArrayList<>(0));
+
+        assertEquals(newgrp.toString(), group.toString());
+    }
+
+    /**
+     * Tests addSubgroup() when the new subgroup has a wild-card policy type, but the
+     * policy doesn't have a matching type.
+     *
+     * @throws PfModelException if an error occurs
+     */
+    @Test
+    public void testAddSubGroupWildCardPolicyTypeUnmatched() throws PfModelException {
+        when(dao.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyListWildCardUnmatched.json"));
+        when(dao.getPolicyTypeList("some.*", "2.3.4")).thenReturn(Collections.emptyList());
+
+        PdpGroups groups = loadPdpGroups("createGroupsWildCard.json");
+        PdpGroup group = loadPdpGroups("createGroups.json").getGroups().get(0);
+        when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+        assertThatThrownBy(() -> prov.createOrUpdateGroups(groups)).isInstanceOf(PfModelException.class);
+    }
+
     @Test
     public void testAddSubGroup_ValidationPolicyTypeNotFound() throws Exception {
         PdpGroups groups = loadPdpGroups("createGroupsNewSub.json");
         PdpGroup group = new PdpGroup(newgrp);
         when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
 
-        newgrp.getPdpSubgroups().get(0).getSupportedPolicyTypes().add(new ToscaPolicyTypeIdentifier("typeX", "9.8.7"));
+        newgrp.getPdpSubgroups().get(0).getSupportedPolicyTypes()
+                        .add(new ToscaPolicyTypeIdentifier("typeX.*", "9.8.7"));
 
         prov.createOrUpdateGroups(groups);
 
         prov.deployPolicies(loadEmptyRequest());
     }
 
+    /**
+     * Tests deployPolicies() when the supported policy type uses a wild-card.
+     *
+     * @throws Exception if an error occurs
+     */
+    @Test
+    public void testDeployPoliciesWildCard() throws Exception {
+        when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("deployPoliciesWildCard.json"));
+        when(dao.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyListWildCard.json"));
+        when(dao.getPolicyTypeList(any(), any())).thenReturn(Collections.emptyList());
+
+        policy1.setName("policy.some");
+        policy1.setVersion(POLICY1_VERSION);
+        policy1.setType("some.type");
+        policy1.setTypeVersion("100.2.3");
+
+        PdpDeployPolicies depreq = loadRequest();
+        depreq.getPolicies().get(0).setName("policy.some");
+
+        prov.deployPolicies(depreq);
+
+        assertGroup(getGroupUpdates(), GROUP1_NAME);
+
+        List<PdpUpdate> requests = getUpdateRequests(1);
+        assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2);
+
+        // should have notified of added policy/PDPs
+        ArgumentCaptor<PolicyPdpNotificationData> captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class);
+        verify(notifier).addDeploymentData(captor.capture());
+        assertDeploymentData(captor, policy1.getIdentifier(), "[pdpB]");
+
+        // no undeployment notifications
+        verify(notifier, never()).addUndeploymentData(any());
+    }
+
     @Test
     public void testDeploySimplePolicies() throws Exception {
         prov.deployPolicies(loadEmptyRequest());