Repository: cloudstack
Updated Branches:
  refs/heads/4.4 4723fbb83 -> ec5ee761d


Refactor listNetworks logic to use new IAM model.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ec5ee761
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ec5ee761
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ec5ee761

Branch: refs/heads/4.4
Commit: ec5ee761d98c67c7da2ea70b623d4a9f3da966b5
Parents: 4723fbb
Author: Min Chen <[email protected]>
Authored: Tue Mar 18 16:07:22 2014 -0700
Committer: Min Chen <[email protected]>
Committed: Tue Mar 18 16:47:08 2014 -0700

----------------------------------------------------------------------
 .../com/cloud/network/NetworkServiceImpl.java   | 326 ++++---------------
 1 file changed, 65 insertions(+), 261 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ec5ee761/server/src/com/cloud/network/NetworkServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java 
b/server/src/com/cloud/network/NetworkServiceImpl.java
index b804b07..1c7786e 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -105,20 +105,19 @@ import com.cloud.network.dao.AccountGuestVlanMapVO;
 import com.cloud.network.dao.FirewallRulesDao;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.dao.LoadBalancerVMMapDao;
+import com.cloud.network.dao.LoadBalancerVMMapVO;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkDomainDao;
-import com.cloud.network.dao.NetworkDomainVO;
 import com.cloud.network.dao.NetworkServiceMapDao;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.dao.OvsProviderDao;
 import com.cloud.network.dao.PhysicalNetworkDao;
 import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
-import com.cloud.network.dao.LoadBalancerVMMapDao;
 import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
 import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
 import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
 import com.cloud.network.dao.PhysicalNetworkVO;
-import com.cloud.network.dao.LoadBalancerVMMapVO;
 import com.cloud.network.element.NetworkElement;
 import com.cloud.network.element.OvsProviderVO;
 import com.cloud.network.element.VirtualRouterElement;
@@ -141,13 +140,13 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
 import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
 import com.cloud.org.Grouping;
 import com.cloud.projects.Project;
+import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.projects.ProjectManager;
 import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
-import com.cloud.user.AccountVO;
 import com.cloud.user.DomainManager;
 import com.cloud.user.ResourceLimitService;
 import com.cloud.user.User;
@@ -157,6 +156,7 @@ import com.cloud.user.dao.UserDao;
 import com.cloud.utils.Journal;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.EntityManager;
@@ -1390,14 +1390,10 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
         String trafficType = cmd.getTrafficType();
         Boolean isSystem = cmd.getIsSystem();
         String aclType = cmd.getAclType();
-        Long projectId = cmd.getProjectId();
-        List<Long> permittedAccounts = new ArrayList<Long>();
-        String path = null;
         Long physicalNetworkId = cmd.getPhysicalNetworkId();
         List<String> supportedServicesStr = cmd.getSupportedServices();
         Boolean restartRequired = cmd.getRestartRequired();
         boolean listAll = cmd.listAll();
-        boolean isRecursive = cmd.isRecursive();
         Boolean specifyIpRanges = cmd.getSpecifyIpRanges();
         Long vpcId = cmd.getVpcId();
         Boolean canUseForDeploy = cmd.canUseForDeploy();
@@ -1416,66 +1412,16 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
             throw new InvalidParameterValueException("System network belongs 
to system, account and domainId parameters can't be specified");
         }
 
-        if (domainId != null) {
-            DomainVO domain = _domainDao.findById(domainId);
-            if (domain == null) {
-                // see DomainVO.java
-                throw new InvalidParameterValueException("Specified domain id 
doesn't exist in the system");
-            }
-
-            _accountMgr.checkAccess(caller, domain);
-            if (accountName != null) {
-                Account owner = 
_accountMgr.getActiveAccountByName(accountName, domainId);
-                if (owner == null) {
-                    // see DomainVO.java
-                    throw new InvalidParameterValueException("Unable to find 
account " + accountName + " in specified domain");
-                }
-
-                _accountMgr.checkAccess(caller, null, true, owner);
-                permittedAccounts.add(owner.getId());
-            }
-        }
-
-        if (!_accountMgr.isAdmin(caller.getType()) || (projectId != null && 
projectId.longValue() != -1 && domainId == null)) {
-            permittedAccounts.add(caller.getId());
-            domainId = caller.getDomainId();
-        }
-
-        // set project information
-        boolean skipProjectNetworks = true;
-        if (projectId != null) {
-            if (projectId.longValue() == -1) {
-                if (!_accountMgr.isAdmin(caller.getType())) {
-                    
permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
-                }
-            } else {
-                permittedAccounts.clear();
-                Project project = _projectMgr.getProject(projectId);
-                if (project == null) {
-                    throw new InvalidParameterValueException("Unable to find 
project by specified id");
-                }
-                if (!_projectMgr.canAccessProjectAccount(caller, 
project.getProjectAccountId())) {
-                    // getProject() returns type ProjectVO.
-                    InvalidParameterValueException ex = new 
InvalidParameterValueException("Account " + caller + " cannot access specified 
project id");
-                    ex.addProxyObject(project.getUuid(), "projectId");
-                    throw ex;
-                }
-
-                //add project account
-                permittedAccounts.add(project.getProjectAccountId());
-                //add caller account (if admin)
-                if (_accountMgr.isAdmin(caller.getType())) {
-                    permittedAccounts.add(caller.getId());
-                }
-            }
-            skipProjectNetworks = false;
-        }
+        List<Long> permittedDomains = new ArrayList<Long>();
+        List<Long> permittedAccounts = new ArrayList<Long>();
+        List<Long> permittedResources = new ArrayList<Long>();
+        Ternary<Long, Boolean, ListProjectResourcesCriteria> 
domainIdRecursiveListProject = new Ternary<Long, Boolean, 
ListProjectResourcesCriteria>(cmd.getDomainId(),
+                cmd.isRecursive(), null);
+        _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), 
cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources,
+                domainIdRecursiveListProject, cmd.listAll(), false, 
"listNetworks");
+        Boolean isRecursive = domainIdRecursiveListProject.second();
+        ListProjectResourcesCriteria listProjectResourcesCriteria = 
domainIdRecursiveListProject.third();
 
-        if (domainId != null) {
-            path = _domainDao.findById(domainId).getPath();
-        } else {
-        path = _domainDao.findById(caller.getDomainId()).getPath();
-        }
 
         if (listAll && domainId == null) {
             isRecursive = true;
@@ -1483,6 +1429,7 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
 
         Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, 
null);
         SearchBuilder<NetworkVO> sb = _networksDao.createSearchBuilder();
+        _accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, 
permittedAccounts, permittedResources, listProjectResourcesCriteria);
 
         if (forVpc != null) {
             if (forVpc) {
@@ -1517,122 +1464,9 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
             sb.join("tagSearch", tagSearch, sb.entity().getId(), 
tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
         }
 
-        if (permittedAccounts.isEmpty()) {
-            SearchBuilder<DomainVO> domainSearch = 
_domainDao.createSearchBuilder();
-            domainSearch.and("path", domainSearch.entity().getPath(), 
SearchCriteria.Op.LIKE);
-            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), 
domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
-        }
-
-            SearchBuilder<AccountVO> accountSearch = 
_accountDao.createSearchBuilder();
-        accountSearch.and("typeNEQ", accountSearch.entity().getType(), 
SearchCriteria.Op.NEQ);
-        accountSearch.and("typeEQ", accountSearch.entity().getType(), 
SearchCriteria.Op.EQ);
-
-            sb.join("accountSearch", accountSearch, 
sb.entity().getAccountId(), accountSearch.entity().getId(), 
JoinBuilder.JoinType.INNER);
-
-        List<NetworkVO> networksToReturn = new ArrayList<NetworkVO>();
-
-        if (isSystem == null || !isSystem) {
-            if (!permittedAccounts.isEmpty()) {
-                //get account level networks
-                networksToReturn.addAll(listAccountSpecificNetworks(
-                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, 
zoneId, guestIpType, trafficType, physicalNetworkId, aclType, 
skipProjectNetworks, restartRequired,
-                                specifyIpRanges, vpcId, tags, display), 
searchFilter, permittedAccounts));
-                //get domain level networks
-                if (domainId != null) {
-                    networksToReturn.addAll(listDomainLevelNetworks(
-                            buildNetworkSearchCriteria(sb, keyword, id, 
isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, 
restartRequired,
-                                    specifyIpRanges, vpcId, tags, display), 
searchFilter, domainId, false));
-                }
-            } else {
-                //add account specific networks
-                
networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(
-                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, 
zoneId, guestIpType, trafficType, physicalNetworkId, aclType, 
skipProjectNetworks, restartRequired,
-                                specifyIpRanges, vpcId, tags, display), 
searchFilter, path, isRecursive));
-                //add domain specific networks of domain + parent domains
-                networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(
-                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, 
zoneId, guestIpType, trafficType, physicalNetworkId, aclType, 
skipProjectNetworks, restartRequired,
-                                specifyIpRanges, vpcId, tags, display), 
searchFilter, path, isRecursive));
-                //add networks of subdomains
-                if (domainId == null) {
-                    networksToReturn.addAll(listDomainLevelNetworks(
-                            buildNetworkSearchCriteria(sb, keyword, id, 
isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, 
restartRequired,
-                                    specifyIpRanges, vpcId, tags, display), 
searchFilter, caller.getDomainId(), true));
-                }
-            }
-        } else {
-            networksToReturn = _networksDao.search(
-                    buildNetworkSearchCriteria(sb, keyword, id, isSystem, 
zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, 
restartRequired,
-                            specifyIpRanges, vpcId, tags, display), 
searchFilter);
-        }
-
-        if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && 
!networksToReturn.isEmpty()) {
-            List<NetworkVO> supportedNetworks = new ArrayList<NetworkVO>();
-            Service[] suppportedServices = new 
Service[supportedServicesStr.size()];
-            int i = 0;
-            for (String supportedServiceStr : supportedServicesStr) {
-                Service service = Service.getService(supportedServiceStr);
-                if (service == null) {
-                    throw new InvalidParameterValueException("Invalid service 
specified " + supportedServiceStr);
-                } else {
-                    suppportedServices[i] = service;
-                }
-                i++;
-            }
-
-            for (NetworkVO network : networksToReturn) {
-                if (areServicesSupportedInNetwork(network.getId(), 
suppportedServices)) {
-                    supportedNetworks.add(network);
-                }
-            }
-
-            networksToReturn = supportedNetworks;
-        }
-
-        if (canUseForDeploy != null) {
-            List<NetworkVO> networksForDeploy = new ArrayList<NetworkVO>();
-            for (NetworkVO network : networksToReturn) {
-                if (_networkModel.canUseForDeploy(network) == canUseForDeploy) 
{
-                    networksForDeploy.add(network);
-                }
-            }
-
-            networksToReturn = networksForDeploy;
-        }
-
-        //Now apply pagination
-        //Most likely pageSize will never exceed int value, and we need 
integer to partition the listToReturn
-        boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() 
!= null;
-        if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && 
cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= 
Integer.MAX_VALUE
-                && cmd.getPageSizeVal() >= Integer.MIN_VALUE) {
-            int index = cmd.getStartIndex().intValue() == 0 ? 0 : 
cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue();
-            List<NetworkVO> wPagination = new ArrayList<NetworkVO>();
-            List<List<NetworkVO>> partitions = 
partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue());
-            if (index < partitions.size()) {
-                wPagination = partitions.get(index);
-            }
-            return new Pair<List<? extends Network>, Integer>(wPagination, 
networksToReturn.size());
-        }
-
-        return new Pair<List<? extends Network>, Integer>(networksToReturn, 
networksToReturn.size());
-    }
-
-    private static List<List<NetworkVO>> partitionNetworks(List<NetworkVO> 
originalList, int chunkSize) {
-        List<List<NetworkVO>> listOfChunks = new ArrayList<List<NetworkVO>>();
-        for (int i = 0; i < originalList.size() / chunkSize; i++) {
-            listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize 
+ chunkSize));
-        }
-        if (originalList.size() % chunkSize != 0) {
-            listOfChunks.add(originalList.subList(originalList.size() - 
originalList.size() % chunkSize, originalList.size()));
-        }
-        return listOfChunks;
-    }
-
-    private SearchCriteria<NetworkVO> 
buildNetworkSearchCriteria(SearchBuilder<NetworkVO> sb, String keyword, Long 
id, Boolean isSystem, Long zoneId, String guestIpType,
-            String trafficType, Long physicalNetworkId, String aclType, 
boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges, 
Long vpcId,
-            Map<String, String> tags, Boolean display) {
-
+        // build network search criteria
         SearchCriteria<NetworkVO> sc = sb.create();
-
+        _accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, 
permittedAccounts, permittedResources, listProjectResourcesCriteria);
         if (isSystem != null) {
             sc.setJoinParameters("networkOfferingSearch", "systemOnly", 
isSystem);
         }
@@ -1671,12 +1505,6 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
             sc.addAnd("physicalNetworkId", SearchCriteria.Op.EQ, 
physicalNetworkId);
         }
 
-        if (skipProjectNetworks) {
-            sc.setJoinParameters("accountSearch", "typeNEQ", 
Account.ACCOUNT_TYPE_PROJECT);
-        } else {
-            sc.setJoinParameters("accountSearch", "typeEQ", 
Account.ACCOUNT_TYPE_PROJECT);
-        }
-
         if (restartRequired != null) {
             sc.addAnd("restartRequired", SearchCriteria.Op.EQ, 
restartRequired);
         }
@@ -1699,94 +1527,70 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
             }
         }
 
-        return sc;
-    }
-
-    private List<NetworkVO> listDomainLevelNetworks(SearchCriteria<NetworkVO> 
sc, Filter searchFilter, long domainId, boolean parentDomainsOnly) {
-        List<Long> networkIds = new ArrayList<Long>();
-        Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
-        List<NetworkDomainVO> maps = 
_networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
+        List<NetworkVO> networksToReturn = _networksDao.search(sc, 
searchFilter);
 
-        for (NetworkDomainVO map : maps) {
-            if (map.getDomainId() == domainId && parentDomainsOnly) {
-                continue;
-            }
-            boolean subdomainAccess = (map.isSubdomainAccess() != null) ? 
map.isSubdomainAccess() : getAllowSubdomainAccessGlobal();
-            if (map.getDomainId() == domainId || subdomainAccess) {
-                networkIds.add(map.getNetworkId());
+        // filter by supported services
+        if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && 
!networksToReturn.isEmpty()) {
+            List<NetworkVO> supportedNetworks = new ArrayList<NetworkVO>();
+            Service[] suppportedServices = new 
Service[supportedServicesStr.size()];
+            int i = 0;
+            for (String supportedServiceStr : supportedServicesStr) {
+                Service service = Service.getService(supportedServiceStr);
+                if (service == null) {
+                    throw new InvalidParameterValueException("Invalid service 
specified " + supportedServiceStr);
+                } else {
+                    suppportedServices[i] = service;
+                }
+                i++;
             }
-        }
-
-        if (!networkIds.isEmpty()) {
-            SearchCriteria<NetworkVO> domainSC = 
_networksDao.createSearchCriteria();
-            domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
-            domainSC.addAnd("aclType", SearchCriteria.Op.EQ, 
ACLType.Domain.toString());
 
-            sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
-            return _networksDao.search(sc, searchFilter);
-        } else {
-            return new ArrayList<NetworkVO>();
-        }
-    }
+            for (NetworkVO network : networksToReturn) {
+                if (areServicesSupportedInNetwork(network.getId(), 
suppportedServices)) {
+                    supportedNetworks.add(network);
+                }
+            }
 
-    private List<NetworkVO> 
listAccountSpecificNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, 
List<Long> permittedAccounts) {
-        SearchCriteria<NetworkVO> accountSC = 
_networksDao.createSearchCriteria();
-        if (!permittedAccounts.isEmpty()) {
-            accountSC.addAnd("accountId", SearchCriteria.Op.IN, 
permittedAccounts.toArray());
+            networksToReturn = supportedNetworks;
         }
 
-        accountSC.addAnd("aclType", SearchCriteria.Op.EQ, 
ACLType.Account.toString());
-
-        sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
-        return _networksDao.search(sc, searchFilter);
-    }
-
-    private List<NetworkVO> 
listAccountSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter 
searchFilter, String path, boolean isRecursive) {
-        SearchCriteria<NetworkVO> accountSC = 
_networksDao.createSearchCriteria();
-        accountSC.addAnd("aclType", SearchCriteria.Op.EQ, 
ACLType.Account.toString());
-
-        if (path != null) {
-            if (isRecursive) {
-                sc.setJoinParameters("domainSearch", "path", path + "%");
-            } else {
-                sc.setJoinParameters("domainSearch", "path", path);
+        // filter by usability to deploy
+        if (canUseForDeploy != null) {
+            List<NetworkVO> networksForDeploy = new ArrayList<NetworkVO>();
+            for (NetworkVO network : networksToReturn) {
+                if (_networkModel.canUseForDeploy(network) == canUseForDeploy) 
{
+                    networksForDeploy.add(network);
+                }
             }
-        }
-
-        sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
-        return _networksDao.search(sc, searchFilter);
-    }
 
-    private List<NetworkVO> 
listDomainSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter 
searchFilter, String path, boolean isRecursive) {
+            networksToReturn = networksForDeploy;
+        }
 
-        Set<Long> allowedDomains = new HashSet<Long>();
-        if (path != null) {
-            if (isRecursive) {
-                allowedDomains = _domainMgr.getDomainChildrenIds(path);
-            } else {
-                Domain domain = _domainDao.findDomainByPath(path);
-                allowedDomains.add(domain.getId());
+        //Now apply pagination
+        //Most likely pageSize will never exceed int value, and we need 
integer to partition the listToReturn
+        boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() 
!= null;
+        if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && 
cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= 
Integer.MAX_VALUE
+                && cmd.getPageSizeVal() >= Integer.MIN_VALUE) {
+            int index = cmd.getStartIndex().intValue() == 0 ? 0 : 
cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue();
+            List<NetworkVO> wPagination = new ArrayList<NetworkVO>();
+            List<List<NetworkVO>> partitions = 
partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue());
+            if (index < partitions.size()) {
+                wPagination = partitions.get(index);
             }
+            return new Pair<List<? extends Network>, Integer>(wPagination, 
networksToReturn.size());
         }
 
-        List<Long> networkIds = new ArrayList<Long>();
-
-        List<NetworkDomainVO> maps = 
_networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
+        return new Pair<List<? extends Network>, Integer>(networksToReturn, 
networksToReturn.size());
+    }
 
-        for (NetworkDomainVO map : maps) {
-            networkIds.add(map.getNetworkId());
+    private static List<List<NetworkVO>> partitionNetworks(List<NetworkVO> 
originalList, int chunkSize) {
+        List<List<NetworkVO>> listOfChunks = new ArrayList<List<NetworkVO>>();
+        for (int i = 0; i < originalList.size() / chunkSize; i++) {
+            listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize 
+ chunkSize));
         }
-
-        if (!networkIds.isEmpty()) {
-            SearchCriteria<NetworkVO> domainSC = 
_networksDao.createSearchCriteria();
-            domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
-            domainSC.addAnd("aclType", SearchCriteria.Op.EQ, 
ACLType.Domain.toString());
-
-            sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
-        return _networksDao.search(sc, searchFilter);
-        } else {
-            return new ArrayList<NetworkVO>();
+        if (originalList.size() % chunkSize != 0) {
+            listOfChunks.add(originalList.subList(originalList.size() - 
originalList.size() % chunkSize, originalList.size()));
         }
+        return listOfChunks;
     }
 
     @Override

Reply via email to