Mirrors.java

/*
 * Copyright © 2012-2025 The CTAN Team and individual authors
 *
 * This file is distributed under the 3-clause BSD license.
 * See file LICENSE for details.
 */
package org.ctan.site.domain.mirrors;

import java.io.IOException;
import java.time.LocalDateTime;

import org.apache.lucene.index.CorruptIndexException;
import org.ctan.site.CtanConfiguration.CtanConfig;
import org.ctan.site.services.search.base.IndexType;
import org.ctan.site.services.search.base.IndexingSession;
import org.ctan.site.services.search.base.IndexingSession.IndexArgs;
import org.ctan.site.services.search.base.Searchable;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
 * This domain class represents a CTAN mirror site.
 *
 * @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
 */
@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@SuppressFBWarnings(value = "EI_EXPOSE_REP")
public class Mirrors implements Searchable {

    /**
     * The field <code>id</code> contains the numerical id.
     */
    @Id
    @GeneratedValue
    private Long id;

    /**
     * The field <code>hostname</code> contains the host name.
     */
    @Column(length = 255, nullable = false)
    private String hostname;

    /**
     * The field <code>path</code> contains the path.
     */
    @Column(length = 255, nullable = false)
    private String path;

    /**
     * The field <code>continent</code> contains the continent.
     */
    @ManyToOne
    @JoinColumn(name = "location_continent_id")
    private Continents continent;

    /**
     * The field <code>country</code> contains the country.
     */
    @ManyToOne
    @JoinColumn(name = "location_country_id")
    private Countries country;

    /**
     * The field <code>region</code> contains the region.
     */
    @Column(length = 255, name = "location_region")
    private String region;

    /**
     * The field <code>town</code> contains the town.
     */
    @Column(length = 255, name = "location_town")
    private String town;

    /**
     * The field <code>frequency</code> contains the update frequency.
     */
    @Column(length = 255)
    private String frequency;
    // @ManyToOne
    // @JoinColumn(name = "masterhost")
    // private Mirrors masterhost;

    /**
     * The field <code>services</code> contains the set of services. It is
     * encoded as bit field.
     */
    @Column
    private int services;

    /**
     * The field <code>dateAdded</code> contains the date of adding the mirror.
     */
    @Column(name = "date_added")
    private LocalDateTime dateAdded;

    /**
     * The field <code>dateRemoved</code> contains the date of removal or
     * <code>null</code>.
     */
    @Column(name = "date_removed")
    private LocalDateTime dateRemoved;

    /**
     * The field <code>status</code> contains the status.
     */
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "status_id")
    private Status status;

    /**
     * The field <code>httpUrl</code> contains the URL for http.
     */
    @Column(length = 255, name = "http_url")
    private String httpUrl;

    /**
     * The field <code>rsyncUrl</code> contains the UTL for rsync.
     */
    @Column(length = 255, name = "rsync_url")
    private String rsyncUrl;

    /**
     * The field <code>note</code> contains notes.
     */
    @Column(length = 255)
    private String note;

    /**
     * {@inheritDoc}
     *
     * @see org.ctan.site.services.search.base.Searchable#indexPath()
     */
    @Override
    public String indexPath() {

        return "/mirror/" + hostname;
    }

    /**
     * {@inheritDoc}
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {

        return hostname;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.ctan.site.services.search.base.Searchable#updateIndex(IndexingSession)
     */
    @Override
    public void updateIndex(IndexingSession session)
        throws CorruptIndexException,
            IOException {

        for (var locale : CtanConfig.LOCALES) {
            session.updateIndex(indexPath(),
                IndexArgs.builder()
                    .type(IndexType.MIRRORS)
                    .locale(locale)
                    .title(hostname)
                    .display(hostname)
                    .content(new String[]{
                        hostname,
                        country.getName(locale),
                        town,
                        region,
                        continent.getName(locale)
                    })
                    .build());
        }
    }
}