Skip to content

Commit

Permalink
GPU-1722: REST design and implementation, improvements, javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
guggi committed Sep 3, 2024
1 parent 6282b8c commit 02db4ea
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import com.gentics.api.lib.exception.NodeException;
import com.gentics.contentnode.db.DBUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
* Represents a log entry entity for the publish protocol.
*/
public class PublishLogEntry {

private int id;
Expand All @@ -18,19 +22,38 @@ public class PublishLogEntry {

private int user;

private Date date;
private LocalDateTime date;

public PublishLogEntry() {
}

/**
* Constructs a new PublishLogEntry with the specified object ID, type, status, and user.
* Used to persist entity to database. The id and date fields are auto generated.
*
* @param objId the object ID
* @param type the type of the object
* @param status the status of the publish operation
* @param user the user performing the operation
*/
public PublishLogEntry(int objId, String type, int status, int user) {
this.objId = objId;
this.type = type;
this.state = status;
this.user = user;
}

public PublishLogEntry(int id, int objId, String type, int status, int user, Date date) {
/**
* Constructs a new PublishLogEntry with the specified ID, object ID, type, status, user, and date.
*
* @param id the ID of the log entry
* @param objId the object ID
* @param type the type of the object
* @param status the status of the publish operation
* @param user the user performing the operation
* @param date the date of the log entry
*/
public PublishLogEntry(int id, int objId, String type, int status, int user, LocalDateTime date) {
this.id = id;
this.objId = objId;
this.type = type;
Expand All @@ -39,6 +62,12 @@ public PublishLogEntry(int id, int objId, String type, int status, int user, Dat
this.date = date;
}


/**
* Saves the publish log entry to the database.
*
* @throws NodeException if an error occurs during the save operation
*/
public void save() throws NodeException {
DBUtils.executeInsert(
"INSERT INTO publish_protocol (obj_id, type, state, user) VALUES (?, ?, ?, ?)",
Expand All @@ -50,30 +79,50 @@ public void save() throws NodeException {
});
}

public PublishLogEntry load(int id) throws NodeException {
return DBUtils.select("SELECT * FROM publish_protocol WHERE id = " + id, resultSet -> {
int objId = resultSet.getInt(1);
String type = resultSet.getString(2);
int state = resultSet.getInt(3);
int user = resultSet.getInt(4);
Date date = resultSet.getDate(5);

return new PublishLogEntry(id, objId, type, state, user, date);
/**
* Loads a publish log entry by a specified field and value.
*
* @param fieldName the name of the field
* @param value the value of the field
* @return an Optional containing the publish log entry if found, otherwise empty
* @throws NodeException if an error occurs during the load operation
*/
public Optional<PublishLogEntry> loadByField(String fieldName, int value) throws NodeException {
var query = String.format("SELECT * FROM publish_protocol WHERE %s = %s ORDER BY id DESC", fieldName, value);
return DBUtils.select(query, resultSet -> {
if (resultSet.next()) {
var objId = resultSet.getInt("obj_id");
var type = resultSet.getString("type");
var state = resultSet.getBoolean("state") ? 1 : 0;
var user = resultSet.getInt("user");
var timestamp = resultSet.getTimestamp("date");
LocalDateTime dateTime = timestamp.toLocalDateTime();

return Optional.of(new PublishLogEntry(id, objId, type, state, user, dateTime));
}
return Optional.empty();
});
}

/**
* Loads all publish log entries from the database.
*
* @return a list of publish log entries
* @throws NodeException if an error occurs during the load operation
*/
public List<PublishLogEntry> loadAll() throws NodeException {
return DBUtils.select("SELECT * FROM publish_protocol", resultSet -> {
List<PublishLogEntry> entries = new ArrayList<>();
while (resultSet.next()) {
int id = resultSet.getInt("id");
int objId = resultSet.getInt("obj_id");
String type = resultSet.getString("type");
int state = resultSet.getInt("state");
int user = resultSet.getInt("user");
Date date = resultSet.getDate("date");

entries.add(new PublishLogEntry(id, objId, type, state, user, date));
var id = resultSet.getInt("id");
var objId = resultSet.getInt("obj_id");
var type = resultSet.getString("type");
var state = resultSet.getInt("state");
var user = resultSet.getInt("user");
var timestamp = resultSet.getTimestamp("date");
LocalDateTime dateTime = timestamp.toLocalDateTime();

entries.add(new PublishLogEntry(id, objId, type, state, user, dateTime));
}
return entries;
});
Expand Down Expand Up @@ -120,11 +169,11 @@ public void setUser(int user) {
this.user = user;
}

public Date getDate() {
public LocalDateTime getDate() {
return date;
}

public void setDate(Date date) {
public void setDate(LocalDateTime date) {
this.date = date;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@
import static com.gentics.contentnode.object.Page.TYPE_PAGE;

import com.gentics.api.lib.exception.NodeException;
import com.gentics.contentnode.i18n.I18NHelper;
import com.gentics.contentnode.object.PublishableNodeObject;
import com.gentics.contentnode.rest.exceptions.EntityNotFoundException;
import com.gentics.lib.log.NodeLogger;
import java.util.ArrayList;
import java.util.List;

/**
* Service for managing publish protocol entries.
*/
public class PublishProtocolService {

private static final NodeLogger logger = NodeLogger.getNodeLogger(PublishProtocolService.class);


public PublishProtocolService() {
}


/**
* Logs the publish state of a given object.
*
* @param <T> the type of the publishable node object
* @param object the publishable node object
* @param status the status of the publish operation
* @param user the user performing the operation
* @throws NodeException if an error occurs during logging
*/
public <T extends PublishableNodeObject> void logPublishState(T object, int status, int user)
throws NodeException {
var publishLogEntry = new PublishLogEntry(object.getId(), getType(object.getTType()), status,
Expand All @@ -29,21 +38,44 @@ public <T extends PublishableNodeObject> void logPublishState(T object, int stat
publishLogEntry.save();
}

public PublishLogEntry getPublishLogEntries(int id) throws NodeException {
return new PublishLogEntry().load(id);
/**
* Retrieves a publish log entry by its object ID.
*
* @param objId the object ID of the publish log entry
* @return the publish log entry
* @throws NodeException if an error occurs during retrieval
* @throws EntityNotFoundException if the entry is not found
*/
public PublishLogEntry getPublishLogEntryByObjectId(int objId) throws NodeException {
return new PublishLogEntry().loadByField("obj_id", objId).orElseThrow(
() -> new EntityNotFoundException(I18NHelper.get("publish_protocol.entry_not_found",
String.valueOf(objId))));
}


/**
* Retrieves all publish log entries.
*
* @return a list of publish log entries
* @throws NodeException if an error occurs during retrieval
*/
public List<PublishLogEntry> getPublishLogEntries() throws NodeException {
try {
return new PublishLogEntry().loadAll();
}
catch (Exception e) {
} catch (Exception e) {
logger.error("Something went wrong while retrieving the publish protocol", e);
return new ArrayList<>();
}
}

public String getType(int ttype) {

/**
* Gets the type of the publishable node object.
*
* @param ttype the type code of the publishable node object
* @return the type as a string
*/
private String getType(int ttype) {
return switch (ttype) {
case TYPE_PAGE -> PublishType.PAGE.toString();
case TYPE_FORM -> PublishType.FORM.toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.gentics.contentnode.rest.resource.impl;

import static com.gentics.contentnode.factory.Trx.supply;

import com.gentics.api.lib.exception.NodeException;
import com.gentics.contentnode.etc.ContentNodeHelper;
import com.gentics.contentnode.etc.Function;
import com.gentics.contentnode.factory.Trx;
import com.gentics.contentnode.publish.protocol.PublishLogEntry;
import com.gentics.contentnode.publish.protocol.PublishProtocolService;
import com.gentics.contentnode.rest.model.PublishLogDto;
import com.gentics.contentnode.rest.model.response.GenericItemList;
import com.gentics.contentnode.rest.resource.PublishProtocolResource;
import com.gentics.contentnode.rest.resource.parameter.PagingParameterBean;
import com.gentics.contentnode.rest.util.ListBuilder;
import javax.ws.rs.BeanParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Produces({MediaType.APPLICATION_JSON})
@Path("/publish/state")
public class PublishProtocolResourceImpl implements PublishProtocolResource {

private final PublishProtocolService publishProtocolService = new PublishProtocolService();

private final Function<PublishLogEntry, PublishLogDto> MAP2REST = (publishLogEntry) -> new PublishLogDto(
publishLogEntry.getObjId(),
publishLogEntry.getType(),
publishLogEntry.getState() == 1 ? "ONLINE" : "OFFLINE",
publishLogEntry.getUser(),
publishLogEntry.getDate().toString()
);

@Override
@GET
@Path("/{objId}")
public PublishLogDto get(@PathParam("objId") Integer objId) throws NodeException {
try (Trx trx = ContentNodeHelper.trx()) {
return MAP2REST.apply(this.publishProtocolService.getPublishLogEntryByObjectId(objId));
}
}

@Override
@GET
@Path("/")
public GenericItemList<PublishLogDto> list(
@BeanParam PagingParameterBean paging) throws NodeException {
var publishLogEntries = supply(publishProtocolService::getPublishLogEntries);

return ListBuilder.from(publishLogEntries, MAP2REST)
.page(paging)
.to(new GenericItemList<>());
}

}
2 changes: 2 additions & 0 deletions cms-core/src/main/resources/contentnode_de_DE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ actions=Aktionen
log=Protokoll
rest.general.error=Es ist ein Fehler beim Zugriff auf das Backend System aufgetreten.
rest.invalid.json.error=Das Format des Request Bodies war inkorrekt.
rest.invalid.request=Ungültige Anfrage
rest.incorrect.body.error=Dem Aufruf wurde ein falsches Objekt \u00FCbergeben.
rest.feature.required=Das erforderliche Feature {0} ist nicht aktiviert.
rest.permission.required=Sie haben unzureichende Berechtigungen f\u00FCr diese Anfrage.
Expand Down Expand Up @@ -1139,3 +1140,4 @@ feature.asset_management=Asset Management
feature.asset_management.help=Im Node k\u00F6nnen Bilder und Dateien aus externen Asset Management Systemen \u00FCbernommen werden.
feature.webp_conversion=Automatische WEBP-Konvertierung
feature.webp_conversion.help=Hochgeladene Bilder werden automatisch in das WEBP-Format konvertiert. Scheduler-Task "Convert Images" konvertiert bestehende Bilder in Nodes die das Feature aktiviert haben.
publish_protocol.entry_not_found=Publish Log Eintrag mit ID {0} wurde nicht gefunden.
2 changes: 2 additions & 0 deletions cms-core/src/main/resources/contentnode_en_EN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ log=Log
rest.general.error=An error occurred while accessing the backend system.
rest.invalid.json.error=The format of the request body was incorrect.
rest.incorrect.body.error=The request body contained an incorrect object.
rest.invalid.request=Invalid request.
rest.feature.required=The required feature {0} is not activated.
rest.permission.required=You have insufficient permissions for this request.
validation.policies.anycontent=any content
Expand Down Expand Up @@ -1118,3 +1119,4 @@ feature.asset_management=Asset Management
feature.asset_management.help=It is possible to include images and files from external Asset Management Systems.
feature.webp_conversion=Automatic WEBP conversion
feature.webp_conversion.help=Uploaded images will be automatically converted to WEBP format. Scheduler task "Convert Images" will convert existing images in nodes which have the feature enabled.
publish_protocol.entry_not_found=Publish Log entry with ID {0} not found.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gentics.contentnode.rest.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public record PublishLogDto(
int objId,
String type,
String state,
int user,
String date
) {

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gentics.contentnode.rest.model.response;

import java.io.Serial;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement
public class GenericItemList<T> extends AbstractListResponse<T> {

@Serial
private static final long serialVersionUID = -5713150794537109477L;
}
Loading

0 comments on commit 02db4ea

Please sign in to comment.