| // Licensed to the Apache Software Foundation (ASF) under one | 
 | // or more contributor license agreements.  See the NOTICE file | 
 | // distributed with this work for additional information | 
 | // regarding copyright ownership.  The ASF licenses this file | 
 | // to you 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 com.cloud.dc.dao; | 
 |  | 
 | import java.sql.PreparedStatement; | 
 | import java.sql.ResultSet; | 
 | import java.sql.SQLException; | 
 | import java.util.ArrayList; | 
 | import java.util.List; | 
 | import java.util.Map; | 
 |  | 
 | import javax.inject.Inject; | 
 | import javax.naming.ConfigurationException; | 
 |  | 
 | import org.apache.commons.lang3.ArrayUtils; | 
 | import org.apache.commons.lang3.StringUtils; | 
 | import org.springframework.stereotype.Component; | 
 |  | 
 | import com.cloud.dc.AccountVlanMapVO; | 
 | import com.cloud.dc.DomainVlanMapVO; | 
 | import com.cloud.dc.PodVlanMapVO; | 
 | import com.cloud.dc.Vlan; | 
 | import com.cloud.dc.Vlan.VlanType; | 
 | import com.cloud.dc.VlanVO; | 
 | import com.cloud.network.dao.IPAddressDao; | 
 | import com.cloud.utils.Pair; | 
 | import com.cloud.utils.db.DB; | 
 | import com.cloud.utils.db.GenericDaoBase; | 
 | import com.cloud.utils.db.JoinBuilder; | 
 | import com.cloud.utils.db.SearchBuilder; | 
 | import com.cloud.utils.db.SearchCriteria; | 
 | import com.cloud.utils.db.TransactionLegacy; | 
 | import com.cloud.utils.exception.CloudRuntimeException; | 
 | import com.cloud.utils.net.NetUtils; | 
 |  | 
 | @Component | 
 | public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao { | 
 |  | 
 |     private final String FindZoneWideVlans = | 
 |         "SELECT * FROM vlan WHERE data_center_id=? and vlan_type=? and vlan_id!=? and id not in (select vlan_db_id from account_vlan_map)"; | 
 |  | 
 |     protected SearchBuilder<VlanVO> ZoneVlanIdSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneTypeSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneTypeAllPodsSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneTypePodSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneVlanSearch; | 
 |     protected SearchBuilder<VlanVO> NetworkVlanSearch; | 
 |     protected SearchBuilder<VlanVO> PhysicalNetworkVlanSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneWideNonDedicatedVlanSearch; | 
 |     protected SearchBuilder<VlanVO> VlanGatewaysearch; | 
 |     protected SearchBuilder<VlanVO> DedicatedVlanSearch; | 
 |     protected SearchBuilder<VlanVO> ZoneVlanIp6Search; | 
 |     protected SearchBuilder<VlanVO> ZoneIp6Search; | 
 |     protected SearchBuilder<VlanVO> ZoneVlansSearch; | 
 |  | 
 |     protected SearchBuilder<AccountVlanMapVO> AccountVlanMapSearch; | 
 |     protected SearchBuilder<DomainVlanMapVO> DomainVlanMapSearch; | 
 |  | 
 |     @Inject | 
 |     protected PodVlanMapDao _podVlanMapDao; | 
 |     @Inject | 
 |     protected AccountVlanMapDao _accountVlanMapDao; | 
 |     @Inject | 
 |     protected DomainVlanMapDao _domainVlanMapDao; | 
 |     @Inject | 
 |     protected IPAddressDao _ipAddressDao; | 
 |  | 
 |     @Override | 
 |     public VlanVO findByZoneAndVlanId(long zoneId, String vlanId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneVlanIdSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlanId", vlanId); | 
 |         return findOneBy(sc); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns a vlan by the network id and if the given IPv4 is in the network IP range. | 
 |      */ | 
 |     @Override | 
 |     public VlanVO findByNetworkIdAndIpv4(long networkId, String ipv4Address) { | 
 |         List<VlanVO> vlanVoList = listVlansByNetworkId(networkId); | 
 |         for (VlanVO vlan : vlanVoList) { | 
 |             String ipRange = vlan.getIpRange(); | 
 |             String[] ipRangeParts = ipRange.split("-"); | 
 |             String startIP = ipRangeParts[0]; | 
 |             String endIP = ipRangeParts[1]; | 
 |             if (NetUtils.isIpInRange(ipv4Address, startIP, endIP)) { | 
 |                 return vlan; | 
 |             } | 
 |         } | 
 |         return null; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listByZone(long zoneId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     public VlanDaoImpl() { | 
 |         ZoneVlanIdSearch = createSearchBuilder(); | 
 |         ZoneVlanIdSearch.and("zoneId", ZoneVlanIdSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneVlanIdSearch.and("vlanId", ZoneVlanIdSearch.entity().getVlanTag(), SearchCriteria.Op.EQ); | 
 |         ZoneVlanIdSearch.done(); | 
 |  | 
 |         ZoneSearch = createSearchBuilder(); | 
 |         ZoneSearch.and("zoneId", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneSearch.done(); | 
 |  | 
 |         ZoneTypeSearch = createSearchBuilder(); | 
 |         ZoneTypeSearch.and("zoneId", ZoneTypeSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneTypeSearch.and("vlanType", ZoneTypeSearch.entity().getVlanType(), SearchCriteria.Op.EQ); | 
 |         ZoneTypeSearch.done(); | 
 |  | 
 |         NetworkVlanSearch = createSearchBuilder(); | 
 |         NetworkVlanSearch.and("networkId", NetworkVlanSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); | 
 |         NetworkVlanSearch.done(); | 
 |  | 
 |         PhysicalNetworkVlanSearch = createSearchBuilder(); | 
 |         PhysicalNetworkVlanSearch.and("physicalNetworkId", PhysicalNetworkVlanSearch.entity().getPhysicalNetworkId(), SearchCriteria.Op.EQ); | 
 |         PhysicalNetworkVlanSearch.done(); | 
 |  | 
 |         VlanGatewaysearch = createSearchBuilder(); | 
 |         VlanGatewaysearch.and("gateway", VlanGatewaysearch.entity().getVlanGateway(), SearchCriteria.Op.EQ); | 
 |         VlanGatewaysearch.and("networkid", VlanGatewaysearch.entity().getNetworkId(), SearchCriteria.Op.EQ); | 
 |         VlanGatewaysearch.done(); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listZoneWideVlans(long zoneId, VlanType vlanType, String vlanId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneVlanSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlanId", vlanId); | 
 |         sc.setParameters("vlanType", vlanType); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listByZoneAndType(long zoneId, VlanType vlanType) { | 
 |         SearchCriteria<VlanVO> sc = ZoneTypeSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlanType", vlanType); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listByType(VlanType vlanType) { | 
 |         SearchCriteria<VlanVO> sc = ZoneTypeSearch.create(); | 
 |         sc.setParameters("vlanType", vlanType); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansForPod(long podId) { | 
 |         //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two | 
 |         List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId); | 
 |         List<VlanVO> result = new ArrayList<VlanVO>(); | 
 |         for (PodVlanMapVO pvmvo : vlanMaps) { | 
 |             VlanVO vlanByPodId = findById(pvmvo.getVlanDbId()); | 
 |             if (vlanByPodId != null) { | 
 |                 result.add(vlanByPodId); | 
 |             } | 
 |         } | 
 |         return result; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansForPodByType(long podId, VlanType vlanType) { | 
 |         //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two) | 
 |         List<PodVlanMapVO> vlanMaps = _podVlanMapDao.listPodVlanMapsByPod(podId); | 
 |         List<VlanVO> result = new ArrayList<VlanVO>(); | 
 |         for (PodVlanMapVO pvmvo : vlanMaps) { | 
 |             VlanVO vlan = findById(pvmvo.getVlanDbId()); | 
 |             if (vlan.getVlanType() == vlanType) { | 
 |                 result.add(vlan); | 
 |             } | 
 |         } | 
 |         return result; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansForAccountByType(Long zoneId, long accountId, VlanType vlanType) { | 
 |         //FIXME: use a join statement to improve the performance (should be minor since we expect only one or two) | 
 |         List<AccountVlanMapVO> vlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId); | 
 |         List<VlanVO> result = new ArrayList<VlanVO>(); | 
 |         for (AccountVlanMapVO acvmvo : vlanMaps) { | 
 |             VlanVO vlan = findById(acvmvo.getVlanDbId()); | 
 |             if (vlan.getVlanType() == vlanType && (zoneId == null || vlan.getDataCenterId() == zoneId)) { | 
 |                 result.add(vlan); | 
 |             } | 
 |         } | 
 |         return result; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public void addToPod(long podId, long vlanDbId) { | 
 |         PodVlanMapVO pvmvo = new PodVlanMapVO(podId, vlanDbId); | 
 |         _podVlanMapDao.persist(pvmvo); | 
 |  | 
 |     } | 
 |  | 
 |     @Override | 
 |     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { | 
 |         boolean result = super.configure(name, params); | 
 |         ZoneTypeAllPodsSearch = createSearchBuilder(); | 
 |         ZoneTypeAllPodsSearch.and("zoneId", ZoneTypeAllPodsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneTypeAllPodsSearch.and("vlanType", ZoneTypeAllPodsSearch.entity().getVlanType(), SearchCriteria.Op.EQ); | 
 |  | 
 |         SearchBuilder<PodVlanMapVO> PodVlanSearch = _podVlanMapDao.createSearchBuilder(); | 
 |         PodVlanSearch.and("podId", PodVlanSearch.entity().getPodId(), SearchCriteria.Op.NNULL); | 
 |         ZoneTypeAllPodsSearch.join("vlan", PodVlanSearch, PodVlanSearch.entity().getVlanDbId(), ZoneTypeAllPodsSearch.entity().getId(), JoinBuilder.JoinType.INNER); | 
 |  | 
 |         ZoneTypeAllPodsSearch.done(); | 
 |         PodVlanSearch.done(); | 
 |  | 
 |         ZoneTypePodSearch = createSearchBuilder(); | 
 |         ZoneTypePodSearch.and("zoneId", ZoneTypePodSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneTypePodSearch.and("vlanType", ZoneTypePodSearch.entity().getVlanType(), SearchCriteria.Op.EQ); | 
 |  | 
 |         SearchBuilder<PodVlanMapVO> PodVlanSearch2 = _podVlanMapDao.createSearchBuilder(); | 
 |         PodVlanSearch2.and("podId", PodVlanSearch2.entity().getPodId(), SearchCriteria.Op.EQ); | 
 |         ZoneTypePodSearch.join("vlan", PodVlanSearch2, PodVlanSearch2.entity().getVlanDbId(), ZoneTypePodSearch.entity().getId(), JoinBuilder.JoinType.INNER); | 
 |         PodVlanSearch2.done(); | 
 |         ZoneTypePodSearch.done(); | 
 |  | 
 |         ZoneWideNonDedicatedVlanSearch = createSearchBuilder(); | 
 |         ZoneWideNonDedicatedVlanSearch.and("zoneId", ZoneWideNonDedicatedVlanSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder(); | 
 |         AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.NULL); | 
 |         ZoneWideNonDedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity() | 
 |             .getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); | 
 |         DomainVlanMapSearch = _domainVlanMapDao.createSearchBuilder(); | 
 |         DomainVlanMapSearch.and("domainId", DomainVlanMapSearch.entity().getDomainId(), SearchCriteria.Op.NULL); | 
 |         ZoneWideNonDedicatedVlanSearch.join("DomainVlanMapSearch", DomainVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), DomainVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); | 
 |         ZoneWideNonDedicatedVlanSearch.done(); | 
 |         AccountVlanMapSearch.done(); | 
 |         DomainVlanMapSearch.done(); | 
 |  | 
 |         DedicatedVlanSearch = createSearchBuilder(); | 
 |         AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder(); | 
 |         AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ); | 
 |         DedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, DedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity().getVlanDbId(), | 
 |             JoinBuilder.JoinType.LEFTOUTER); | 
 |         DedicatedVlanSearch.done(); | 
 |         AccountVlanMapSearch.done(); | 
 |  | 
 |         ZoneVlanIp6Search = createSearchBuilder(); | 
 |         ZoneVlanIp6Search.and("zoneId", ZoneVlanIp6Search.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneVlanIp6Search.and("vlanId", ZoneVlanIp6Search.entity().getVlanTag(), SearchCriteria.Op.EQ); | 
 |         ZoneVlanIp6Search.and("ip6Gateway", ZoneVlanIp6Search.entity().getIp6Gateway(), SearchCriteria.Op.NNULL); | 
 |         ZoneVlanIp6Search.and("ip6Cidr", ZoneVlanIp6Search.entity().getIp6Cidr(), SearchCriteria.Op.NNULL); | 
 |         ZoneVlanIp6Search.done(); | 
 |  | 
 |         ZoneIp6Search = createSearchBuilder(); | 
 |         ZoneIp6Search.and("zoneId", ZoneIp6Search.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneIp6Search.and("ip6Gateway", ZoneIp6Search.entity().getIp6Gateway(), SearchCriteria.Op.NNULL); | 
 |         ZoneIp6Search.and("ip6Cidr", ZoneIp6Search.entity().getIp6Cidr(), SearchCriteria.Op.NNULL); | 
 |         ZoneIp6Search.done(); | 
 |  | 
 |         ZoneVlansSearch = createSearchBuilder(); | 
 |         ZoneVlansSearch.and("zoneId", ZoneVlansSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); | 
 |         ZoneVlansSearch.and("vlan", ZoneVlansSearch.entity().getVlanTag(), SearchCriteria.Op.IN); | 
 |         ZoneVlansSearch.done(); | 
 |         return result; | 
 |     } | 
 |  | 
 |     private VlanVO findNextVlan(long zoneId, Vlan.VlanType vlanType) { | 
 |         List<VlanVO> allVlans = listByZoneAndType(zoneId, vlanType); | 
 |         List<VlanVO> emptyVlans = new ArrayList<VlanVO>(); | 
 |         List<VlanVO> fullVlans = new ArrayList<VlanVO>(); | 
 |  | 
 |         // Try to find a VLAN that is partially allocated | 
 |         for (VlanVO vlan : allVlans) { | 
 |             long vlanDbId = vlan.getId(); | 
 |  | 
 |             int countOfAllocatedIps = _ipAddressDao.countIPs(zoneId, vlanDbId, true); | 
 |             int countOfAllIps = _ipAddressDao.countIPs(zoneId, vlanDbId, false); | 
 |  | 
 |             if ((countOfAllocatedIps > 0) && (countOfAllocatedIps < countOfAllIps)) { | 
 |                 return vlan; | 
 |             } else if (countOfAllocatedIps == 0) { | 
 |                 emptyVlans.add(vlan); | 
 |             } else if (countOfAllocatedIps == countOfAllIps) { | 
 |                 fullVlans.add(vlan); | 
 |             } | 
 |         } | 
 |  | 
 |         if (emptyVlans.isEmpty()) { | 
 |             return null; | 
 |         } | 
 |  | 
 |         // Try to find an empty VLAN with the same tag/subnet as a VLAN that is full | 
 |         for (VlanVO fullVlan : fullVlans) { | 
 |             for (VlanVO emptyVlan : emptyVlans) { | 
 |                 if (fullVlan.getVlanTag().equals(emptyVlan.getVlanTag()) && fullVlan.getVlanGateway().equals(emptyVlan.getVlanGateway()) && | 
 |                     fullVlan.getVlanNetmask().equals(emptyVlan.getVlanNetmask())) { | 
 |                     return emptyVlan; | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |         // Return a random empty VLAN | 
 |         return emptyVlans.get(0); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public boolean zoneHasDirectAttachUntaggedVlans(long zoneId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneTypeAllPodsSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlanType", VlanType.DirectAttached); | 
 |  | 
 |         return listIncludingRemovedBy(sc).size() > 0; | 
 |     } | 
 |  | 
 |     public Pair<String, VlanVO> assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneTypePodSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlanType", VlanType.DirectAttached); | 
 |         sc.setJoinParameters("vlan", "podId", podId); | 
 |  | 
 |         VlanVO vlan = findOneIncludingRemovedBy(sc); | 
 |         if (vlan == null) { | 
 |             return null; | 
 |         } | 
 |  | 
 |         return null; | 
 |     } | 
 |  | 
 |     @Override | 
 |     @DB | 
 |     public List<VlanVO> searchForZoneWideVlans(long dcId, String vlanType, String vlanId) { | 
 |         StringBuilder sql = new StringBuilder(FindZoneWideVlans); | 
 |         TransactionLegacy txn = TransactionLegacy.currentTxn(); | 
 |         List<VlanVO> zoneWideVlans = new ArrayList<VlanVO>(); | 
 |         try(PreparedStatement pstmt = txn.prepareStatement(sql.toString());){ | 
 |             if(pstmt != null) { | 
 |                 pstmt.setLong(1, dcId); | 
 |                 pstmt.setString(2, vlanType); | 
 |                 pstmt.setString(3, vlanId); | 
 |                 try(ResultSet rs = pstmt.executeQuery();) { | 
 |                     while (rs.next()) { | 
 |                         zoneWideVlans.add(toEntityBean(rs, false)); | 
 |                     } | 
 |                 }catch (SQLException e) { | 
 |                     throw new CloudRuntimeException("searchForZoneWideVlans:Exception:" + e.getMessage(), e); | 
 |                 } | 
 |             } | 
 |             return zoneWideVlans; | 
 |         } catch (SQLException e) { | 
 |             throw new CloudRuntimeException("searchForZoneWideVlans:Exception:" + e.getMessage(), e); | 
 |         } | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansByNetworkId(long networkId) { | 
 |         SearchCriteria<VlanVO> sc = NetworkVlanSearch.create(); | 
 |         sc.setParameters("networkId", networkId); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override public List<VlanVO> listVlansByNetworkIdIncludingRemoved(long networkId) { | 
 |         SearchCriteria<VlanVO> sc = NetworkVlanSearch.create(); | 
 |         sc.setParameters("networkId", networkId); | 
 |         return listIncludingRemovedBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansByNetworkIdAndGateway(long networkid, String gateway) { | 
 |         SearchCriteria<VlanVO> sc = VlanGatewaysearch.create(); | 
 |         sc.setParameters("networkid", networkid); | 
 |         sc.setParameters("gateway", gateway); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listVlansByPhysicalNetworkId(long physicalNetworkId) { | 
 |         SearchCriteria<VlanVO> sc = PhysicalNetworkVlanSearch.create(); | 
 |         sc.setParameters("physicalNetworkId", physicalNetworkId); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listZoneWideNonDedicatedVlans(long zoneId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneWideNonDedicatedVlanSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listDedicatedVlans(long accountId) { | 
 |         SearchCriteria<VlanVO> sc = DedicatedVlanSearch.create(); | 
 |         sc.setJoinParameters("AccountVlanMapSearch", "accountId", accountId); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listIpv6RangeByZoneIdAndVlanId(long zoneId, String vlanId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneVlanIp6Search.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         if(StringUtils.isNotEmpty(vlanId)) { | 
 |             sc.setParameters("vlanId", vlanId); | 
 |         } | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public List<VlanVO> listIpv6SupportingVlansByZone(long zoneId) { | 
 |         SearchCriteria<VlanVO> sc = ZoneIp6Search.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         List<VlanVO> vlanVOS = listBy(sc); | 
 |         Object[] vlanIds = vlanVOS.stream().map(VlanVO::getVlanTag).toArray(); | 
 |         if (ArrayUtils.isEmpty(vlanIds)) { | 
 |             return new ArrayList<>(); | 
 |         } | 
 |         sc = ZoneVlansSearch.create(); | 
 |         sc.setParameters("zoneId", zoneId); | 
 |         sc.setParameters("vlan", vlanIds); | 
 |         return listBy(sc); | 
 |     } | 
 |  | 
 | } |