diff --git a/src/main/java/it/inaf/oats/vospace/datamodel/NodeProperties.java b/src/main/java/it/inaf/oats/vospace/datamodel/NodeProperties.java
index fbc098a9ef05a0a4b6610cb4060537d2c78a5fb2..3661f693a74ffca0b58e0ab6e61bea4584289dfc 100644
--- a/src/main/java/it/inaf/oats/vospace/datamodel/NodeProperties.java
+++ b/src/main/java/it/inaf/oats/vospace/datamodel/NodeProperties.java
@@ -1,88 +1,71 @@
 package it.inaf.oats.vospace.datamodel;
 
 import java.util.List;
-import java.util.stream.Collectors;
 import net.ivoa.xml.vospace.v2.Node;
 import net.ivoa.xml.vospace.v2.Property;
 
 public abstract class NodeProperties {
-    
-    
-    private NodeProperties() { }
-    
+
+    private NodeProperties() {
+    }
+
     public static final String BASE_URI = "ivo://ivoa.net/vospace/core#";
     public static final String AVAILABLE_SPACE_URI = "ivo://ivoa.net/vospace/core#availableSpace";      // the amount of space available within a container      
-    public static final String INITIAL_CREATION_TIME_URI  = "ivo://ivoa.net/vospace/core#btime";       // the initial creation time
-    public static final String CONTRIBUTOR_URI  = "ivo://ivoa.net/vospace/core#contributor"; // an entity responsible for making contributions to this resource
-    public static final String COVERAGE_URI  = "ivo://ivoa.net/vospace/core#coverage";    // a spatial or temporal topic of the resource, the spatial applicability of the resource, or the jurisdiction under which the resource is relevant      
-    public static final String CREATOR_URI  = "ivo://ivoa.net/vospace/core#creator";     // an entity primarily responsible for making the resource
-    public static final String STATUS_CHANGE_TIME_URI  = "ivo://ivoa.net/vospace/core#ctime";       // the status change (aka metadata modification) time    
-    public static final String DATE_URI  = "ivo://ivoa.net/vospace/core#date";        // a point or period of time associated with an event in the lifecycle of the resource
-    public static final String DESCRIPTION_URI  = "ivo://ivoa.net/vospace/core#description"; // an account of the resource    
-    public static final String FORMAT_URI  = "ivo://ivoa.net/vospace/core#format";      // the file format, physical medium or dimensions of the resource
-    public static final String GROUP_READ_URI  = "ivo://ivoa.net/vospace/core#groupread";   // the list of groups which can only read this resource  delimiter-separated 
-    public static final String GROUP_WRITE_URI  = "ivo://ivoa.net/vospace/core#groupwrite";  // the list of groups which can read and write to this resource  delimiter-separated 
-    public static final String IDENTIFIER_URI  = "ivo://ivoa.net/vospace/core#identifier";  // an unambiguous reference to the resource within a given context
-    public static final String LANGUAGE_URI  = "ivo://ivoa.net/vospace/core#language";    // a language of the resource    
-    public static final String LENGTH_URI  = "ivo://ivoa.net/vospace/core#length";      // the length or size of a resource      
-    public static final String MODIFICATION_TIME_URI  = "ivo://ivoa.net/vospace/core#mtime";       // the data modification time    
-    public static final String PUBLIC_READ_URI  = "ivo://ivoa.net/vospace/core#publicread";  // whether this resource is world readable
-    public static final String PUBLISHER_URI  = "ivo://ivoa.net/vospace/core#publisher";   // an entity responsible for making the resource available
-    public static final String QUOTA_URI  = "ivo://ivoa.net/vospace/core#quota";       // the value of a system quota on the resource   
-    public static final String RELATED_RESOURCE_URI  = "ivo://ivoa.net/vospace/core#relation";    // a related resource    
-    public static final String RIGHTS_ON_URI  = "ivo://ivoa.net/vospace/core#rights";      // information about rights held in and over the resource
-    public static final String RESOURCE_RELATED_URI  = "ivo://ivoa.net/vospace/core#source";      // a related resource from which the described resource is derived
-    public static final String SUBJECT_URI  = "ivo://ivoa.net/vospace/core#subject";     // the topic of the resource     
-    public static final String TITLE_URI  = "ivo://ivoa.net/vospace/core#title";       // a name given to the resource  
-    public static final String TYPE_URI  = "ivo://ivoa.net/vospace/core#type";        // the nature or genre of the resource
+    public static final String INITIAL_CREATION_TIME_URI = "ivo://ivoa.net/vospace/core#btime";       // the initial creation time
+    public static final String CONTRIBUTOR_URI = "ivo://ivoa.net/vospace/core#contributor"; // an entity responsible for making contributions to this resource
+    public static final String COVERAGE_URI = "ivo://ivoa.net/vospace/core#coverage";    // a spatial or temporal topic of the resource, the spatial applicability of the resource, or the jurisdiction under which the resource is relevant      
+    public static final String CREATOR_URI = "ivo://ivoa.net/vospace/core#creator";     // an entity primarily responsible for making the resource
+    public static final String STATUS_CHANGE_TIME_URI = "ivo://ivoa.net/vospace/core#ctime";       // the status change (aka metadata modification) time    
+    public static final String DATE_URI = "ivo://ivoa.net/vospace/core#date";        // a point or period of time associated with an event in the lifecycle of the resource
+    public static final String DESCRIPTION_URI = "ivo://ivoa.net/vospace/core#description"; // an account of the resource    
+    public static final String FORMAT_URI = "ivo://ivoa.net/vospace/core#format";      // the file format, physical medium or dimensions of the resource
+    public static final String GROUP_READ_URI = "ivo://ivoa.net/vospace/core#groupread";   // the list of groups which can only read this resource  delimiter-separated 
+    public static final String GROUP_WRITE_URI = "ivo://ivoa.net/vospace/core#groupwrite";  // the list of groups which can read and write to this resource  delimiter-separated 
+    public static final String IDENTIFIER_URI = "ivo://ivoa.net/vospace/core#identifier";  // an unambiguous reference to the resource within a given context
+    public static final String LANGUAGE_URI = "ivo://ivoa.net/vospace/core#language";    // a language of the resource    
+    public static final String LENGTH_URI = "ivo://ivoa.net/vospace/core#length";      // the length or size of a resource      
+    public static final String MODIFICATION_TIME_URI = "ivo://ivoa.net/vospace/core#mtime";       // the data modification time    
+    public static final String PUBLIC_READ_URI = "ivo://ivoa.net/vospace/core#publicread";  // whether this resource is world readable
+    public static final String PUBLISHER_URI = "ivo://ivoa.net/vospace/core#publisher";   // an entity responsible for making the resource available
+    public static final String QUOTA_URI = "ivo://ivoa.net/vospace/core#quota";       // the value of a system quota on the resource   
+    public static final String RELATED_RESOURCE_URI = "ivo://ivoa.net/vospace/core#relation";    // a related resource    
+    public static final String RIGHTS_ON_URI = "ivo://ivoa.net/vospace/core#rights";      // information about rights held in and over the resource
+    public static final String RESOURCE_RELATED_URI = "ivo://ivoa.net/vospace/core#source";      // a related resource from which the described resource is derived
+    public static final String SUBJECT_URI = "ivo://ivoa.net/vospace/core#subject";     // the topic of the resource     
+    public static final String TITLE_URI = "ivo://ivoa.net/vospace/core#title";       // a name given to the resource  
+    public static final String TYPE_URI = "ivo://ivoa.net/vospace/core#type";        // the nature or genre of the resource
     //
     // Non-standard properties
     public static final String ASYNC_TRANS_URN = "urn:async_trans";
     public static final String STICKY_URN = "urn:sticky";
-    
-    
 
-    
     public static String getStandardNodePropertyByName(Node node, String propertyName) {
         return getNodePropertyByURI(node, BASE_URI.concat(propertyName));
     }
 
-
-    public static String getProperty(Node node, String propertyName) {
-
-        for (Property property : node.getProperties()) {
-            if (property.getUri().equals(BASE_URI.concat(propertyName))) {
-                return property.getValue();
-            }
-        }
-        return null;
-    }
-    
-
     public static String getNodePropertyByURI(Node node, String uri) {
-        
+
         for (Property property : node.getProperties()) {
             if (uri.equals(property.getUri())) {
                 return property.getValue();
             }
         }
         return null;
-        
     }
+
     // Returns all properties stored inside the node under the requested
     // property URI.    
     public static List<String> getNodePropertyAsListByURI(Node node, String propertyURI) {
+        String property = getNodePropertyByURI(node, propertyURI);
+        return parsePropertyStringToList(property);
+    }
 
-        List<String> propertyList = node.getProperties().stream()
-                .filter((i) -> i.getUri()
-                .equals(propertyURI))
-                .map((i) -> i.getValue())
-                .collect(Collectors.toList());
+    private static List<String> parsePropertyStringToList(String property) {
 
-        return propertyList;
-    }
+        if (property == null) {
+            return List.of();
+        }
 
-    public static List<String> parsePropertyStringToList(String property) {
         // If separator changes, this method should remain consistent
         // For now it assumes that " " is the separator        
         String separator = " ";
@@ -93,7 +76,5 @@ public abstract class NodeProperties {
         }
 
         return List.of(trimmedProperty.split(separator));
-
     }
-    
 }
diff --git a/src/main/java/it/inaf/oats/vospace/datamodel/NodeUtils.java b/src/main/java/it/inaf/oats/vospace/datamodel/NodeUtils.java
index 22b131fd4d882ddc0119aba1b7780665d19a9d4c..2021bdbfd4fe1c18ea142e34ac93e234ed762571 100644
--- a/src/main/java/it/inaf/oats/vospace/datamodel/NodeUtils.java
+++ b/src/main/java/it/inaf/oats/vospace/datamodel/NodeUtils.java
@@ -110,13 +110,11 @@ public class NodeUtils {
         }
 
         return resultList;
-
     }
 
     public static boolean checkIfWritable(Node myNode, String userName, List<String> userGroups) {
 
-        return checkAccessPropery(myNode, userName, userGroups, NodeProperties.GROUP_WRITE_URI);
-
+        return checkAccessProperty(myNode, userName, userGroups, NodeProperties.GROUP_WRITE_URI);
     }
 
     public static boolean checkIfReadable(Node myNode, String userName, List<String> userGroups) {
@@ -125,20 +123,18 @@ public class NodeUtils {
             return true;
         }
 
-        return checkAccessPropery(myNode, userName, userGroups, NodeProperties.GROUP_READ_URI);
-
+        return checkAccessProperty(myNode, userName, userGroups, NodeProperties.GROUP_READ_URI);
     }
 
-    public static boolean checkAccessPropery(Node myNode, String userName,
+    private static boolean checkAccessProperty(Node myNode, String userName,
             List<String> userGroups, String accessPropertyName) {
 
         // First check if parent node creator is == userid
-        List<String> nodeOwner
-                = NodeProperties.getNodePropertyAsListByURI(myNode, NodeProperties.CREATOR_URI);
+        String nodeOwner = NodeProperties.getNodePropertyByURI(myNode, NodeProperties.CREATOR_URI);
 
         if (nodeOwner == null
                 || nodeOwner.isEmpty()
-                || !nodeOwner.get(0).equals(userName)) {
+                || !nodeOwner.equals(userName)) {
             // Node owner check has failed: let's check if user can write
             // due to group privileges
 
@@ -157,11 +153,8 @@ public class NodeUtils {
                 return false;
             }
 
-            List<String> nodeGroups
-                    = NodeProperties.parsePropertyStringToList(groupAccessPropValues.get(0));
-
-            if (nodeGroups.isEmpty()
-                    || !nodeGroups.stream()
+            if (groupAccessPropValues.isEmpty()
+                    || !groupAccessPropValues.stream()
                             .anyMatch((i) -> userGroups.contains(i))) {
                 return false;
             }
@@ -170,9 +163,6 @@ public class NodeUtils {
 
         return true;
     }
-    
-        
-        
 
     public static String getDbNodeType(Node node) {
         if (node instanceof ContainerNode) {
@@ -182,7 +172,6 @@ public class NodeUtils {
         }
         throw new UnsupportedOperationException("Unable to retrieve database node type for class " + node.getClass().getCanonicalName());
     }
-     
 
     public static String getNodeName(String path) {
         String[] parsedPath = path.split("/");
@@ -190,12 +179,10 @@ public class NodeUtils {
         return parsedPath[parsedPath.length - 1];
     }
 
-    
     public static String getNodeName(Node myNode) {
         String uri = myNode.getUri();
         return getNodeName(uri);
     }
-        
 
     public static boolean getIsBusy(Node myNode) {
 
@@ -207,8 +194,7 @@ public class NodeUtils {
 
         return false;
     }
-    
-    
+
     public static Node getTypedNode(String type) {
         Node node;
         switch (type) {
@@ -226,14 +212,12 @@ public class NodeUtils {
         }
         return node;
     }
-    
-    
+
     public static String getVosPath(Node myNode) {
-       
-       String nodeUri = myNode.getUri();
-       
-       return nodeUri.replaceAll("vos://[^/]+", "");
-   }
-    
+
+        String nodeUri = myNode.getUri();
+
+        return nodeUri.replaceAll("vos://[^/]+", "");
+    }
 
 }
diff --git a/src/test/java/it/inaf/oats/vospace/datamodel/NodePropertiesTest.java b/src/test/java/it/inaf/oats/vospace/datamodel/NodePropertiesTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1457f90fd1107c9ac24a06d0cb182e565386fd7
--- /dev/null
+++ b/src/test/java/it/inaf/oats/vospace/datamodel/NodePropertiesTest.java
@@ -0,0 +1,28 @@
+package it.inaf.oats.vospace.datamodel;
+
+import java.util.List;
+import net.ivoa.xml.vospace.v2.DataNode;
+import net.ivoa.xml.vospace.v2.Node;
+import net.ivoa.xml.vospace.v2.Property;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+
+public class NodePropertiesTest {
+
+    @Test
+    public void testGetNodePropertyAsListByURI() {
+
+        Property groupRead = new Property();
+        groupRead.setUri(NodeProperties.GROUP_READ_URI);
+        groupRead.setValue("group1 group2");
+
+        Node node = new DataNode();
+        node.getProperties().add(groupRead);
+        
+        List<String> values = NodeProperties.getNodePropertyAsListByURI(node, NodeProperties.GROUP_READ_URI);
+
+        assertEquals(2, values.size());
+        assertEquals("group1", values.get(0));
+        assertEquals("group2", values.get(1));
+    }
+}
diff --git a/src/test/java/it/inaf/oats/vospace/datamodel/NodeUtilsTest.java b/src/test/java/it/inaf/oats/vospace/datamodel/NodeUtilsTest.java
index 065dd2014e84c8f45eeb04dd79afcadda15545ab..13df807889f49a0ba3ec6e653dafba92fbf9b0b3 100644
--- a/src/test/java/it/inaf/oats/vospace/datamodel/NodeUtilsTest.java
+++ b/src/test/java/it/inaf/oats/vospace/datamodel/NodeUtilsTest.java
@@ -2,8 +2,14 @@ package it.inaf.oats.vospace.datamodel;
 
 import java.util.ArrayList;
 import java.util.List;
+import net.ivoa.xml.vospace.v2.ContainerNode;
+import net.ivoa.xml.vospace.v2.DataNode;
+import net.ivoa.xml.vospace.v2.LinkNode;
+import net.ivoa.xml.vospace.v2.Node;
+import net.ivoa.xml.vospace.v2.Property;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import org.junit.jupiter.api.Test;
 
@@ -44,7 +50,7 @@ public class NodeUtilsTest {
     public void testIllegalQuotes() {
         testIllegalChars("\"'.pdf");
     }
-    
+
     @Test
     public void testIllegalSlashEncoded() {
         testIllegalChars("%2F.pdf");
@@ -60,77 +66,203 @@ public class NodeUtilsTest {
         assertTrue(exception);
     }
 
-    //@Test
+    @Test
     public void getPathFromRequestURLStringTest() {
-        
-        
+
         String urlForTest = "http://server.example.com/vospace/";
         String result = NodeUtils.getPathFromRequestURLString(urlForTest);
         assertEquals("/", result);
-        
+
         urlForTest = "http://server.example.com/vospace/nodes";
         result = NodeUtils.getPathFromRequestURLString(urlForTest);
         assertEquals("/", result);
-        
+
         urlForTest = "http://server.example.com/vospace/nodes/mydata";
         result = NodeUtils.getPathFromRequestURLString(urlForTest);
         assertEquals("/mydata", result);
-        
+
         urlForTest = "http://server.example.com/vospace/nodes/mydata1/uffi/nonso/pappa.txt";
         result = NodeUtils.getPathFromRequestURLString(urlForTest);
         assertEquals("/mydata1/uffi/nonso/pappa.txt", result);
     }
-     
-    /* Is it a possible case?
+
+    // Is it a possible case?
     @Test
     public void subPathComponentsTest1() {
-        
-        //assertArrayEquals(expected, actual)
         String pathForTest = "";
-        List result = NodeUtils.subPathComponents(pathForTest);
-        List expected = new ArrayList();     // expected empty
-        assertArrayEquals(expected.toArray(), result.toArray());
-        
+        List<String> result = NodeUtils.subPathComponents(pathForTest);
+        assertTrue(result.isEmpty());
     }
-    */
-        
+
     @Test
     public void subPathComponentsTest2() {
-        
+
         String pathForTest = "/";
-        List result = NodeUtils.subPathComponents(pathForTest);
-        List expected = new ArrayList();
+        List<String> result = NodeUtils.subPathComponents(pathForTest);
+        List<String> expected = new ArrayList<>();
         expected.add("/");
         assertArrayEquals(expected.toArray(), result.toArray());
-        
-                
-    }   
-    
-        
-    @Test
-    public void subPathComponentsTest3() {        
-        
+    }
+
+    @Test
+    public void subPathComponentsTest3() {
+
         String pathForTest = "/mynode1";
-        List result = NodeUtils.subPathComponents(pathForTest);
-        List expected = new ArrayList();
+        List<String> result = NodeUtils.subPathComponents(pathForTest);
+        List<String> expected = new ArrayList<>();
         expected.add("/mynode1");
         assertArrayEquals(expected.toArray(), result.toArray());
-        
     }
-    
-        
+
     @Test
     public void subPathComponentsTest4() {
-        
-        //assertArrayEquals(expected, actual)
+
         String pathForTest = "/mydata1/uffi/nonso/pappa.txt";
-        List result = NodeUtils.subPathComponents(pathForTest);
-        List expected = new ArrayList();
+        List<String> result = NodeUtils.subPathComponents(pathForTest);
+        List<String> expected = new ArrayList<>();
         expected.add("/mydata1");
         expected.add("/mydata1/uffi");
         expected.add("/mydata1/uffi/nonso");
         expected.add("/mydata1/uffi/nonso/pappa.txt");
         assertArrayEquals(expected.toArray(), result.toArray());
-        
+    }
+
+    @Test
+    public void testCheckReadablePublicNode() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+        Property publicRead = getProperty(NodeProperties.PUBLIC_READ_URI, "true");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+        node.getProperties().add(publicRead);
+
+        assertTrue(NodeUtils.checkIfReadable(node, "user3", List.of()));
+    }
+
+    @Test
+    public void testCheckReadableCreatorOnly() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+
+        assertTrue(NodeUtils.checkIfReadable(node, "user1", List.of()));
+    }
+
+    @Test
+    public void testCheckReadableGroupsTrue() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+        Property groupWrite = getProperty(NodeProperties.GROUP_READ_URI, "group3 group4");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+        node.getProperties().add(groupWrite);
+
+        assertTrue(NodeUtils.checkIfReadable(node, "user2", List.of("group2", "group3")));
+    }
+
+    @Test
+    public void testCheckReadableGroupsFalse() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+        Property groupWrite = getProperty(NodeProperties.GROUP_READ_URI, "group3 group4");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+        node.getProperties().add(groupWrite);
+
+        assertFalse(NodeUtils.checkIfReadable(node, "user2", List.of("group5", "group6")));
+    }
+
+    @Test
+    public void testCheckWritableCreatorOnly() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+
+        assertTrue(NodeUtils.checkIfWritable(node, "user1", List.of()));
+    }
+
+    @Test
+    public void testCheckWritableGroupsTrue() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+        Property groupWrite = getProperty(NodeProperties.GROUP_WRITE_URI, "group3 group4");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+        node.getProperties().add(groupWrite);
+
+        assertTrue(NodeUtils.checkIfWritable(node, "user2", List.of("group2", "group3")));
+    }
+
+    @Test
+    public void testCheckWritableGroupsFalse() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+        Property groupWrite = getProperty(NodeProperties.GROUP_WRITE_URI, "group3 group4");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+        node.getProperties().add(groupWrite);
+
+        assertFalse(NodeUtils.checkIfWritable(node, "user2", List.of("group5", "group6")));
+    }
+
+    @Test
+    public void testCheckWritableNoGroups() {
+
+        Property creator = getProperty(NodeProperties.CREATOR_URI, "user1");
+
+        Node node = new DataNode();
+        node.getProperties().add(creator);
+
+        assertFalse(NodeUtils.checkIfWritable(node, "user2", List.of()));
+    }
+
+    @Test
+    public void testGetVosPath() {
+
+        Node node = new DataNode();
+        node.setUri("vos://example.com!vospace/mynode/child1/child2");
+
+        assertEquals("/mynode/child1/child2", NodeUtils.getVosPath(node));
+    }
+
+    @Test
+    public void testGetParentPath() {
+        assertEquals("/node1/node2", NodeUtils.getParentPath("/node1/node2/node2"));
+    }
+
+    @Test
+    public void testIsBusy() {
+        DataNode node = new DataNode();
+        node.setBusy(true);
+        assertTrue(NodeUtils.getIsBusy(node));
+    }
+
+    @Test
+    public void testIsNeverBusy() {
+        LinkNode node = new LinkNode();
+        assertFalse(NodeUtils.getIsBusy(node));
+    }
+
+    @Test
+    public void testGetNodeName() {
+        Node node = new DataNode();
+        node.setUri("vos://example.com!vospace/mynode/child1/child2");
+        assertEquals("child2", NodeUtils.getNodeName(node));
+    }
+
+    private Property getProperty(String uri, String value) {
+        Property property = new Property();
+        property.setUri(uri);
+        property.setValue(value);
+        return property;
     }
 }