Skip to content

Commit

Permalink
implement design creation incl. persistence
Browse files Browse the repository at this point in the history
  • Loading branch information
Darkwyng committed Dec 31, 2022
1 parent 7b1ccf5 commit 7321edf
Show file tree
Hide file tree
Showing 18 changed files with 341 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import com.pim.stars.design.imp.persistence.DesignRepository;
import com.pim.stars.id.IdConfiguration;
import com.pim.stars.id.api.IdCreator;

public interface DesignConfiguration {

Expand All @@ -19,8 +21,13 @@ public static class Provided {
}

@Configuration
@Import({ Provided.class })
@Import({ Provided.class, IdConfiguration.Complete.class })
public static class Complete {

}

public static interface Required {

public IdCreator idCreator();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.pim.stars.design.api;

import com.pim.stars.design.api.types.DesignType;
import com.pim.stars.gadget.api.types.HullType;

public interface Design {

Expand All @@ -10,5 +10,5 @@ public interface Design {

public String getOwnerId();

public DesignType getDesignType();
public HullType getHullType();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.pim.stars.design.api;

import com.pim.stars.gadget.api.Gadget;
import com.pim.stars.gadget.api.hull.GadgetSlot;
import com.pim.stars.gadget.api.hull.Hull;
import com.pim.stars.game.api.Game;
import com.pim.stars.race.api.Race;
Expand All @@ -10,13 +9,9 @@ public interface DesignDefiner {

public DesignBuilder start(Game game, Race race, Hull hull);

public DesignBuilder start(Game game, String raceId, String hullId);

public interface DesignBuilder {

public DesignBuilder fillSlot(GadgetSlot slot, Gadget gadget, int numberOfGadgets);

public DesignBuilder fillSlot(String slotId, String gadgetId, int numberOfGadgets);
public DesignBuilder fillSlot(String slotId, Gadget gadget, int numberOfGadgets);

public Design build(String designName);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.pim.stars.design.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.pim.stars.design.api.Design;
import com.pim.stars.design.api.DesignDefiner;
import com.pim.stars.design.imp.persistence.DesignEntity;
import com.pim.stars.design.imp.persistence.DesignEntity.DesignEntityId;
import com.pim.stars.design.imp.persistence.DesignEntity.DesignEntityStatus;
import com.pim.stars.design.imp.persistence.DesignEntity.FilledGadgetSlot;
import com.pim.stars.design.imp.persistence.DesignRepository;
import com.pim.stars.gadget.api.Gadget;
import com.pim.stars.gadget.api.hull.GadgetSlot;
import com.pim.stars.gadget.api.hull.Hull;
import com.pim.stars.gadget.api.types.HullType;
import com.pim.stars.game.api.Game;
import com.pim.stars.id.api.IdCreator;
import com.pim.stars.race.api.Race;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Component
public class DesignDefinerImp implements DesignDefiner {

@Autowired
private IdCreator idCreator;
@Autowired
private DesignRepository designRepository;

@Override
public DesignBuilder start(final Game game, final Race race, final Hull hull) {
return new DesignBuilderImp(game, race.getId(), hull);
}

private class DesignBuilderImp implements DesignBuilder {

private final DesignEntity entity = new DesignEntity();
private final Hull hull;

public DesignBuilderImp(final Game game, final String ownerId, final Hull hull) {
entity.setEntityId(new DesignEntityId(idCreator.createId(), game.getId(), game.getYear()));
entity.setOwnerId(ownerId);
entity.setHullId(hull.getId());
this.hull = hull;
}

@Override
public DesignBuilder fillSlot(final String slotId, final Gadget gadget, final int numberOfGadgets) {
final GadgetSlot slot = hull.getGadgetSlots().stream()
.filter(candidate -> candidate.getSlotId().equals(slotId)).findFirst()
.orElseThrow(() -> incorrectSlotException(hull.getId(), slotId));
return fillSlot(slot, gadget, numberOfGadgets);
}

private DesignBuilder fillSlot(final GadgetSlot slot, final Gadget gadget, final int numberOfGadgets) {
final String slotId = slot.getSlotId();
ensureSlotNotAlreadyFilled(slotId);
ensureGadgetAllowedInSlot(slot, gadget, numberOfGadgets);

entity.getFilledGadgetSlots().add(new FilledGadgetSlot(slotId, gadget.getId(), numberOfGadgets));

return this;
}

private void ensureSlotNotAlreadyFilled(final String slotId) {
final boolean slotIsAlreadyFilled = entity.getFilledGadgetSlots().stream()
.anyMatch(candidate -> candidate.getSlotId().equals(slotId));
if (slotIsAlreadyFilled) {
throw new IllegalArgumentException("The slot with ID " + slotId + " has already been filled.");
}
}

private void ensureGadgetAllowedInSlot(final GadgetSlot slot, final Gadget gadget, final int numberOfGadgets) {
if (!slot.getAllowedGadgetTypes().stream()
.anyMatch(type -> type.getId().equals(gadget.getGadgetType().getId()))) {
throw new IllegalArgumentException("The slot with ID " + slot.getSlotId()
+ " does not allow gadget with ID " + gadget.getId() + ", because type "
+ gadget.getGadgetType() + " is not contained in the list of allowed gadget types: "
+ slot.getAllowedGadgetTypes());
} else if ((slot.getMinimumNumberOfGadgets() > numberOfGadgets)
|| (slot.getMaximumNumberOfGadgets() < numberOfGadgets)) {
throw new IllegalArgumentException("The slot with ID " + slot.getSlotId() + " does not allow to add "
+ numberOfGadgets + ". It must be between " + slot.getMinimumNumberOfGadgets() + " and "
+ slot.getMaximumNumberOfGadgets() + ".");
}
}

@Override
public Design build(final String designName) {
entity.setName(designName);
entity.setHullTypeId(hull.getHullType().getId());
entity.setStatus(DesignEntityStatus.EDITABLE.getId());
designRepository.save(entity);
return new DesignImp(entity.getEntityId().getId(), entity.getName(), entity.getOwnerId(),
hull.getHullType());
}

private IllegalArgumentException incorrectSlotException(final String hullId, final String slotId) {
return new IllegalArgumentException("The hull with the ID " + hullId + " has no slot with ID " + slotId);
}
}

@Getter
@AllArgsConstructor
private class DesignImp implements Design {

private final String id;
private final String name;
private final String ownerId;
private final HullType hullType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -17,33 +18,38 @@ public class DesignEntity {
@Id
private DesignEntityId entityId;
private String ownerId;
private String designTypeId;

private String name;
private String status;

private String hullId;
private String hullTypeId;
private Collection<FilledGadgetSlot> filledGadgetSlots = new ArrayList<>();
}

@Getter
@Setter
class FilledGadgetSlot {
@Getter
@AllArgsConstructor
public static class FilledGadgetSlot {

private String slotId;
private String gadgetId;
private int numberOfGadgets;
}
private final String slotId;
private final String gadgetId;
private final int numberOfGadgets;
}

@Getter
@Setter
class DesignEntityId {
@Getter
@AllArgsConstructor
public static class DesignEntityId {

private final String id;
private final String gameId;
private final int year;
}

public static enum DesignEntityStatus {

private String id;
private String gameId;
private int year;
}
EDITABLE, ACTIVE, DELETED;

enum DesignEntityStatus {
EDITABLE, ACTIVE, DELETED;
public String getId() {
return name();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import com.pim.stars.design.imp.persistence.DesignEntity.DesignEntityId;

@Repository
public interface DesignRepository extends MongoRepository<DesignEntity, DesignEntityId> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public interface GadgetSlot {

public String getId();
public String getSlotId();

public int getMinimumNumberOfGadgets();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public class GadgetProperties {

private List<String> gadgetFilePaths = Arrays.asList("com/pim/stars/gadget/imp/gadgets.xml");
private List<String> hullFilePaths = Arrays.asList("com/pim/stars/gadget/imp/hulls.xml");

private String markerForVeryFlexibleSlot = "Any";
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
@Component
public class GadgetProviderImp implements GadgetProvider {

private static final String MARKER_FOR_VERY_FLEXIBLE_SLOT = "Any";

private Collection<Gadget> gadgets = null;
private Collection<Hull> hulls = null;

Expand Down Expand Up @@ -136,7 +134,7 @@ protected Collection<GadgetType> getGadgetTypesOfSlot(final String hullId, final
final String allowedGadgetTypeIds = slot.getAllowedGadgetTypeIds();
if (allowedGadgetTypeIds == null || Strings.isNullOrEmpty(allowedGadgetTypeIds.trim())) {
throw gadgetTypeParsingError(hullId, slot, "The list of types is empty.");
} else if (MARKER_FOR_VERY_FLEXIBLE_SLOT.equals(allowedGadgetTypeIds)) {
} else if (gadgetProperties.getMarkerForVeryFlexibleSlot().equals(allowedGadgetTypeIds)) {
return getGadgetTypesForVeryFlexibleSlot();
} else {
final Collection<String> unknownTypeIds = new ArrayList<>();
Expand All @@ -159,7 +157,7 @@ protected Collection<GadgetType> getGadgetTypesOfSlot(final String hullId, final
}
}

private Collection<GadgetType> getGadgetTypesForVeryFlexibleSlot() {
protected Collection<GadgetType> getGadgetTypesForVeryFlexibleSlot() {
if (gadgetTypesForVeryFlexibleSlot == null) {
gadgetTypesForVeryFlexibleSlot = gadgetTypeByIdMap.values().stream()
.filter(type -> !type.getId().equals("Engine")).collect(Collectors.toUnmodifiableList());
Expand All @@ -172,7 +170,7 @@ private IllegalArgumentException gadgetTypeParsingError(final String hullId, fin
final String errorMessage) {
return new IllegalArgumentException("The alllowedGadgetTypeIds '" + slot.getAllowedGadgetTypeIds()
+ "' of slot '" + slot.getId() + "' of hull '" + hullId + "' could not be parsed."
+ " It is expected to be either '" + MARKER_FOR_VERY_FLEXIBLE_SLOT
+ " It is expected to be either '" + gadgetProperties.getMarkerForVeryFlexibleSlot()
+ "' or a comma separated list of IDs of gadget types. " + errorMessage);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@ToString
public class GadgetSlotImp implements GadgetSlot {

private final String id;
private final String slotId;

private final int minimumNumberOfGadgets;
private final int maximumNumberOfGadgets;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package com.pim.stars.design;

import static org.mockito.Mockito.mock;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;

import com.pim.stars.design.imp.persistence.DesignRepository;
import com.pim.stars.id.api.IdCreator;

public class DesignTestConfiguration implements DesignConfiguration.Required {

public class DesignTestConfiguration {
@Bean
@Override
public IdCreator idCreator() {
return mock(IdCreator.class);
}

@Configuration
@Import({ DesignTestConfiguration.class, DesignConfiguration.Provided.class })
Expand Down
Loading

0 comments on commit 7321edf

Please sign in to comment.