ArchiveFile.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.archive;
import java.io.IOException;
import java.util.Map;
import org.apache.lucene.index.CorruptIndexException;
import org.ctan.site.CtanConfiguration.CtanConfig;
import org.ctan.site.services.DateUtils;
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 com.google.common.collect.ImmutableMap;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder.Default;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* This domain class records the info about a file or directory in the
* <code>tex-archive</code> tree.
*
* @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
*/
@Entity(name = "archive_file")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class ArchiveFile implements Searchable {
/**
* This enumeration lists known file types.
*/
public enum FileType {
/**
* The field <code>UNKNOWN</code> contains the indicates an unknown file
* type.
*/
UNKNOWN('?'),
/**
* The field <code>FILE</code> contains the indicates a plain file.
*/
FILE('f'),
/**
* The field <code>DIRECTORY</code> contains the indicator for a
* directory.
*/
DIRECTORY('d'),
/**
* The field <code>ARCHIVE</code> contains the indicator for an archive.
*/
ARCHIVE('a'),
/**
* The field <code>GENERATED</code> contains the indicator for a
* generated file.
*/
GENERATED('g');
/**
* The field <code>id</code> contains the numerical representation.
*/
final int id;
/**
* Creates a new object.
*
* @param id the id
*/
FileType(char id) {
this.id = id;
}
}
/**
* The field <code>id</code> contains the numerical id.
*/
@Id
@GeneratedValue
@EqualsAndHashCode.Exclude
private Long id;
/**
* The field <code>path</code> contains the full path, i.e. the directory
* and the file name.
*/
@Column(length = 1024)
@Default
private String path = null;
/**
* The field <code>name</code> contains the name.
*/
@Column(length = 255)
private String name;
/**
* The field <code>title</code> contains the title.
*/
@Column(length = 255)
private String title;
/**
* The field <code>type</code> contains the file type.
*/
@Enumerated(EnumType.STRING)
@Column
private FileType type;
/**
* The field <code>mtime</code> contains the modification time.
*/
@Column
private long mtime;
/**
* {@inheritDoc}
*
* @see org.ctan.site.services.search.base.Searchable#indexPath()
*/
@Override
public String indexPath() {
return switch (type) {
case FileType.FILE -> "/tex-archive" + path + "#" + name;
default -> "/tex-archive" + path + "/" + (name != null ? name : "");
};
}
/**
* This method is a getter for the boolean property of a file being an
* archive.
*
* @return <code>true</code> iff the file is an archive
*/
public boolean isArchive() {
return type == FileType.ARCHIVE;
}
/**
* This method is a getter for the boolean property of a file being a
* directory.
*
* @return <code>true</code> iff the file is a directory
*/
public boolean isDirectory() {
return type == FileType.DIRECTORY;
}
/**
* This method is a getter for the boolean property of a file being a plain
* file.
*
* @return <code>true</code> iff the file is a plain file
*/
public boolean isFile() {
return type == FileType.FILE;
}
/**
* The method <code>toMap</code> provides means to get the instance as Map.
*
* @return the Map representation
*/
public Map<String, Object> toMap() {
return ImmutableMap.of("id", (Object) getId(),
"type", type.toString(),
"path", path,
"name", name,
"title", title,
"mtime", DateUtils.formatDateTime(mtime),
"isArchive", isArchive(),
"isFile", isFile(),
"isDirectory", isDirectory());
}
/**
* {@inheritDoc}
*
* @see org.ctan.site.services.search.base.Searchable#updateIndex(org.ctan.site.services.search.base.IndexingSession)
*/
@Override
public void updateIndex(IndexingSession session)
throws CorruptIndexException,
IOException {
IndexArgs args = IndexArgs.builder()
.type(IndexType.FILES)
.title(title != null ? title : name)
.display(path)
.content(new String[]{name})
.modified(mtime)
.build();
String indexPath = indexPath();
for (var locale : CtanConfig.LOCALES) {
args.setLocale(locale);
session.updateIndex(indexPath, args);
}
}
}