All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.olingo.client.api.domain.ClientEntitySetIterator Maven / Gradle / Ivy

There is a newer version: 3.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.olingo.client.api.domain;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.apache.commons.io.IOUtils;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.data.ResWrap;
import org.apache.olingo.client.api.serialization.ODataDeserializerException;
import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.format.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * OData entity set iterator class.
 * 
* Please don't forget to call the close()>/ method when not needed any more. * * @param concrete ODataEntity implementation * @param concrete ODataEntitySet implementation */ public class ClientEntitySetIterator implements Iterator { /** * Logger. */ private static final Logger LOG = LoggerFactory.getLogger(ClientEntitySetIterator.class); protected final ODataClient odataClient; protected ResWrap cached; private final InputStream stream; private final ContentType contentType; private T entitySet; private final ByteArrayOutputStream osEntitySet; private final String namespaces; private boolean available = true; /** * Constructor. * * @param odataClient client instance getting this request * @param stream source stream. * @param contentType OData format. */ public ClientEntitySetIterator(final ODataClient odataClient, final InputStream stream, final ContentType contentType) { this.odataClient = odataClient; this.stream = stream; this.contentType = contentType; this.osEntitySet = new ByteArrayOutputStream(); if(contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) { namespaces = getAllElementAttributes(stream, "feed", osEntitySet); } else { namespaces = null; try { if (consume(stream, "\"value\":", osEntitySet, true) >= 0) { int c = 0; while (c != '[' && (c = stream.read()) >= 0) { osEntitySet.write(c); } } } catch (IOException e) { LOG.error("Error parsing entity set", e); throw new IllegalStateException(e); } } } @SuppressWarnings("unchecked") @Override public boolean hasNext() { if (available && cached == null) { if (contentType.isCompatible(ContentType.APPLICATION_ATOM_SVC) || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) { cached = nextAtomEntityFromEntitySet(stream, osEntitySet, namespaces); } else { cached = nextJSONEntityFromEntitySet(stream, osEntitySet); } if (cached == null) { available = false; try { entitySet = (T) odataClient.getReader(). readEntitySet(new ByteArrayInputStream(osEntitySet.toByteArray()), contentType); } catch (final ODataDeserializerException e) { available = false; } close(); } } return available; } @Override public E next() { if (hasNext()) { @SuppressWarnings("unchecked") final E res = (E) odataClient.getBinder().getODataEntity(cached); cached = null; return res; } throw new NoSuchElementException("No entity found"); } /** * Unsupported operation. */ @Override public void remove() { throw new UnsupportedOperationException("Operation not supported"); } /** * Closes the current iterator. */ public void close() { IOUtils.closeQuietly(stream); IOUtils.closeQuietly(osEntitySet); } /** * Gets the next link if exists. * * @return next link if exists; null otherwise. */ public URI getNext() { if (entitySet == null) { throw new IllegalStateException("Iteration must be completed in order to retrieve the link for next page"); } return entitySet.getNext(); } private ResWrap nextJSONEntityFromEntitySet(final InputStream input, final OutputStream osEntitySet) { final ByteArrayOutputStream entity = new ByteArrayOutputStream(); ResWrap jsonEntity = null; try { int c; boolean foundNewOne = false; do { c = input.read(); if (c == '{') { entity.write(c); c = -1; foundNewOne = true; } if (c == ']') { osEntitySet.write(c); c = -1; } } while (c >= 0); if (foundNewOne) { int objectCount = 1; int stringCount = 0; c = 0; boolean previousCharIsEscape = false; while (objectCount > 0 && c >= 0) { c = input.read(); if (c == '{' && stringCount <= 0) { objectCount++; } else if (c == '}' && stringCount <= 0) { objectCount--; // Detect JSON Strings to be able to correctly detect an Entity } else if (c == '"' && stringCount <= 0 && !previousCharIsEscape) { stringCount++; } else if (c == '"' && stringCount > 0 && !previousCharIsEscape) { stringCount--; } entity.write(c); if (c == '\\' && !previousCharIsEscape) { previousCharIsEscape = true; } else { previousCharIsEscape = false; } } if (c >= 0) { jsonEntity = odataClient.getDeserializer(ContentType.JSON).toEntity( new ByteArrayInputStream(entity.toByteArray())); } } else { while ((c = input.read()) >= 0) { osEntitySet.write(c); } } } catch (Exception e) { LOG.error("Error retrieving entities from EntitySet", e); } return jsonEntity; } private ResWrap nextAtomEntityFromEntitySet( final InputStream input, final OutputStream osEntitySet, final String namespaces) { final ByteArrayOutputStream entity = new ByteArrayOutputStream(); ResWrap atomEntity = null; try { if (consume(input, "", osEntitySet, false) >= 0) { entity.write("".getBytes(Constants.UTF8)); if (consume(input, "", entity, true) >= 0) { atomEntity = odataClient.getDeserializer(ContentType.APPLICATION_ATOM_XML). toEntity(new ByteArrayInputStream(entity.toByteArray())); } } } catch (Exception e) { LOG.error("Error retrieving entities from EntitySet", e); } return atomEntity; } private String getAllElementAttributes(final InputStream input, final String name, final OutputStream os) { final ByteArrayOutputStream attrs = new ByteArrayOutputStream(); String res; try { byte[] attrsDeclaration = null; final String key = "<" + name + " "; if (consume(input, key, os, true) >= 0 && consume(input, ">", attrs, false) >= 0) { attrsDeclaration = attrs.toByteArray(); os.write(attrsDeclaration); os.write('>'); } res = attrsDeclaration == null ? "" : new String(attrsDeclaration, Constants.UTF8).trim(); } catch (Exception e) { LOG.error("Error retrieving entities from EntitySet", e); res = ""; } return res.endsWith("/") ? res.substring(0, res.length() - 1) : res; } private int consume( final InputStream input, final String end, final OutputStream os, final boolean includeEndKey) throws IOException { final char[] endKey = end.toCharArray(); final char[] endLowerKey = end.toLowerCase().toCharArray(); final char[] endUpperKey = end.toUpperCase().toCharArray(); int pos = 0; int c = 0; while (pos < endKey.length && (c = input.read()) >= 0) { if (c == endLowerKey[pos] || c == endUpperKey[pos]) { pos++; if (includeEndKey && os != null) { os.write(c); } } else if (pos > 0) { if (!includeEndKey && os != null) { for (int i = 0; i < pos; i++) { os.write(endKey[i]); } } if (os != null) { os.write(c); } pos = 0; } else { if (os != null) { os.write(c); } } } return c; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy