source: OAIProvider/trunk/src/main/java/eu/clarin/oai/provider/impl/VerbEnumerateRecord.java @ 1911

Last change on this file since 1911 was 1911, checked in by oschonef, 12 years ago
  • first round of major refactoring to simply the provider
    • result sets converted to iterator/cursor-mode (better streaming support)
    • delegate serializing of records to Result and ResultList?
    • prepare getting rid of over-engineered and complicated MetadataFormats? classes (not done, yet)

HEADS UP: breaks existing API

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1package eu.clarin.oai.provider.impl;
2
3import java.io.IOException;
4import java.util.Date;
5import java.util.List;
6
7import javax.xml.stream.XMLStreamException;
8import javax.xml.stream.XMLStreamWriter;
9
10import eu.clarin.oai.provider.MetadataFormat;
11import eu.clarin.oai.provider.OAIException;
12import eu.clarin.oai.provider.Record;
13import eu.clarin.oai.provider.RecordList;
14import eu.clarin.oai.provider.ext.Argument;
15import eu.clarin.oai.provider.ext.OAIErrorCode;
16import eu.clarin.oai.provider.ext.OAIOutputStream;
17import eu.clarin.oai.provider.ext.RepositoryAdapter;
18import eu.clarin.oai.provider.ext.ResumptionToken;
19import eu.clarin.oai.provider.ext.Verb;
20import eu.clarin.oai.provider.ext.VerbContext;
21
22abstract class VerbEnumerateRecord extends Verb {
23    private static final Argument[] ARGUMENTS = {
24        DefaultArguments.FROM,
25        DefaultArguments.UNTIL,
26        DefaultArguments.SET,
27        DefaultArguments.METADATAPREFIX,
28        DefaultArguments.RESUMPTIONTOKEN
29    };
30
31    protected VerbEnumerateRecord() {
32    }
33
34    @Override
35    public final Argument[] getArguments() {
36        return ARGUMENTS;
37    }
38
39    @Override
40    public final void process(VerbContext ctx) throws IOException,
41            XMLStreamException, OAIException {
42        logger.debug("process ENUMERATE-RECORD ({})", getName());
43
44        RepositoryAdapter repository = ctx.getRepository();
45        String prefix = null;
46        String set = null;
47        Date from = null;
48        Date until = null;
49        int offset = 0;
50        boolean resume = false;
51       
52        if (ctx.hasArgument(DefaultArguments.ARG_RESUMPTIONTOKEN)) {
53            final Long id =
54                (Long) ctx.getArgument(DefaultArguments.ARG_RESUMPTIONTOKEN);
55            ResumptionToken token = repository.getResumptionToken(id);
56            if (token == null) {
57                ctx.addError(OAIErrorCode.BAD_RESUMPTION_TOKEN,
58                        "Invalid resumption token (id='" + id + "')");
59                return; // bail early
60            }
61            synchronized (token) {
62                prefix = token.getMetadataPrefix();
63                set    = token.getSet();
64                from   = token.getFrom();
65                until  = token.getUntil();
66                offset = token.getNextOffset();
67            } // synchronized (token)
68            resume = true;
69        } else {
70            prefix = (String) ctx.getArgument(DefaultArguments.ARG_METADATAPREFIX);
71            set    = (String) ctx.getArgument(DefaultArguments.ARG_SET);
72            from   = (Date)   ctx.getArgument(DefaultArguments.ARG_FROM);
73            until  = (Date)   ctx.getArgument(DefaultArguments.ARG_UNTIL);
74        }
75
76        MetadataFormat format = repository.getMetadataFormatByPrefix(prefix);
77        if (format != null) {
78            if ((set != null) && !repository.isUsingSets()) {
79                ctx.addError(OAIErrorCode.NO_SET_HIERARCHY,
80                        "Repository does not support sets");
81            } else {
82                // fetch records
83                final RecordList result = doGetRecords(repository, prefix,
84                        from, until, set, offset);
85
86                // process results
87                if (result != null) {
88                    try {
89                        OAIOutputStream out = ctx.getOutputStream();
90                        out.writeStartElement(getName());
91                        int size = 0;
92                       
93                        // emulate a record ...
94                        Record record = new Record() {
95                            @Override
96                            public Object getLocalId() {
97                                return result.getLocalId();
98                            }
99
100                            @Override
101                            public Date getDatestamp() {
102                                return result.getDatestamp();
103                            }
104
105                            @Override
106                            public boolean isDeleted() {
107                                return result.isDeleted();
108                            }
109
110                            @Override
111                            public List<String> getSetSpecs() {
112                                return result.getSetSpecs();
113                            }
114
115                            public void writeRecord(XMLStreamWriter writer)
116                                    throws XMLStreamException {
117                                result.writeRecord(writer);
118                            }
119                        };
120
121                        // process results
122                        while (result.next()) {
123                            doWriteRecord(repository, out, format, record);
124                            size++;
125                        } // while
126
127                        /*
128                         * add resumption token, if more results are pending or
129                         * if this is the last batch of result list
130                         */
131                        if (resume || !result.isListComplete()) {
132                            ResumptionToken token = null;
133                            if (!result.isListComplete()) {
134                                token = repository.createResumptionToken();
135                                final int nextOffset = size + offset;
136                                synchronized (token) {
137                                    token.setMetadataPrefix(prefix);
138                                    token.setSet(set);
139                                    token.setFrom(from);
140                                    token.setUntil(until);
141                                    token.setNextOffset(nextOffset);
142                                    token.setCursor(offset);
143                                    token.setCompleteListSize(
144                                            result.getTotalSize());
145                                } // synchronized (token)
146                            }
147                            out.writeResumptionToken(token);
148                        }
149                        out.writeEndElement(); // ListRecords element
150                        out.close();
151                    } finally {
152                        result.close();
153                    }
154                } else {
155                    ctx.addError(OAIErrorCode.NO_RECORDS_MATCH,
156                            "No records match");
157                }
158            }
159        } else {
160            ctx.addError(OAIErrorCode.CANNOT_DISSERMINATE_FORMAT,
161                    "Repository does not support metadataPrefix '" +
162                    prefix + "'");
163        }
164    }
165
166    protected abstract RecordList doGetRecords(RepositoryAdapter repository,
167            String prefix, Date from, Date until, String set, int offset)
168            throws OAIException;
169
170    protected abstract void doWriteRecord(RepositoryAdapter repository,
171            OAIOutputStream out, MetadataFormat format, Record record)
172            throws XMLStreamException;
173
174} // abstract class VerbEnumerateRecord
Note: See TracBrowser for help on using the repository browser.