2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.so.bpmn.infrastructure.aai.tasks;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.TreeSet;
26 import java.util.stream.Collectors;
28 import org.camunda.bpm.engine.delegate.BpmnError;
29 import org.onap.so.bpmn.common.BuildingBlockExecution;
30 import org.onap.so.bpmn.servicedecomposition.bbobjects.CloudRegion;
31 import org.onap.so.bpmn.servicedecomposition.bbobjects.Collection;
32 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
33 import org.onap.so.bpmn.servicedecomposition.bbobjects.Customer;
34 import org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf;
35 import org.onap.so.bpmn.servicedecomposition.bbobjects.InstanceGroup;
36 import org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network;
37 import org.onap.so.bpmn.servicedecomposition.bbobjects.LineOfBusiness;
38 import org.onap.so.bpmn.servicedecomposition.bbobjects.OwningEntity;
39 import org.onap.so.bpmn.servicedecomposition.bbobjects.Platform;
40 import org.onap.so.bpmn.servicedecomposition.bbobjects.Project;
41 import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance;
42 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
43 import org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup;
44 import org.onap.so.bpmn.servicedecomposition.entities.GeneralBuildingBlock;
45 import org.onap.so.bpmn.servicedecomposition.entities.ResourceKey;
46 import org.onap.so.bpmn.servicedecomposition.tasks.ExtractPojosForBB;
47 import org.onap.so.client.exception.BBObjectNotFoundException;
48 import org.onap.so.client.exception.ExceptionBuilder;
49 import org.onap.so.client.orchestration.AAIConfigurationResources;
50 import org.onap.so.client.orchestration.AAINetworkResources;
51 import org.onap.so.client.orchestration.AAIServiceInstanceResources;
52 import org.onap.so.client.orchestration.AAIVfModuleResources;
53 import org.onap.so.client.orchestration.AAIVnfResources;
54 import org.onap.so.client.orchestration.AAIVolumeGroupResources;
55 import org.onap.so.client.orchestration.AAIVpnBindingResources;
56 import org.onap.so.logger.MessageEnum;
57 import org.onap.so.logger.MsoLogger;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.beans.factory.annotation.Autowired;
61 import org.springframework.core.env.Environment;
62 import org.springframework.stereotype.Component;
65 public class AAICreateTasks {
67 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, AAICreateTasks.class);
68 private static final Logger logger = LoggerFactory.getLogger(AAICreateTasks.class.getName());
70 private static final String networkTypeProvider = "PROVIDER";
71 private static String NETWORK_COLLECTION_NAME = "networkCollectionName";
73 private AAIServiceInstanceResources aaiSIResources;
75 private AAIVnfResources aaiVnfResources;
77 private ExceptionBuilder exceptionUtil;
79 private ExtractPojosForBB extractPojosForBB;
81 private AAIVolumeGroupResources aaiVolumeGroupResources;
83 private AAIVfModuleResources aaiVfModuleResources;
85 private AAINetworkResources aaiNetworkResources;
87 private AAIVpnBindingResources aaiVpnBindingResources;
89 private AAIConfigurationResources aaiConfigurationResources;
91 private Environment env;
93 public void createServiceInstance(BuildingBlockExecution execution) {
95 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
96 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
97 aaiSIResources.createServiceInstance(serviceInstance, customer);
98 } catch (Exception ex) {
99 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
103 public void createServiceSubscription(BuildingBlockExecution execution){
105 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution,
106 ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
107 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
108 if (null == customer) {
109 String errorMessage = "Exception in creating ServiceSubscription. Customer not present for ServiceInstanceID: "
110 + serviceInstance.getServiceInstanceId();
111 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, errorMessage, "BPMN", MsoLogger.getServiceName(),
112 MsoLogger.ErrorCode.UnknownError, errorMessage);
113 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, errorMessage);
115 aaiSIResources.createServiceSubscription(customer);
116 } catch (BpmnError ex) {
119 catch (Exception ex) {
120 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
124 public void createProject(BuildingBlockExecution execution) {
126 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
127 Project project = serviceInstance.getProject();
128 if(project != null) {
129 if (project.getProjectName() == null || "".equals(project.getProjectName())) {
130 msoLogger.info("ProjectName is null in input. Skipping create project...");
132 aaiSIResources.createProjectandConnectServiceInstance(project, serviceInstance);
135 } catch (Exception ex) {
136 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
140 public void createOwningEntity(BuildingBlockExecution execution) {
142 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
143 OwningEntity owningEntity = serviceInstance.getOwningEntity();
144 String owningEntityId = owningEntity.getOwningEntityId();
145 String owningEntityName = owningEntity.getOwningEntityName();
146 if (owningEntityId == null || "".equals(owningEntityId)) {
147 String msg = "Exception in AAICreateOwningEntity. OwningEntityId is null.";
148 execution.setVariable("ErrorCreateOEAAI", msg);
149 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
151 if (aaiSIResources.existsOwningEntity(owningEntity)) {
152 aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
154 if (owningEntityName == null || "".equals(owningEntityName)) {
155 String msg = "Exception in AAICreateOwningEntity. Can't create an owningEntity with no owningEntityName.";
156 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(),
157 MsoLogger.ErrorCode.UnknownError, msg);
158 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
160 if(aaiSIResources.existsOwningEntityName(owningEntityName)){
161 String msg = "Exception in AAICreateOwningEntity. Can't create OwningEntity as name already exists in AAI associated with a different owning-entity-id (name must be unique)";
162 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(),
163 MsoLogger.ErrorCode.UnknownError, msg);
164 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
166 aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
171 } catch (Exception ex) {
172 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
176 public void createVnf(BuildingBlockExecution execution) {
178 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
179 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
180 execution.setVariable("callHoming", Boolean.TRUE.equals(vnf.isCallHoming()));
181 aaiVnfResources.createVnfandConnectServiceInstance(vnf, serviceInstance);
182 } catch (Exception ex) {
183 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
187 public void createPlatform(BuildingBlockExecution execution) {
189 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
190 Platform platform = vnf.getPlatform();
191 if(platform != null) {
192 if (platform.getPlatformName() == null || "".equals(platform.getPlatformName())) {
193 msoLogger.debug("PlatformName is null in input. Skipping create platform...");
195 aaiVnfResources.createPlatformandConnectVnf(platform,vnf);
198 } catch (Exception ex) {
199 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
204 public void createLineOfBusiness(BuildingBlockExecution execution) {
206 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
207 LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
208 if(lineOfBusiness != null) {
209 if (lineOfBusiness.getLineOfBusinessName() == null || "".equals(lineOfBusiness.getLineOfBusinessName())) {
210 msoLogger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
212 aaiVnfResources.createLineOfBusinessandConnectVnf(lineOfBusiness,vnf);
215 } catch (Exception ex) {
216 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
220 public void createVolumeGroup(BuildingBlockExecution execution) {
222 GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
224 GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
225 VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID, execution.getLookupMap().get(ResourceKey.VOLUME_GROUP_ID));
226 CloudRegion cloudRegion = gBBInput.getCloudRegion();
227 aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
228 aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
229 aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup,cloudRegion);
230 } catch (Exception ex) {
231 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
235 public void createVfModule(BuildingBlockExecution execution) {
237 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
238 VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID, execution.getLookupMap().get(ResourceKey.VF_MODULE_ID));
240 if (vfModule.getModelInfoVfModule() != null && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
241 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
243 vfModule.setModuleIndex(moduleIndex);
244 aaiVfModuleResources.createVfModule(vfModule, vnf);
245 } catch (Exception ex) {
246 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
251 * BPMN access method to establish relationships in AAI
255 public void connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
257 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
258 VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID, execution.getLookupMap().get(ResourceKey.VF_MODULE_ID));
259 VolumeGroup volumeGroup = null;
261 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID, execution.getLookupMap().get(ResourceKey.VOLUME_GROUP_ID));
262 } catch (BBObjectNotFoundException e){
263 msoLogger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
265 if (volumeGroup != null) {
266 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup, execution.getGeneralBuildingBlock().getCloudRegion());
268 } catch (Exception ex) {
269 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
274 * BPMN access method to execute Create L3Network operation (PUT )in AAI
278 public void createNetwork(BuildingBlockExecution execution) {
280 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
281 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
282 //set default to false. ToBe updated by SDNC
283 l3network.setIsBoundToVpn(false);
284 //define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
285 if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
286 l3network.setIsBoundToVpn(true);
287 //put network shell in AAI
288 aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
289 } catch (Exception ex) {
290 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
293 public void createCustomer(BuildingBlockExecution execution) throws Exception {
295 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
297 aaiVpnBindingResources.createCustomer(customer);
298 } catch(Exception ex) {
299 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
304 * BPMN access method to execute NetworkCollection operation (PUT) in AAI
308 public void createNetworkCollection(BuildingBlockExecution execution) {
310 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
311 Collection networkCollection = serviceInstance.getCollection();
312 //pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
314 networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
315 aaiNetworkResources.createNetworkCollection(networkCollection);
316 } catch (Exception ex) {
317 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
322 * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
326 public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
328 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
329 InstanceGroup instanceGroup = serviceInstance.getCollection().getInstanceGroup();
330 //set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
331 instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
333 aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
334 } catch (Exception ex) {
335 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
341 * BPMN access method to establish relationships in AAI
345 public void connectNetworkToTenant(BuildingBlockExecution execution) {
347 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
348 aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
349 } catch (Exception ex) {
350 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
355 * BPMN access method to establish relationships in AAI
359 public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
361 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
362 aaiNetworkResources.connectNetworkToCloudRegion(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
363 } catch (Exception ex) {
364 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
369 * BPMN access method to establish relationships in AAI
373 public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
375 boolean cloudRegionsToSkip = false;
376 String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
377 if (cloudRegions != null){
378 cloudRegionsToSkip = Arrays.stream(cloudRegions).anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
380 if(!cloudRegionsToSkip) {
381 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
382 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
384 } catch (Exception ex) {
385 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
390 * BPMN access method to establish relationships in AAI
394 public void connectVnfToTenant(BuildingBlockExecution execution) {
396 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
397 aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
398 } catch (Exception ex) {
399 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
404 * BPMN access method to establish relationships in AAI
408 public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
410 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
411 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
412 aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
413 } catch (Exception ex) {
414 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
419 * BPMN access method to establish relationships in AAI
423 public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
425 ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
426 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
427 //connect network only if Instance Group / Collection objects exist
428 if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
429 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network, serviceInstance.getCollection().getInstanceGroup());
430 } catch (Exception ex) {
431 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
435 public void createConfiguration(BuildingBlockExecution execution){
437 Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID, execution.getLookupMap().get(ResourceKey.CONFIGURATION_ID));
438 aaiConfigurationResources.createConfiguration(configuration);
439 } catch (Exception ex) {
440 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
444 * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
446 * if we have a module type A, and there are 3 instances of those,
447 * and then module type B has 2 instances, if we are adding a new module type A,
448 * the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
451 protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
453 String newVfModuleModelInvariantUUID = null;
454 if (newVfModule.getModelInfoVfModule() != null) {
455 newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
459 if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
460 List<VfModule> modules = genericVnf.getVfModules().stream().filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId())).collect(Collectors.toList());
461 TreeSet<Integer> moduleIndices = new TreeSet<>();
462 int nullIndexFound = 0;
463 for (VfModule vfModule : modules) {
464 if (vfModule.getModelInfoVfModule() != null) {
465 if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
466 if (vfModule.getModuleIndex() != null) {
467 moduleIndices.add(vfModule.getModuleIndex());
470 logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}", vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
476 return calculateUnusedIndex(moduleIndices, nullIndexFound);
482 protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
483 //pad array with nulls
484 Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
485 Integer[] array = moduleIndices.toArray(temp);
487 //when a null is found skip that potential value
488 //effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
489 for (int i=0; i < array.length; i++, result++) {
490 if (Integer.valueOf(result) != array[i]) {
491 if (nullIndexFound > 0) {