class XYZGeometryBuilder {

    public List<TileGeometry> buildTopGeometry(XYZTileLayerInfo layer, String layerId, TileRenderProperties props)
    {
        TileGeometry.Builder<GeographicPosition> tileBuilder = new TileGeometry.Builder<GeographicPosition>();
        tileBuilder.setMinimumDisplaySize(384);
        tileBuilder.setMaximumDisplaySize(1280);

        double minLatitude = -90;
        double maxLatitude = 90;
        double totalLonDegrees = 360d;
        double minLon = -180;

        if (layer.getFootprint() != null)
        {
            minLatitude = layer.getFootprint().getMinLatD();
            maxLatitude = layer.getFootprint().getMaxLatD();
            minLon = layer.getFootprint().getMinLonD();
            totalLonDegrees = layer.getFootprint().getWidth();
        }
        else if (layer.getProjection() == Projection.EPSG_3857)
        {
            maxLatitude = ourWebMaxLatitude;
            minLatitude = -ourWebMaxLatitude;
        }

        List<TileGeometry> noParentGeometries = New.list();

        Constraints constraints = null;
        if (layer.getTimeSpan() != null)
        {
            constraints = Constraints.createTimeOnlyConstraint(layer.getTimeSpan());
        }

        XYZQueryTracker tracker = new XYZQueryTracker(myUIRegistry, layer.getDisplayName());
        double deltaLon = totalLonDegrees / layer.getNumberOfTopLevels();
        for (int j = 0; j < layer.getNumberOfTopLevels(); j++)
        {
            GeographicBoundingBox boundingBox = new GeographicBoundingBox(
                    LatLonAlt.createFromDegrees(minLatitude, minLon + deltaLon * j),
                    LatLonAlt.createFromDegrees(maxLatitude, minLon + deltaLon * (j + 1)));
            tileBuilder.setBounds(boundingBox);
            ImageManager imageManager = new ImageManager(new ZYXImageKey(0, 0, j, boundingBox),
                    new XYZImageProvider(myRegistry, layer));
            tileBuilder.setImageManager(imageManager);

            XYZBaseDivider divider = null;
            if (layer.getProjection() == Projection.EPSG_3857)
            {
                divider = new XYZ3857Divider(layer, tracker);
            }
            else
            {
                divider = new XYZ4326Divider(layer, tracker);
            }

            tileBuilder.setDivider(divider);

            TileGeometry topGeometry = new TileGeometry(tileBuilder, props, constraints, layerId);

            List<TileGeometry> geometries = zoomInIfNeedBe(topGeometry, layer);

            for (TileGeometry geometry : geometries)
            {
                tileBuilder = new TileGeometry.Builder<GeographicPosition>();
                tileBuilder.setMinimumDisplaySize(300);
                tileBuilder.setMaximumDisplaySize(600);
                boundingBox = (GeographicBoundingBox)geometry.getBounds();
                tileBuilder.setBounds(boundingBox);
                imageManager = new ImageManager((ZYXImageKey)geometry.getImageManager().getImageKey(),
                        new XYZImageProvider(myRegistry, layer));
                tileBuilder.setImageManager(imageManager);
                imageManager.addRequestObserver(tracker);
                tileBuilder.setDivider(divider);

                noParentGeometries.add(new TileGeometry(tileBuilder, props, constraints, layerId));
            }
        }

        return noParentGeometries;
    }

    public  XYZGeometryBuilder(DataRegistry registry, UIRegistry uiRegistry);

}