Extract artifact component belonging logic 23/107223/8
authorFrancis Toth <francis.toth@yoppworks.com>
Mon, 4 May 2020 22:42:58 +0000 (18:42 -0400)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Thu, 28 May 2020 07:48:14 +0000 (07:48 +0000)
This commit extracts checkArtifactInComponent and checkArtifactInResourceInstance from ArtifactsBusinessLogic. Tests have been added along with a some utility functions designed to generate randomized test data. The former tests were deleted as they were not doing any assertions.

Signed-off-by: Francis Toth <francis.toth@yoppworks.com>
Change-Id: I1b27c55d064cf4e9a40cd7b152e7ea6032a09276
Issue-ID: SDC-2961

catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtils.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtilsTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/TestDataUtils.java [new file with mode: 0644]

index 17f8bde..1db7d44 100644 (file)
@@ -69,6 +69,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentEx
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.utils.ArtifactUtils;
+import org.openecomp.sdc.be.components.impl.utils.ComponentUtils;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum;
@@ -855,10 +856,10 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
         switch (componentType) {
             case RESOURCE:
             case SERVICE:
-                found = checkArtifactInComponent(component, artifactId);
+                found = ComponentUtils.checkArtifactInComponent(component, artifactId);
                 break;
             case RESOURCE_INSTANCE:
-                found = checkArtifactInResourceInstance(component, componentId, artifactId);
+                found = ComponentUtils.checkArtifactInResourceInstance(component, componentId, artifactId);
                 break;
             default:
                 found = false;
@@ -2902,108 +2903,6 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
         return downloadArtifact(artifactDefinition);
     }
 
-    private boolean checkArtifactInComponent(Component component, String artifactId) {
-        boolean found = false;
-        Map<String, ArtifactDefinition> artifactsS = component.getArtifacts();
-        if (artifactsS != null) {
-            for (Map.Entry<String, ArtifactDefinition> entry : artifactsS.entrySet()) {
-                if (entry.getValue().getUniqueId().equals(artifactId)) {
-                    found = true;
-                    break;
-                }
-            }
-        }
-        Map<String, ArtifactDefinition> deploymentArtifactsS = component.getDeploymentArtifacts();
-        if (!found && deploymentArtifactsS != null) {
-            for (Map.Entry<String, ArtifactDefinition> entry : deploymentArtifactsS.entrySet()) {
-                if (entry.getValue().getUniqueId().equals(artifactId)) {
-                    found = true;
-                    break;
-                }
-            }
-        }
-        Map<String, ArtifactDefinition> toscaArtifactsS = component.getToscaArtifacts();
-        if (!found && toscaArtifactsS != null) {
-            for (Map.Entry<String, ArtifactDefinition> entry : toscaArtifactsS.entrySet()) {
-                if (entry.getValue().getUniqueId().equals(artifactId)) {
-                    found = true;
-                    break;
-                }
-            }
-        }
-
-        Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
-        if (!found && interfaces != null) {
-            for (Map.Entry<String, InterfaceDefinition> entry : interfaces.entrySet()) {
-                Map<String, Operation> operations = entry.getValue().getOperationsMap();
-                for (Map.Entry<String, Operation> entryOp : operations.entrySet()) {
-                    if (entryOp.getValue().getImplementation() != null && entryOp.getValue()
-                            .getImplementation()
-                            .getUniqueId()
-                            .equals(artifactId)) {
-                        found = true;
-                        break;
-                    }
-                }
-            }
-        }
-        switch (component.getComponentType()) {
-            case RESOURCE:
-                break;
-            case SERVICE:
-                Map<String, ArtifactDefinition> apiArtifacts = ((Service) component).getServiceApiArtifacts();
-                if (!found && apiArtifacts != null) {
-                    for (Map.Entry<String, ArtifactDefinition> entry : apiArtifacts.entrySet()) {
-                        if (entry.getValue().getUniqueId().equals(artifactId)) {
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-                break;
-            default:
-
-        }
-
-        return found;
-    }
-
-    private boolean checkArtifactInResourceInstance(Component component, String resourceInstanceId, String artifactId) {
-
-        boolean found = false;
-        List<ComponentInstance> resourceInstances = component.getComponentInstances();
-        ComponentInstance resourceInstance = null;
-        for (ComponentInstance ri : resourceInstances) {
-            if (ri.getUniqueId().equals(resourceInstanceId)) {
-                resourceInstance = ri;
-                break;
-            }
-        }
-        if (resourceInstance != null) {
-            Map<String, ArtifactDefinition> artifacts = resourceInstance.getDeploymentArtifacts();
-            if (artifacts != null) {
-                for (Map.Entry<String, ArtifactDefinition> entry : artifacts.entrySet()) {
-                    if (entry.getValue().getUniqueId().equals(artifactId)) {
-                        found = true;
-                        break;
-                    }
-                }
-            }
-            if (!found) {
-                artifacts = resourceInstance.getArtifacts();
-                if (artifacts != null) {
-                    for (Map.Entry<String, ArtifactDefinition> entry : artifacts.entrySet()) {
-                        if (entry.getValue().getUniqueId().equals(artifactId)) {
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        return found;
-    }
-
     private Component validateComponentExists(String componentId, AuditingActionEnum auditingAction, User user, String artifactId, ComponentTypeEnum componentType,
                                               String containerComponentType) {
 
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtils.java
new file mode 100644 (file)
index 0000000..02176d9
--- /dev/null
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl.utils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.Service;
+
+public final class ComponentUtils {
+
+    private ComponentUtils() {
+    }
+
+    public static boolean checkArtifactInComponent(
+        Component component, String artifactId
+    ) {
+        Predicate<ArtifactDefinition> hasSameArtifactId =
+            ad -> ad != null && ad.getUniqueId().equals(artifactId);
+
+        return exists(component.getArtifacts(), hasSameArtifactId) ||
+            exists(component.getDeploymentArtifacts(), hasSameArtifactId) ||
+            exists(component.getToscaArtifacts(), hasSameArtifactId) ||
+            hasOperationImplementationWithUniqueId(component, artifactId) ||
+            isServiceAndHasApiArtifactWithUniqueId(component, hasSameArtifactId);
+    }
+
+    private static boolean isServiceAndHasApiArtifactWithUniqueId(Component component,
+        Predicate<ArtifactDefinition> hasSameArtifactId) {
+        return component.getComponentType() == ComponentTypeEnum.SERVICE && exists(
+            ((Service) component).getServiceApiArtifacts(), hasSameArtifactId);
+    }
+
+    private static boolean hasOperationImplementationWithUniqueId(Component component, String artifactId) {
+        return findFirst(valueStream(component.getInterfaces())
+                .flatMap(v -> valueStream(v.getOperationsMap()))
+                .map(OperationDataDefinition::getImplementation),
+            e -> e != null && e.getUniqueId().equals(artifactId)
+        ).isPresent();
+    }
+
+    public static boolean checkArtifactInResourceInstance(
+        Component component, String resourceInstanceId, String artifactId
+    ) {
+        Predicate<ComponentInstance> hasSameResourceId =
+            ri -> ri != null && ri.getUniqueId().equals(resourceInstanceId);
+
+        Predicate<ArtifactDefinition> hasSameArtifactId =
+            ad -> ad != null && ad.getUniqueId().equals(artifactId);
+
+        return findFirst(component.getComponentInstances(), hasSameResourceId).map(ri ->
+            exists(ri.getDeploymentArtifacts(), hasSameArtifactId) ||
+                exists(ri.getArtifacts(), hasSameArtifactId)
+        ).isPresent();
+    }
+
+    private static <V> Optional<V> findFirst(List<V> ovs, Predicate<V> p) {
+        return Optional.ofNullable(ovs).flatMap(vs -> findFirst(vs.stream(), p));
+    }
+
+    private static <K, V> boolean exists(Map<K, V> okvs, Predicate<V> p) {
+        return Optional.ofNullable(okvs)
+            .flatMap(kvs -> findFirst(kvs.values().stream(), p))
+            .isPresent();
+    }
+
+    private static <V> Optional<V> findFirst(Stream<V> vs, Predicate<V> p) {
+        return Optional.ofNullable(vs).flatMap(ms -> ms.filter(p).findFirst());
+    }
+
+    private static <K, V> Stream<V> valueStream(Map<K, V> okvs) {
+        return Optional.ofNullable(okvs).map(kvs -> kvs.values().stream()).orElse(Stream.empty());
+    }
+}
index 6f0b83b..c514565 100644 (file)
@@ -844,20 +844,6 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
         return getTestSubject();
     }
 
-    @Test
-    public void testCheckArtifactInComponent() throws Exception {
-        ArtifactsBusinessLogic testSubject;
-        Component component = new Resource();
-        component.setComponentType(ComponentTypeEnum.RESOURCE);
-        String artifactId = "";
-        boolean result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = Deencapsulation.invoke(testSubject, "checkArtifactInComponent",
-                new Object[]{component, artifactId});
-    }
-
     @Test
     public void testCheckCreateFields() throws Exception {
         ArtifactsBusinessLogic testSubject;
@@ -936,7 +922,6 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
                 artifactId, component, artifacts);
     }
 
-
     @Test
     public void testValidateArtifact() throws Exception {
         ArtifactsBusinessLogic testSubject;
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/ComponentUtilsTest.java
new file mode 100644 (file)
index 0000000..bf9ecaf
--- /dev/null
@@ -0,0 +1,130 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl.utils;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.openecomp.sdc.be.components.impl.utils.ComponentUtils.checkArtifactInComponent;
+import static org.openecomp.sdc.be.components.impl.utils.ComponentUtils.checkArtifactInResourceInstance;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.aComponent;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.aComponentInstance;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.aResourceInstanceId;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.aUniqueId;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.anArtifactDefinition;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.anArtifactId;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.anOperation;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.someArtifacts;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.someComponentInstances;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.someInterfaces;
+import static org.openecomp.sdc.be.components.impl.utils.TestDataUtils.someOperations;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.Operation;
+import org.openecomp.sdc.be.model.Service;
+
+public class ComponentUtilsTest {
+
+    private static final String ARTIFACT_ID = "SomeArtifactId";
+
+    @Test
+    public void checkArtifactInComponentShouldReturnFalseWhenNoConditionsAreMet() {
+        assertFalse(checkArtifactInComponent(aComponent(), ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInComponentShouldReturnTrueWhenOneArtifactHasQueriedId() {
+        Component component = aComponent();
+        component.setArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+        assertTrue(checkArtifactInComponent(component, ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInComponentShouldReturnTrueWhenOneDeploymentArtifactHasQueriedId() {
+        Component component = aComponent();
+        component.setDeploymentArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+        assertTrue(checkArtifactInComponent(component, ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInComponentShouldReturnTrueWhenOneToscaArtifactHasQueriedId() {
+        Component component = aComponent();
+        component.setToscaArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+        assertTrue(checkArtifactInComponent(component, ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInComponentShouldReturnTrueWhenOneOperationHasQueriedId() {
+        Component component = aComponent();
+        component.setInterfaces(someInterfaces(anInterfaceDefinition(ARTIFACT_ID)));
+        assertTrue(checkArtifactInComponent(component, ARTIFACT_ID));
+    }
+
+    private static InterfaceDefinition anInterfaceDefinition(String artifactUniqueId) {
+        Map<String, Operation> operations = someOperations(
+            anOperation(aUniqueId(), anArtifactDefinition(artifactUniqueId)));
+
+        InterfaceDefinition id = new InterfaceDefinition();
+        id.setOperationsMap(operations);
+
+        return id;
+    }
+
+    @Test
+    public void checkArtifactInComponentShouldReturnTrueWhenServiceHasArtifactsWithQueriedId() {
+        Service service = new Service();
+        service.setComponentType(ComponentTypeEnum.SERVICE);
+        service.setServiceApiArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+
+        assertTrue(checkArtifactInComponent(service, ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInResourceInstanceShouldReturnFalseWhenNoConditionIsMet() {
+        assertFalse(checkArtifactInResourceInstance(aComponent(), aResourceInstanceId(), anArtifactId()));
+    }
+
+    @Test
+    public void checkArtifactInResourceInstanceShouldReturnTrueWhenResourceHasQueriedIdAndDeploymentArtifactId() {
+        ComponentInstance ci = aComponentInstance(aResourceInstanceId());
+        ci.setDeploymentArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+
+        Component component = aComponent();
+        component.setComponentInstances(someComponentInstances(ci));
+
+        assertTrue(checkArtifactInResourceInstance(component, ci.getUniqueId(), ARTIFACT_ID));
+    }
+
+    @Test
+    public void checkArtifactInResourceInstanceShouldReturnTrueWhenResourceHasQueriedIdAndArtifactId() {
+        ComponentInstance ci = aComponentInstance(aResourceInstanceId());
+        ci.setArtifacts(someArtifacts(anArtifactDefinition(ARTIFACT_ID)));
+
+        Component component = aComponent();
+        component.setComponentInstances(someComponentInstances(ci));
+
+        assertTrue(checkArtifactInResourceInstance(component, ci.getUniqueId(), ARTIFACT_ID));
+    }
+}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/TestDataUtils.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/TestDataUtils.java
new file mode 100644 (file)
index 0000000..bc7d57a
--- /dev/null
@@ -0,0 +1,185 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.function.Function;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.Operation;
+import org.openecomp.sdc.be.model.Product;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.Service;
+
+/**
+ * This class provides some utility functions to generate close to randomized data for testing purpose.
+ */
+public class TestDataUtils {
+
+    private TestDataUtils() {
+    }
+
+    /**
+     * Generates a random {@code Component}
+     */
+    public static Component aComponent() {
+        return oneOf(new Resource(), new Service(), new Product());
+    }
+
+    /**
+     * Generates a random map of {@code ArtifactDefinition}
+     */
+    public static Map<String, ArtifactDefinition> someArtifacts(ArtifactDefinition a, ArtifactDefinition... as) {
+        return some(ArtifactDataDefinition::getUniqueId, a, as);
+    }
+
+    /**
+     * Generates a random {@code ArtifactDefinition} provided with a unique id
+     */
+    public static ArtifactDefinition anArtifactDefinition(String uniqueId) {
+        ArtifactDefinition ad = new ArtifactDefinition();
+        ad.setUniqueId(uniqueId);
+        return ad;
+    }
+
+    /**
+     * Converts  n {@code ComponentInstance} to {@code List<ComponentInstance>}
+     */
+    public static List<ComponentInstance> someComponentInstances(ComponentInstance ci, ComponentInstance... cis) {
+        return varargs(ci, cis);
+    }
+
+    /**
+     * Generates a random {@code ComponentInstance} provided with a unique id
+     */
+    public static ComponentInstance aComponentInstance(String uniqueId) {
+        ComponentInstance ci = new ComponentInstance();
+        ci.setUniqueId(uniqueId);
+        return ci;
+    }
+
+    /**
+     * Converts  n {@code Operation} to {@code List<Operation>}
+     */
+    public static Map<String, Operation> someOperations(Operation o, Operation... os) {
+        return some(Operation::getUniqueId, o, os);
+    }
+
+    /**
+     * Generates a random {@code Operation} provided with a unique id and an implementation
+     */
+    public static Operation anOperation(String uniqueId, ArtifactDefinition implementation) {
+        Operation o = new Operation();
+        o.setUniqueId(uniqueId);
+        o.setImplementation(implementation);
+        return o;
+    }
+
+    /**
+     * Converts  n {@code InterfaceDefinition} to a {@code Map<String, InterfaceDefinition>}
+     */
+    public static Map<String, InterfaceDefinition> someInterfaces(InterfaceDefinition a, InterfaceDefinition... as) {
+        return some(InterfaceDefinition::getUniqueId, a, as);
+    }
+
+    /**
+     * Generates a {@code Map} given a function to generate a key from a value, along with the values to put in the
+     * resulting {@code Map}.
+     *
+     * @param keyMapper A function to generate a key from a value
+     * @param v0        The first element to put in the {@code Map}
+     * @param vs        The other elements to put on the {@code Map}
+     * @param <K>       The type of a key
+     * @param <V>       The type of a value
+     */
+    @SafeVarargs
+    public static <K, V> Map<K, V> some(Function<V, K> keyMapper, V v0, V... vs) {
+        HashMap<K, V> m = new HashMap<>();
+        for (V v : varargs(v0, vs)) {
+            m.put(keyMapper.apply(v), v);
+        }
+        return m;
+    }
+
+    /**
+     * Alias for {@code aUniqueId}
+     */
+    public static String anArtifactId() {
+        return alphaNum(10);
+    }
+
+    /**
+     * Alias for {@code aUniqueId}
+     */
+    public static String aResourceInstanceId() {
+        return alphaNum(10);
+    }
+
+    /**
+     * Generates a uniqueId
+     */
+    public static String aUniqueId() {
+        return alphaNum(10);
+    }
+
+    /**
+     * Generates an alphanumeric string
+     *
+     * @param size The size of the {@code String} returned
+     */
+    public static String alphaNum(int size) {
+        return alphaNum("", size, new Random());
+    }
+
+    private static String alphaNum(String acc, int rem, Random r) {
+        if (rem == 0) {
+            return acc;
+        } else {
+            String alphaNum = "0123456789abcdefghijklmnopqrstuvwxyz";
+            return alphaNum(acc + alphaNum.charAt(r.nextInt(alphaNum.length())), rem - 1, r);
+        }
+    }
+
+    /**
+     * Randomly selects one value among the ones provided
+     */
+    @SafeVarargs
+    public static <A> A oneOf(A a, A... as) {
+        List<A> as0 = varargs(a, as);
+        Random r = new Random();
+        return as0.get(r.nextInt(as0.size()));
+    }
+
+    @SafeVarargs
+    private static <A> List<A> varargs(A a, A... as) {
+        ArrayList<A> as0 = new ArrayList<>(Arrays.asList(as));
+        as0.add(a);
+        return as0;
+    }
+}