Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Commit 9349c43

Browse files
committed
Merge pull request #32 from jateeter/master
Self and UP <link> support in the export path.
2 parents d9030a0 + 8bebce1 commit 9349c43

File tree

5 files changed

+132
-33
lines changed

5 files changed

+132
-33
lines changed

src/main/java/org/energyos/espi/common/models/atom/adapters/TimeConfigurationAdapter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013 EnergyOS.org
2+
* Copyright 2013, 2014 EnergyOS.org
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@
1818

1919
import org.energyos.espi.common.domain.ObjectFactory;
2020
import org.energyos.espi.common.domain.TimeConfiguration;
21+
import org.energyos.espi.common.utils.AtomMarshallerListener;
2122

2223
import javax.xml.bind.JAXBElement;
2324
import javax.xml.bind.annotation.adapters.XmlAdapter;
24-
2525
public class TimeConfigurationAdapter extends XmlAdapter<JAXBElement<TimeConfiguration>, TimeConfiguration> {
26-
26+
2727
@Override
2828
public TimeConfiguration unmarshal(JAXBElement<TimeConfiguration> v) throws Exception {
2929
return v.getValue();
@@ -34,6 +34,7 @@ public JAXBElement<TimeConfiguration> marshal(TimeConfiguration v) throws Except
3434
if(v == null) {
3535
return null;
3636
}
37-
return new JAXBElement<>(ObjectFactory.LocalTimeParameters_QNAME, TimeConfiguration.class, v);
37+
JAXBElement<TimeConfiguration> element = new JAXBElement<>(ObjectFactory.LocalTimeParameters_QNAME, TimeConfiguration.class, v);
38+
return element;
3839
}
3940
}

src/main/java/org/energyos/espi/common/service/ApplicationInformationService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ public ApplicationInformation findByDataCustodianClientId(
4949
// import-export services
5050
public ApplicationInformation importResource(InputStream stream);
5151

52-
ApplicationInformation findByUUID(UUID uuid);
52+
public ApplicationInformation findByUUID(UUID uuid);
53+
54+
public void setApplicationInformation(ApplicationInformation applicationInformation);
55+
56+
public String getDataCustodianResourceEndpoint();
5357

5458
}

src/main/java/org/energyos/espi/common/service/impl/ApplicationInformationServiceImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
@Transactional
2727
public class ApplicationInformationServiceImpl implements ApplicationInformationService {
2828

29+
// the cached operational object for this service
30+
//
31+
private ApplicationInformation applicationInformation;
32+
2933
@Autowired
3034
private ApplicationInformationRepository applicationInformationRepository;
3135

@@ -46,6 +50,23 @@ public void setApplicationInformationRepository(ApplicationInformationRepository
4650
this.applicationInformationRepository = applicationInformationRepository;
4751
}
4852

53+
// configuration accessors
54+
55+
@Override
56+
public void setApplicationInformation(ApplicationInformation applicationInformation) {
57+
this.applicationInformation = applicationInformation;
58+
}
59+
60+
@Override
61+
public String getDataCustodianResourceEndpoint() {
62+
if (this.applicationInformation == null) {
63+
// default it to the seed value
64+
this.setApplicationInformation(this.findById(1L));
65+
}
66+
return applicationInformation.getDataCustodianResourceEndpoint();
67+
// return "http://localhost:8080/DataCustodian/espi/1_1/resource";
68+
}
69+
4970
@Override
5071
public List<ApplicationInformation> findAll() {
5172
return applicationInformationRepository.findAll();

src/main/java/org/energyos/espi/common/service/impl/ExportServiceImpl.java

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.energyos.espi.common.utils.DateConverter;
1919
import org.energyos.espi.common.utils.EntryTypeIterator;
2020
import org.energyos.espi.common.utils.ExportFilter;
21+
import org.energyos.espi.common.utils.AtomMarshallerListener;
2122
import org.springframework.beans.factory.annotation.Autowired;
2223
import org.springframework.beans.factory.annotation.Qualifier;
2324
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@@ -26,6 +27,7 @@
2627

2728
import javax.servlet.ServletOutputStream;
2829
import javax.xml.bind.JAXBException;
30+
import javax.xml.bind.Marshaller;
2931
import javax.xml.bind.Unmarshaller;
3032
import javax.xml.transform.stream.StreamResult;
3133

@@ -471,15 +473,12 @@ public void exportUsagePointFull(Long usagePointId, Long retailCustomerId,
471473
//
472474

473475
private void buildHeader (OutputStream stream, String hrefFragment) throws IOException {
476+
477+
String selfRef = "<link ref=\"self\" href=\"" + applicationInformationService.getDataCustodianResourceEndpoint() + hrefFragment + "\"/>";
474478
DateTimeType updated = DateConverter.toDateTimeType(new Date());
475479
String temp = updated.getValue().toXMLFormat();
476480
String uuid = UUID.randomUUID().toString();
477-
478-
String selfRef = "<link rel=\"self\" href=\"/espi/1_1/resource" + hrefFragment + "\"/>\n";
479-
480-
//GregorianCalendar updated = new GregorianCalendar();
481-
//updated.setTimeZone(TimeZone.getTimeZone("UTC"))
482-
//String temp = DateConverter.epoch().toString();
481+
483482
stream.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".getBytes());
484483
stream.write("<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">".getBytes());
485484
stream.write("<id>urn:uuid:".getBytes());
@@ -492,31 +491,37 @@ private void buildHeader (OutputStream stream, String hrefFragment) throws IOExc
492491
stream.write(selfRef.getBytes());
493492
}
494493

495-
private void exportEntries(EntryTypeIterator entries, OutputStream stream, ExportFilter exportFilter, Class resourceClass, String hrefFragment) throws IOException {
496-
497-
buildHeader(stream, hrefFragment);
494+
private void exportEntries(EntryTypeIterator entries, OutputStream stream,
495+
ExportFilter exportFilter, Class resourceClass, String hrefFragment)
496+
throws IOException {
498497

499-
if (entries != null) {
500-
501-
while (entries.hasNext()) {
502-
try {
503-
EntryType entry = entries.nextEntry(resourceClass);
504-
exportEntry(entry, stream, exportFilter, hrefFragment);
505-
} catch (Exception e) {
506-
stream.write("/* The requested collection contains no resources */".getBytes());
507-
stream.write("</feed>".getBytes());
508-
}
509-
510-
}
511-
}
512-
stream.write("</feed>".getBytes());
513-
}
498+
buildHeader(stream, hrefFragment);
499+
500+
if (entries != null) {
501+
502+
while (entries.hasNext()) {
503+
try {
504+
EntryType entry = entries.nextEntry(resourceClass);
505+
exportEntry(entry, stream, exportFilter, hrefFragment);
506+
} catch (Exception e) {
507+
stream.write("/* The requested collection contains no resources */"
508+
.getBytes());
509+
stream.write("</feed>".getBytes());
510+
}
511+
512+
}
513+
}
514+
stream.write("</feed>".getBytes());
515+
}
514516

515517
// to export a single entry (w/o the <feed>...</feed> wrappers
516518

517519
private void exportEntry(EntryType entry, OutputStream stream,
518520
ExportFilter exportFilter, String hrefFragment) throws IOException {
519521

522+
AtomMarshallerListener uriListener = new AtomMarshallerListener(applicationInformationService.getDataCustodianResourceEndpoint() + hrefFragment);
523+
fragmentMarshaller.setMarshallerListener(uriListener);
524+
520525
StreamResult result = new StreamResult(stream);
521526
try {
522527
if (exportFilter.matches(entry)) {
@@ -528,8 +533,10 @@ private void exportEntry(EntryType entry, OutputStream stream,
528533
}
529534

530535
private void exportEntriesFull(EntryTypeIterator entries, OutputStream stream, ExportFilter exportFilter, String hrefFragment) throws IOException {
531-
532-
buildHeader(stream, hrefFragment);
536+
537+
// construct the <feed> header components
538+
//
539+
buildHeader(stream, hrefFragment);
533540

534541
if (entries != null) {
535542

@@ -550,8 +557,13 @@ private void exportEntriesFull(EntryTypeIterator entries, OutputStream stream, E
550557
// to export a single entry (w/o the <feed>...</feed> wrappers
551558

552559
private void exportEntryFull(EntryType entry, OutputStream stream,
553-
ExportFilter exportFilter, String hrefFragement) throws IOException {
554-
560+
ExportFilter exportFilter, String hrefFragment) throws IOException {
561+
562+
// setup a listener so that the adapters may later be fed the href fragment;
563+
//
564+
AtomMarshallerListener uriListener = new AtomMarshallerListener(applicationInformationService.getDataCustodianResourceEndpoint() + hrefFragment);
565+
fragmentMarshaller.setMarshallerListener(uriListener);
566+
555567
StreamResult result = new StreamResult(stream);
556568
try {
557569
if (exportFilter.matches(entry)) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
package org.energyos.espi.common.utils;
3+
4+
import javax.xml.bind.Marshaller;
5+
6+
import org.energyos.espi.common.models.atom.EntryType;
7+
import org.energyos.espi.common.models.atom.LinkType;
8+
9+
public class AtomMarshallerListener extends Marshaller.Listener {
10+
11+
private String hrefFragment;
12+
long depth;
13+
14+
public AtomMarshallerListener(String fragment) {
15+
this.hrefFragment = fragment;
16+
}
17+
18+
@Override
19+
public void beforeMarshal(Object source) {
20+
depth++;
21+
if ((source instanceof LinkType) && (((LinkType) source).getRel().equals("self"))) {
22+
((LinkType) source).setHref(mutateFragment((LinkType) source, this.hrefFragment, 0));
23+
}
24+
if ((source instanceof LinkType) && (((LinkType) source).getRel().equals("up"))) {
25+
26+
((LinkType) source).setHref(mutateFragment((LinkType) source, this.hrefFragment, 1));
27+
}
28+
}
29+
30+
@Override
31+
public void afterMarshal(Object source) {
32+
depth--;
33+
}
34+
35+
public String getHrefFragment() {
36+
return this.hrefFragment;
37+
}
38+
39+
// mutate the fragment based upon up/self/ref semantics
40+
//
41+
private String mutateFragment(Object source, String hrefFragment, Integer key) {
42+
String temp = hrefFragment;
43+
switch (key) {
44+
case 0: // a "self" reference - it should be fine
45+
break;
46+
case 1: // an "up" reference - make sure that if it has a "/id" on the tail, that it is dropped, otherwise its ""
47+
Integer i = temp.lastIndexOf("/");
48+
String t = temp.substring(i+1);
49+
if (t.matches("-?\\d+(\\.\\d+)?")) {
50+
temp = temp.substring(0, i);
51+
}
52+
break;
53+
default:
54+
// TODO for now, do nothing, but rel="ref" will be a problem
55+
break;
56+
57+
}
58+
return temp;
59+
60+
}
61+
}

0 commit comments

Comments
 (0)