|  | 
|  | 1 | +/* Copyright 2013 Pascal Christoph. | 
|  | 2 | + * Licensed under the Eclipse Public License 1.0 */ | 
|  | 3 | + | 
|  | 4 | +package org.metafacture.biblio; | 
|  | 5 | + | 
|  | 6 | +import org.metafacture.framework.FluxCommand; | 
|  | 7 | +import org.metafacture.framework.MetafactureException; | 
|  | 8 | +import org.metafacture.framework.ObjectReceiver; | 
|  | 9 | +import org.metafacture.framework.annotations.Description; | 
|  | 10 | +import org.metafacture.framework.annotations.In; | 
|  | 11 | +import org.metafacture.framework.annotations.Out; | 
|  | 12 | +import org.metafacture.framework.helpers.DefaultObjectPipe; | 
|  | 13 | + | 
|  | 14 | +import java.io.IOException; | 
|  | 15 | +import java.io.InputStream; | 
|  | 16 | +import java.io.InputStreamReader; | 
|  | 17 | +import java.io.Reader; | 
|  | 18 | +import java.net.HttpURLConnection; | 
|  | 19 | +import java.net.URL; | 
|  | 20 | + | 
|  | 21 | +/** | 
|  | 22 | + * Opens an SRU (Search Retrieval by URL) stream and passes a reader to the receiver. | 
|  | 23 | + * The input should be the base URL of the SRU service to be retrieved from. | 
|  | 24 | + * | 
|  | 25 | + * @author Pascal Christoph (dr0i) | 
|  | 26 | + */ | 
|  | 27 | +@Description("Opens a SRU stream and passes a reader to the receiver. The input should be the base URL of the SRU service to be retrieved from. Mandatory argument is: QUERY.") | 
|  | 28 | +@In(String.class) | 
|  | 29 | +@Out(Reader.class) | 
|  | 30 | +@FluxCommand("open-sru") | 
|  | 31 | +public final class SruOpener extends DefaultObjectPipe<String, ObjectReceiver<Reader>> { | 
|  | 32 | + | 
|  | 33 | +    private static final String OPERATION = "searchRetrieve"; | 
|  | 34 | +    private static final String RECORD_SCHEMA = "MARC21-xml"; | 
|  | 35 | +    private static final String USER_AGENT = ""; | 
|  | 36 | +    private static final String VERSION = "2.0"; | 
|  | 37 | + | 
|  | 38 | +    private static final int CONNECTION_TIMEOUT = 11000; | 
|  | 39 | +    private static final int MAXIMUM_RECORDS = 10; | 
|  | 40 | +    private static final int START_RECORD = 1; | 
|  | 41 | +    private static final int MINIMUM_LOOKUP_LENGTH =768; | 
|  | 42 | + | 
|  | 43 | +    private String operation = OPERATION; | 
|  | 44 | +    private String query; | 
|  | 45 | +    private String recordSchema = RECORD_SCHEMA; | 
|  | 46 | +    private String userAgent = USER_AGENT; | 
|  | 47 | +    private String version = VERSION; | 
|  | 48 | + | 
|  | 49 | +    private int maximumRecords = MAXIMUM_RECORDS; | 
|  | 50 | +    private int startRecord = START_RECORD; | 
|  | 51 | +    private int totalRecords; | 
|  | 52 | + | 
|  | 53 | +    private boolean stopRetrieving; | 
|  | 54 | + | 
|  | 55 | + | 
|  | 56 | +    /** | 
|  | 57 | +     * Creates an instance of {@link SruOpener} | 
|  | 58 | +     */ | 
|  | 59 | +    public SruOpener() { | 
|  | 60 | +    } | 
|  | 61 | + | 
|  | 62 | +    /** | 
|  | 63 | +     * Sets the User Agent to use. <strong>Default value: {@value USER_AGENT}</strong>. | 
|  | 64 | +     * | 
|  | 65 | +     * @param userAgent a user agent to be used when opening a URL | 
|  | 66 | +     */ | 
|  | 67 | +    public void setUserAgent(final String userAgent) { | 
|  | 68 | +        this.userAgent = userAgent; | 
|  | 69 | +    } | 
|  | 70 | + | 
|  | 71 | +    /** | 
|  | 72 | +     * Sets the query of the search. | 
|  | 73 | +     * <strong>Setting a query is mandatory.</strong> | 
|  | 74 | +     * | 
|  | 75 | +     * @param query the query | 
|  | 76 | +     */ | 
|  | 77 | + | 
|  | 78 | +    public void setQuery(final String query) { | 
|  | 79 | +        this.query = query; | 
|  | 80 | +    } | 
|  | 81 | + | 
|  | 82 | +    /** | 
|  | 83 | +     * Sets total number of records to be retrieved. <strong>Default value: indefinite (as in "all")</strong>. | 
|  | 84 | +     * | 
|  | 85 | +     * @param totalRecords total number of records to be retrieved | 
|  | 86 | +     */ | 
|  | 87 | +    public void setTotal(final String totalRecords) { | 
|  | 88 | +        this.totalRecords = Integer.parseInt(totalRecords); | 
|  | 89 | +    } | 
|  | 90 | + | 
|  | 91 | +    /** | 
|  | 92 | +     * Sets the maximum of records returned in one lookup. <strong>Default value: {@value MAXIMUM_RECORDS}</strong>. | 
|  | 93 | +     * The lookup is repeated as long as {@link #maximumRecords} is lesser than {@link #totalRecords}. | 
|  | 94 | +     * | 
|  | 95 | +     * @param maximumRecords maximum of records returned in one lookup | 
|  | 96 | +     */ | 
|  | 97 | +    public void setMaximumRecords(final String maximumRecords) { | 
|  | 98 | +        this.maximumRecords = Integer.parseInt(maximumRecords); | 
|  | 99 | +    } | 
|  | 100 | + | 
|  | 101 | +    /** | 
|  | 102 | +     * Sets where to start when retrieving records. <strong>Default value: {@value START_RECORD}</strong>. | 
|  | 103 | +     * | 
|  | 104 | +     * @param startRecord where to start when retrieving records | 
|  | 105 | +     */ | 
|  | 106 | +    public void setStartRecord(final String startRecord) { | 
|  | 107 | +            this.startRecord = Integer.parseInt(startRecord); | 
|  | 108 | +    } | 
|  | 109 | + | 
|  | 110 | +    /** | 
|  | 111 | +     * Sets the format of the retrieved record data. <strong>Default value: {@value RECORD_SCHEMA}</strong>. | 
|  | 112 | +     * | 
|  | 113 | +     * @param recordSchema the format of the data of the records | 
|  | 114 | +     */ | 
|  | 115 | +    public void setRecordSchema(final String recordSchema) { | 
|  | 116 | +        this.recordSchema = recordSchema; | 
|  | 117 | +    } | 
|  | 118 | + | 
|  | 119 | +    /** | 
|  | 120 | +     * Sets the kind of operation of the lookup. <strong>Default value: {@value OPERATION}</strong>. | 
|  | 121 | +     * | 
|  | 122 | +     * @param operation the kind of operation of the lookup | 
|  | 123 | +     */ | 
|  | 124 | +    public void setOperation(final String operation) { | 
|  | 125 | +        this.operation = operation; | 
|  | 126 | +    } | 
|  | 127 | + | 
|  | 128 | +    /** | 
|  | 129 | +     * Sets the version of the lookup. <strong>Default value: {@value VERSION}</strong>. | 
|  | 130 | +     * | 
|  | 131 | +     * @param version the version of the lookup | 
|  | 132 | +     */ | 
|  | 133 | +    public void setVersion(final String version) { | 
|  | 134 | +        this.version = version; | 
|  | 135 | +    } | 
|  | 136 | + | 
|  | 137 | +    @Override | 
|  | 138 | +    public void process(final String baseUrl) { | 
|  | 139 | + | 
|  | 140 | +        try { | 
|  | 141 | + | 
|  | 142 | +            StringBuilder srUrl = new StringBuilder(baseUrl); | 
|  | 143 | +            if (query != null) { | 
|  | 144 | +                srUrl.append("?query=").append(query).append("&operation=").append(operation).append("&recordSchema=").append(recordSchema).append("&version=").append(version); | 
|  | 145 | +            } | 
|  | 146 | +            else { | 
|  | 147 | +                throw new IllegalArgumentException("Missing mandatory parameter 'query'"); | 
|  | 148 | +            } | 
|  | 149 | +            int retrievedRecords = 0; | 
|  | 150 | +            while (!stopRetrieving && (totalRecords==0 || retrievedRecords < totalRecords)) { | 
|  | 151 | +                if (totalRecords >0) { | 
|  | 152 | +                    int yetToRetrieveRecords = totalRecords - retrievedRecords ; | 
|  | 153 | +                    if (yetToRetrieveRecords < maximumRecords) { | 
|  | 154 | +                        maximumRecords = yetToRetrieveRecords; | 
|  | 155 | +                    } | 
|  | 156 | +                } | 
|  | 157 | +                retrieve(srUrl, startRecord, maximumRecords); //todo: bis max lookup zuviel (bis der nämlich sehr klein ist => keine | 
|  | 158 | +                // Ergebnisse mehr) | 
|  | 159 | +                startRecord = startRecord + maximumRecords; | 
|  | 160 | +                retrievedRecords = retrievedRecords + maximumRecords; | 
|  | 161 | +            } | 
|  | 162 | +        } | 
|  | 163 | +        catch (final IOException e) { | 
|  | 164 | +            throw new MetafactureException(e); | 
|  | 165 | +        } | 
|  | 166 | +    } | 
|  | 167 | + | 
|  | 168 | +    private void retrieve(StringBuilder srUrl, int startRecord, int maximumRecords) throws IOException { | 
|  | 169 | +        final URL urlToOpen = new URL(srUrl.toString() + "&maximumRecords=" + maximumRecords+"&startRecord=" + startRecord); | 
|  | 170 | +        final HttpURLConnection connection = (HttpURLConnection) urlToOpen.openConnection(); | 
|  | 171 | + | 
|  | 172 | +        connection.setConnectTimeout(CONNECTION_TIMEOUT); | 
|  | 173 | +        if (!userAgent.isEmpty()) { | 
|  | 174 | +            connection.setRequestProperty("User-Agent", userAgent); | 
|  | 175 | +        } | 
|  | 176 | +        InputStream istream = getInputStream(connection); | 
|  | 177 | +        try ( | 
|  | 178 | +            InputStreamReader inputStreamReader = new InputStreamReader(istream); | 
|  | 179 | +        ) { | 
|  | 180 | +            System.out.println("urlToOpen="+urlToOpen.toString()); | 
|  | 181 | +            System.out.print(", startRecord="+startRecord); | 
|  | 182 | +            System.out.print(", maximumRecords="+maximumRecords); | 
|  | 183 | +            System.out.print(", istream.length="+istream.available()); | 
|  | 184 | +            System.out.println(); | 
|  | 185 | +            if (istream.available() < 768){ // we take it that this is a result without a record | 
|  | 186 | +                stopRetrieving = true; | 
|  | 187 | +            } | 
|  | 188 | + | 
|  | 189 | +            getReceiver().process(inputStreamReader); | 
|  | 190 | +        } | 
|  | 191 | +    } | 
|  | 192 | + | 
|  | 193 | +    private InputStream getInputStream(final HttpURLConnection connection) { | 
|  | 194 | +        try { | 
|  | 195 | +            return connection.getInputStream(); | 
|  | 196 | +        } | 
|  | 197 | +        catch (final IOException e) { | 
|  | 198 | +            stopRetrieving = true; | 
|  | 199 | +            return connection.getErrorStream(); | 
|  | 200 | +        } | 
|  | 201 | +    } | 
|  | 202 | + | 
|  | 203 | +} | 
0 commit comments