Skip to content

Commit

Permalink
feat: make chargers attributable (#3565)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebhoerl authored Nov 15, 2024
1 parent b8dbeb2 commit 8969b53
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
import org.matsim.api.core.v01.Identifiable;
import org.matsim.api.core.v01.network.Link;
import org.matsim.contrib.ev.charging.ChargingLogic;
import org.matsim.utils.objectattributes.attributable.Attributable;

public interface Charger extends BasicLocation, Identifiable<Charger> {
public interface Charger extends BasicLocation, Identifiable<Charger>, Attributable {
ChargerSpecification getSpecification();

ChargingLogic getLogic();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.contrib.ev.charging.ChargingLogic;
import org.matsim.utils.objectattributes.attributable.Attributes;

import com.google.common.base.Preconditions;

Expand Down Expand Up @@ -77,6 +78,11 @@ public int getPlugCount() {
return specification.getPlugCount();
}

@Override
public Attributes getAttributes() {
return specification.getAttributes();
}

//TODO in order to add a separate coord: adapt DTD, ChargerSpecification and ChargerReader/Writer
// Additionally, the reader and writer should convert coordinates if CRS different than that of the network
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,33 @@

package org.matsim.contrib.ev.infrastructure;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Stack;

import org.matsim.api.core.v01.Id;
import org.matsim.contrib.ev.EvUnits;
import org.matsim.contrib.ev.infrastructure.ImmutableChargerSpecification.ChargerSpecificationBuilder;
import org.matsim.core.utils.io.MatsimXmlParser;
import org.matsim.utils.objectattributes.AttributeConverter;
import org.matsim.utils.objectattributes.attributable.AttributesImpl;
import org.matsim.utils.objectattributes.attributable.AttributesXmlReaderDelegate;
import org.xml.sax.Attributes;

public final class ChargerReader extends MatsimXmlParser {
private final static String CHARGER = "charger";
private final static String ATTRIBUTES = "attributes";
private final static String ATTRIBUTE = "attribute";

private final ChargingInfrastructureSpecification chargingInfrastructure;

private Map<Class<?>, AttributeConverter<?>> attributeConverters = new HashMap<>();
private final AttributesXmlReaderDelegate attributesReader = new AttributesXmlReaderDelegate();

private ChargerSpecificationBuilder currentBuilder = null;
private AttributesImpl currentAttributes = null;

public ChargerReader(ChargingInfrastructureSpecification chargingInfrastructure) {
super(ValidationType.DTD_ONLY);
this.chargingInfrastructure = chargingInfrastructure;
Expand All @@ -41,15 +55,30 @@ public ChargerReader(ChargingInfrastructureSpecification chargingInfrastructure)
@Override
public void startTag(String name, Attributes atts, Stack<String> context) {
if (CHARGER.equals(name)) {
chargingInfrastructure.addChargerSpecification(createSpecification(atts));
currentBuilder = createSpecification(atts);
} else if (ATTRIBUTES.equals(name)) {
currentAttributes = new AttributesImpl();
attributesReader.startTag(name, atts, context, currentAttributes);
} else if (ATTRIBUTE.equals(name)) {
attributesReader.startTag(name, atts, context, currentAttributes);
}
}

@Override
public void endTag(String name, String content, Stack<String> context) {
if (CHARGER.equals(name)) {
chargingInfrastructure.addChargerSpecification(currentBuilder.build());
currentBuilder = null;
} else if (ATTRIBUTES.equals(name)) {
attributesReader.endTag(name, content, context);
currentBuilder.attributes(currentAttributes);
currentAttributes = null;
} else if (ATTRIBUTE.equals(name)) {
attributesReader.endTag(name, content, context);
}
}

private ChargerSpecification createSpecification(Attributes atts) {
private ChargerSpecificationBuilder createSpecification(Attributes atts) {
return ImmutableChargerSpecification.newBuilder()
.id(Id.create(atts.getValue("id"), Charger.class))
.linkId(Id.createLinkId(atts.getValue("link")))
Expand All @@ -58,7 +87,14 @@ private ChargerSpecification createSpecification(Attributes atts) {
.plugPower(EvUnits.kW_to_W(Double.parseDouble(atts.getValue("plug_power"))))
.plugCount(Optional.ofNullable(atts.getValue("plug_count"))
.map(Integer::parseInt)
.orElse(ChargerSpecification.DEFAULT_PLUG_COUNT))
.build();
.orElse(ChargerSpecification.DEFAULT_PLUG_COUNT));
}

public void putAttributeConverters(Map<Class<?>, AttributeConverter<?>> converters) {
this.attributeConverters.putAll(converters);
}

public void putAttributeConverter(Class<?> key, AttributeConverter<?> converter) {
this.attributeConverters.put(key, converter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Identifiable;
import org.matsim.api.core.v01.network.Link;
import org.matsim.utils.objectattributes.attributable.Attributable;

/**
* ChargerSpecification is assumed to be immutable.
Expand All @@ -34,7 +35,7 @@
*
* @author Michal Maciejewski (michalm)
*/
public interface ChargerSpecification extends Identifiable<Charger> {
public interface ChargerSpecification extends Identifiable<Charger>, Attributable {
String DEFAULT_CHARGER_TYPE = "default";
int DEFAULT_PLUG_COUNT = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,27 @@

package org.matsim.contrib.ev.infrastructure;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.matsim.contrib.ev.EvUnits;
import org.matsim.core.utils.collections.Tuple;
import org.matsim.core.utils.io.MatsimXmlWriter;
import org.matsim.utils.objectattributes.AttributeConverter;
import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate;

public final class ChargerWriter extends MatsimXmlWriter {
private final Stream<? extends ChargerSpecification> chargerSpecifications;

private Map<Class<?>, AttributeConverter<?>> attributeConverters = new HashMap<>();
private final AttributesXmlWriterDelegate attributesWriter = new AttributesXmlWriterDelegate();

public ChargerWriter(Stream<? extends ChargerSpecification> chargerSpecifications) {
this.chargerSpecifications = chargerSpecifications;
}
Expand All @@ -45,13 +54,34 @@ public void write(String file) {
close();
}

private void writeChargers() {
private void writeChargers() throws UncheckedIOException {
chargerSpecifications.forEach(c -> {
List<Tuple<String, String>> atts = Arrays.asList(Tuple.of("id", c.getId().toString()),
Tuple.of("link", c.getLinkId() + ""), Tuple.of("type", c.getChargerType()),
Tuple.of("plug_power", EvUnits.W_to_kW(c.getPlugPower()) + ""),
Tuple.of("plug_count", c.getPlugCount() + ""));
writeStartTag("charger", atts, true);
if (c.getAttributes().size() == 0) {
writeStartTag("charger", atts, true);
} else {
writeStartTag("charger", atts, false);

try {
this.writer.write("\n");
} catch (IOException e) {
throw new UncheckedIOException(e);
}

attributesWriter.writeAttributes("\t\t", this.writer, c.getAttributes(), false);
writeEndTag("charger");
}
});
}

public void putAttributeConverters(Map<Class<?>, AttributeConverter<?>> converters) {
this.attributeConverters.putAll(converters);
}

public void putAttributeConverter(Class<?> key, AttributeConverter<?> converter) {
this.attributeConverters.put(key, converter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

package org.matsim.contrib.ev.infrastructure;

import java.util.Collections;
import java.util.Map;

import org.matsim.api.core.v01.network.Network;
import org.matsim.contrib.ev.EvConfigGroup;
import org.matsim.contrib.ev.charging.ChargingLogic;
import org.matsim.core.config.ConfigGroup;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.qsim.AbstractQSimModule;
import org.matsim.utils.objectattributes.AttributeConverter;

import com.google.inject.Inject;
import com.google.inject.Key;
Expand Down Expand Up @@ -55,11 +59,20 @@ public ChargingInfrastructureModule(Key<Network> networkKey) {
public void install() {
bind(Network.class).annotatedWith(Names.named(CHARGERS)).to(networkKey).asEagerSingleton();

bind(ChargingInfrastructureSpecification.class).toProvider(() -> {
ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationDefaultImpl();
new ChargerReader(chargingInfrastructureSpecification).parse(
ConfigGroup.getInputFileURL(getConfig().getContext(), evCfg.chargersFile));
return chargingInfrastructureSpecification;
bind(ChargingInfrastructureSpecification.class).toProvider(new Provider<>() {
@Inject
private Map<Class<?>,AttributeConverter<?>> attributeConverters = Collections.emptyMap();

public ChargingInfrastructureSpecification get() {
ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationDefaultImpl();

ChargerReader reader = new ChargerReader(chargingInfrastructureSpecification);
reader.putAttributeConverters(attributeConverters);
reader.parse(
ConfigGroup.getInputFileURL(getConfig().getContext(), evCfg.chargersFile));

return chargingInfrastructureSpecification;
}
}).asEagerSingleton();

installQSimModule(new AbstractQSimModule() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.utils.objectattributes.attributable.Attributes;
import org.matsim.utils.objectattributes.attributable.AttributesImpl;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
Expand All @@ -39,13 +41,15 @@ public class ImmutableChargerSpecification implements ChargerSpecification {
private final String chargerType;
private final double plugPower;
private final int plugCount;
private final Attributes attributes;

private ImmutableChargerSpecification( ChargerSpecificationBuilder builder ) {
id = Objects.requireNonNull(builder.id);
linkId = Objects.requireNonNull(builder.linkId);
chargerType = Objects.requireNonNull(builder.chargerType);
plugPower = Objects.requireNonNull(builder.plugPower);
plugCount = Objects.requireNonNull(builder.plugCount);
attributes = builder.attributes != null ? builder.attributes : new AttributesImpl();

Preconditions.checkArgument(plugPower >= 0, "Negative plugPower of charger: %s", id);
Preconditions.checkArgument(plugCount >= 0, "Negative plugCount of charger: %s", id);
Expand Down Expand Up @@ -90,6 +94,11 @@ public int getPlugCount() {
return plugCount;
}

@Override
public Attributes getAttributes() {
return attributes;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
Expand All @@ -107,6 +116,7 @@ public static final class ChargerSpecificationBuilder{
private String chargerType;
private Double plugPower;
private Integer plugCount;
private Attributes attributes;

private ChargerSpecificationBuilder() {
}
Expand Down Expand Up @@ -136,6 +146,11 @@ public ChargerSpecificationBuilder plugCount( int val ) {
return this;
}

public ChargerSpecificationBuilder attributes( Attributes val ) {
attributes = val;
return this;
}

public ImmutableChargerSpecification build() {
return new ImmutableChargerSpecification(this);
}
Expand Down
Loading

0 comments on commit 8969b53

Please sign in to comment.