public void merge()

in src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java [47:126]


    public void merge(HandlerContext context, Feature target, Feature source, Extension targetEx, Extension sourceEx) {
        if (!sourceEx.getName().equals(ApiRegions.EXTENSION_NAME))
            return;
        if (targetEx != null && !targetEx.getName().equals(ApiRegions.EXTENSION_NAME))
            return;

        try {
            final ApiRegions srcRegions = ApiRegions.parse((JsonArray) sourceEx.getJSONStructure());

            final ApiRegions targetRegions;
            if (targetEx != null) {
                targetRegions = ApiRegions.parse((JsonArray) targetEx.getJSONStructure());
            } else {
                targetEx = new Extension(sourceEx.getType(), sourceEx.getName(), sourceEx.getState());
                target.getExtensions().add(targetEx);

                targetRegions = new ApiRegions();
            }

            for (final ApiRegion targetRegion : targetRegions.listRegions()) {
                final ApiRegion sourceRegion = srcRegions.getRegionByName(targetRegion.getName());
                if (sourceRegion != null) {
                    for (final ApiExport srcExp : sourceRegion.listExports()) {
                        if (targetRegion.getExportByName(srcExp.getName()) == null) {
                            targetRegion.add(srcExp);
                        }
                    }
                    LinkedHashSet<ArtifactId> targetOrigins = new LinkedHashSet<>(Arrays.asList(targetRegion.getFeatureOrigins()));
                    LinkedHashSet<ArtifactId> sourceOrigins = new LinkedHashSet<>(Arrays.asList(sourceRegion.getFeatureOrigins()));
                    if (sourceOrigins.isEmpty()) {
                        sourceOrigins.add(source.getId());
                    }
                    targetOrigins.addAll(sourceOrigins);
                    targetRegion.setFeatureOrigins(targetOrigins.toArray(new ArtifactId[0]));
                }
            }

            // Build up a region map to identify the insertion positions
            Map<String, Integer> regionPos = new HashMap<>();
            List<ApiRegion> tRegions = targetRegions.listRegions();
            for (int i=0; i<tRegions.size(); i++) {
                regionPos.put(tRegions.get(i).getName(), i);
            }

            // Process the source regions back to front, to not interfere with the positions in the map
            // Merge them in to have an ordered list that is consistent with both what was already in
            // the target and what is in the source.
            List<ApiRegion> sRegions = srcRegions.listRegions();
            int nextInsertPosition = tRegions.size();
            String nextFound = getNextFound(sRegions.size() - 1, regionPos, sRegions);

            for (int i=sRegions.size() - 1; i>=0; i--) {
                ApiRegion cur = sRegions.get(i);
                if (cur.getName().equals(nextFound)) {
                    nextFound = getNextFound(i - 1, regionPos, sRegions);
                    if (nextFound == null) {
                        nextInsertPosition = 0;
                    } else {
                        nextInsertPosition = regionPos.get(nextFound) + 1;
                    }
                } else {
                    LinkedHashSet<ArtifactId> origins = new LinkedHashSet<>(Arrays.asList(cur.getFeatureOrigins()));
                    if (origins.isEmpty())
                    {
                        origins.add(source.getId());
                        cur.setFeatureOrigins(origins.toArray(new ArtifactId[0]));
                    }
                    if (!targetRegions.add(nextInsertPosition, cur))
                    {
                        throw new IllegalStateException("Duplicate region " + cur.getName());
                    }
                }
            }

            targetEx.setJSONStructure(targetRegions.toJSONArray());

        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }