You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by tb...@apache.org on 2013/12/06 17:53:28 UTC
[46/50] [abbrv] git commit: Renamed project
Renamed project
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/commit/39485c57
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/39485c57
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/39485c57
Branch: refs/heads/ODataServlet
Commit: 39485c572aba33bf34f9249f50e94f996c9517d8
Parents: adaca69
Author: Michael Bolz <mi...@apache.org>
Authored: Thu Dec 5 10:03:26 2013 +0100
Committer: Tamara Boehm <ta...@sap.com>
Committed: Fri Dec 6 17:51:38 2013 +0100
----------------------------------------------------------------------
.../annotation-processor-api/pom.xml | 42 +
.../olingo/odata2/api/data/DataSource.java | 200 +++
.../odata2/api/data/DataSourceProcessor.java | 47 +
.../olingo/odata2/api/data/ValueAccess.java | 69 +
.../annotation-processor-core/pom.xml | 48 +
.../annotation/data/AnnotationInMemoryDs.java | 351 ++++
.../annotation/data/AnnotationValueAccess.java | 106 ++
.../annotation/data/BeanPropertyAccess.java | 186 ++
.../odata2/core/annotation/data/DataStore.java | 192 +++
.../annotation/edm/AnnotationEdmProvider.java | 773 +++++++++
.../annotation/processor/ListsProcessor.java | 1630 ++++++++++++++++++
.../core/annotation/util/AnnotationHelper.java | 726 ++++++++
.../core/annotation/util/ClassHelper.java | 105 ++
.../data/AnnotationsInMemoryDsTest.java | 190 ++
.../edm/AnnotationEdmProviderTest.java | 463 +++++
.../odata2/core/annotation/model/Building.java | 95 +
.../odata2/core/annotation/model/City.java | 62 +
.../odata2/core/annotation/model/Employee.java | 187 ++
.../odata2/core/annotation/model/Location.java | 61 +
.../odata2/core/annotation/model/Manager.java | 47 +
.../annotation/model/ModelSharedConstants.java | 25 +
.../odata2/core/annotation/model/Photo.java | 128 ++
.../odata2/core/annotation/model/RefBase.java | 55 +
.../core/annotation/model/ResourceHelper.java | 64 +
.../odata2/core/annotation/model/Room.java | 89 +
.../odata2/core/annotation/model/Team.java | 81 +
.../annotation-processor-webref/pom.xml | 120 ++
.../odata2/ref/annotation/model/Building.java | 97 ++
.../odata2/ref/annotation/model/City.java | 61 +
.../odata2/ref/annotation/model/Employee.java | 192 +++
.../odata2/ref/annotation/model/Location.java | 60 +
.../odata2/ref/annotation/model/Manager.java | 43 +
.../annotation/model/ModelSharedConstants.java | 25 +
.../odata2/ref/annotation/model/Photo.java | 128 ++
.../odata2/ref/annotation/model/RefBase.java | 78 +
.../ref/annotation/model/ResourceHelper.java | 107 ++
.../odata2/ref/annotation/model/Room.java | 88 +
.../odata2/ref/annotation/model/Team.java | 73 +
.../processor/AnnotationPocServiceFactory.java | 202 +++
.../src/main/resources/log4j.xml | 39 +
.../src/main/version/version.html | 27 +
.../src/main/webapp/WEB-INF/web.xml | 48 +
.../src/main/webapp/index.jsp | 116 ++
odata2-annotation-processor/pom.xml | 30 +
.../edm-annotation-api/pom.xml | 42 -
.../olingo/odata2/api/data/DataSource.java | 200 ---
.../odata2/api/data/DataSourceProcessor.java | 47 -
.../olingo/odata2/api/data/ValueAccess.java | 69 -
.../edm-annotation-core/pom.xml | 48 -
.../annotation/data/AnnotationInMemoryDs.java | 351 ----
.../annotation/data/AnnotationValueAccess.java | 106 --
.../annotation/data/BeanPropertyAccess.java | 186 --
.../odata2/core/annotation/data/DataStore.java | 192 ---
.../annotation/edm/AnnotationEdmProvider.java | 773 ---------
.../annotation/processor/ListsProcessor.java | 1630 ------------------
.../core/annotation/util/AnnotationHelper.java | 726 --------
.../core/annotation/util/ClassHelper.java | 105 --
.../data/AnnotationsInMemoryDsTest.java | 190 --
.../edm/AnnotationEdmProviderTest.java | 463 -----
.../odata2/core/annotation/model/Building.java | 95 -
.../odata2/core/annotation/model/City.java | 62 -
.../odata2/core/annotation/model/Employee.java | 187 --
.../odata2/core/annotation/model/Location.java | 61 -
.../odata2/core/annotation/model/Manager.java | 47 -
.../annotation/model/ModelSharedConstants.java | 25 -
.../odata2/core/annotation/model/Photo.java | 128 --
.../odata2/core/annotation/model/RefBase.java | 55 -
.../core/annotation/model/ResourceHelper.java | 64 -
.../odata2/core/annotation/model/Room.java | 89 -
.../odata2/core/annotation/model/Team.java | 81 -
.../edm-annotation-webref/pom.xml | 120 --
.../odata2/ref/annotation/model/Building.java | 97 --
.../odata2/ref/annotation/model/City.java | 61 -
.../odata2/ref/annotation/model/Employee.java | 192 ---
.../odata2/ref/annotation/model/Location.java | 60 -
.../odata2/ref/annotation/model/Manager.java | 43 -
.../annotation/model/ModelSharedConstants.java | 25 -
.../odata2/ref/annotation/model/Photo.java | 128 --
.../odata2/ref/annotation/model/RefBase.java | 78 -
.../ref/annotation/model/ResourceHelper.java | 107 --
.../odata2/ref/annotation/model/Room.java | 88 -
.../odata2/ref/annotation/model/Team.java | 73 -
.../processor/AnnotationPocServiceFactory.java | 202 ---
.../src/main/resources/log4j.xml | 39 -
.../src/main/version/version.html | 27 -
.../src/main/webapp/WEB-INF/web.xml | 48 -
.../src/main/webapp/index.jsp | 116 --
odata2-edm-annotation/pom.xml | 30 -
odata2-lib/odata-ref/pom.xml | 2 +-
pom.xml | 2 +-
90 files changed, 7558 insertions(+), 7558 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-api/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-api/pom.xml b/odata2-annotation-processor/annotation-processor-api/pom.xml
new file mode 100644
index 0000000..e42ec20
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-api/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-annotation-processor-incubating</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <artifactId>olingo-odata2-annotation-processor-api-incubating</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-api-incubating</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSource.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSource.java b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSource.java
new file mode 100644
index 0000000..694f199
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSource.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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.odata2.api.data;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+
+/**
+ * <p>This interface is intended to make it easier to implement an OData
+ * service in cases where all data for each entity set can be provided as a {@link List} of objects from which all
+ * properties described in the
+ * Entity Data Model can be retrieved and set.</p>
+ * <p>By obeying these restrictions, data-source implementations get the
+ * following advantages:
+ * <ul>
+ * <li>All system query options can be handled centrally.</li>
+ * <li>Following navigation paths must only be done step by step.</li>
+ * </ul>
+ * </p>
+ *
+ */
+public interface DataSource {
+
+ /**
+ * Retrieves the whole data list for the specified entity set.
+ * @param entitySet the requested {@link EdmEntitySet}
+ * @return the requested data list
+ */
+ List<?> readData(EdmEntitySet entitySet) throws ODataNotImplementedException, ODataNotFoundException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Retrieves a single data object for the specified entity set and key.
+ * @param entitySet the requested {@link EdmEntitySet}
+ * @param keys the entity key as map of key names to key values
+ * @return the requested data object
+ */
+ Object readData(EdmEntitySet entitySet, Map<String, Object> keys) throws ODataNotImplementedException,
+ ODataNotFoundException, EdmException, ODataApplicationException;
+
+ /**
+ * <p>Retrieves data for the specified function import and key.</p>
+ * <p>This method is called also for function imports that have defined in
+ * their metadata an other HTTP method than <code>GET</code>.</p>
+ * @param function the requested {@link EdmFunctionImport}
+ * @param parameters the parameters of the function import
+ * as map of parameter names to parameter values
+ * @param keys the key of the returned entity set, as map of key names to key values,
+ * if the return type of the function import is a collection of entities
+ * (optional)
+ * @return the requested data object, either a list or a single object;
+ * if the function import's return type is of type <code>Binary</code>,
+ * the returned object(s) must be of type {@link BinaryData}
+ */
+ Object readData(EdmFunctionImport function, Map<String, Object> parameters, Map<String, Object> keys)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException;
+
+ /**
+ * <p>Retrieves related data for the specified source data, entity set, and key.</p>
+ * <p>If the underlying association of the EDM is specified to have target
+ * multiplicity '*' and no target key is given, this method returns a list of
+ * related data, otherwise it returns a single data object.</p>
+ * @param sourceEntitySet the {@link EdmEntitySet} of the source entity
+ * @param sourceData the data object of the source entity
+ * @param targetEntitySet the requested target {@link EdmEntitySet}
+ * @param targetKeys the key of the target entity as map of key names to key values
+ * (optional)
+ * @return the requested releated data object, either a list or a single object
+ */
+ Object readRelatedData(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetKeys) throws ODataNotImplementedException, ODataNotFoundException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Retrieves the binary data and the MIME type for the media resource
+ * associated to the specified media-link entry.
+ * @param entitySet the {@link EdmEntitySet} of the media-link entry
+ * @param mediaLinkEntryData the data object of the media-link entry
+ * @return the binary data and the MIME type of the media resource
+ */
+ BinaryData readBinaryData(EdmEntitySet entitySet, Object mediaLinkEntryData) throws ODataNotImplementedException,
+ ODataNotFoundException, EdmException, ODataApplicationException;
+
+ /**
+ * <p>Creates and returns a new instance of the requested data-object type.</p>
+ * <p>This instance must not be part of the corresponding list and should
+ * have empty content, apart from the key and other mandatory properties.
+ * However, intermediate objects to access complex properties must not be
+ * <code>null</code>.</p>
+ * @param entitySet the {@link EdmEntitySet} the object must correspond to
+ * @return the new data object
+ */
+ Object newDataObject(EdmEntitySet entitySet) throws ODataNotImplementedException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Writes the binary data for the media resource associated to the
+ * specified media-link entry.
+ * @param entitySet the {@link EdmEntitySet} of the media-link entry
+ * @param mediaLinkEntryData the data object of the media-link entry
+ * @param binaryData the binary data of the media resource along with
+ * the MIME type of the binary data
+ */
+ void writeBinaryData(EdmEntitySet entitySet, Object mediaLinkEntryData, BinaryData binaryData)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException;
+
+ /**
+ * Deletes a single data object identified by the specified entity set and key.
+ * @param entitySet the {@link EdmEntitySet} of the entity to be deleted
+ * @param keys the entity key as map of key names to key values
+ */
+ void deleteData(EdmEntitySet entitySet, Map<String, Object> keys) throws ODataNotImplementedException,
+ ODataNotFoundException, EdmException, ODataApplicationException;
+
+ /**
+ * <p>Inserts an instance into the entity list of the specified entity set.</p>
+ * <p>If {@link #newDataObject} has not set the key and other mandatory
+ * properties already, this method must set them before inserting the
+ * instance into the list.</p>
+ * @param entitySet the {@link EdmEntitySet} the object must correspond to
+ * @param data the data object of the new entity
+ */
+ void createData(EdmEntitySet entitySet, Object data) throws ODataNotImplementedException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Deletes the relation from the specified source data to a target entity
+ * specified by entity set and key.
+ * @param sourceEntitySet the {@link EdmEntitySet} of the source entity
+ * @param sourceData the data object of the source entity
+ * @param targetEntitySet the {@link EdmEntitySet} of the target entity
+ * @param targetKeys the key of the target entity as map of key names to key values
+ * (optional)
+ */
+ void deleteRelation(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetKeys) throws ODataNotImplementedException, ODataNotFoundException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Writes a relation from the specified source data to a target entity
+ * specified by entity set and key.
+ * @param sourceEntitySet the {@link EdmEntitySet} of the source entity
+ * @param sourceData the data object of the source entity
+ * @param targetEntitySet the {@link EdmEntitySet} of the relation target
+ * @param targetKeys the key of the target entity as map of key names to key values
+ */
+ void writeRelation(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetKeys) throws ODataNotImplementedException, ODataNotFoundException, EdmException,
+ ODataApplicationException;
+
+ /**
+ * Container to store binary data (as byte array) and the associated MIME type.
+ */
+ public class BinaryData {
+ private final byte[] data;
+ private final String mimeType;
+
+ public BinaryData(final byte[] data, final String mimeType) {
+ this.data = data;
+ this.mimeType = mimeType;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ @Override
+ public String toString() {
+ return "data=" + Arrays.toString(data) + ", mimeType=" + mimeType;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSourceProcessor.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSourceProcessor.java b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSourceProcessor.java
new file mode 100644
index 0000000..2be5663
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/DataSourceProcessor.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.odata2.api.data;
+
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+
+/**
+ * Abstract class for implementation of the centralized parts of OData processing,
+ * allowing to use the simplified {@link DataSource} and {@link ValueAccess} for the
+ * actual data handling.
+ * <br/>
+ * Extend this class and implement a DataSourceProcessor if the default implementation
+ * (<code>ListProcessor</code> found in <code>annotation-processor-core module</code>) has to be overwritten.
+ */
+public abstract class DataSourceProcessor extends ODataSingleProcessor {
+
+ protected final DataSource dataSource;
+ protected final ValueAccess valueAccess;
+
+ /**
+ * Initialize a {@link DataSourceProcessor} in combination with given {@link DataSource} (providing data objects)
+ * and {@link ValueAccess} (accessing values of data objects).
+ *
+ * @param dataSource used for accessing the data objects
+ * @param valueAccess for accessing the values provided by the data objects
+ */
+ public DataSourceProcessor(final DataSource dataSource, final ValueAccess valueAccess) {
+ this.dataSource = dataSource;
+ this.valueAccess = valueAccess;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/ValueAccess.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/ValueAccess.java b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/ValueAccess.java
new file mode 100644
index 0000000..685e1b6
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-api/src/main/java/org/apache/olingo/odata2/api/data/ValueAccess.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.odata2.api.data;
+
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * This interface is intended to access values in a Java object.
+ */
+public interface ValueAccess {
+
+ /**
+ * Retrieves the value of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the requested {@link EdmProperty}
+ * @return the requested property value
+ */
+ public <T> Object getPropertyValue(final T data, final EdmProperty property) throws ODataException;
+
+ /**
+ * Sets the value of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the {@link EdmProperty}
+ * @param value the new value of the property
+ */
+ public <T, V> void setPropertyValue(T data, final EdmProperty property, final V value) throws ODataException;
+
+ /**
+ * Retrieves the Java type of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the requested {@link EdmProperty}
+ * @return the requested Java type
+ */
+ public <T> Class<?> getPropertyType(final T data, final EdmProperty property) throws ODataException;
+
+ /**
+ * Retrieves the value defined by a mapping object for the given data object.
+ * @param data the Java data object
+ * @param mapping the requested {@link EdmMapping}
+ * @return the requested value
+ */
+ public <T> Object getMappingValue(final T data, final EdmMapping mapping) throws ODataException;
+
+ /**
+ * Sets the value defined by a mapping object for the given data object.
+ * @param data the Java data object
+ * @param mapping the {@link EdmMapping}
+ * @param value the new value
+ */
+ public <T, V> void setMappingValue(T data, final EdmMapping mapping, final V value) throws ODataException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/pom.xml b/odata2-annotation-processor/annotation-processor-core/pom.xml
new file mode 100644
index 0000000..4732522
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>olingo-odata2-annotation-processor-core-incubating</artifactId>
+ <packaging>jar</packaging>
+ <name>${project.artifactId}</name>
+
+ <parent>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-annotation-processor-incubating</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-annotation-processor-api-incubating</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-api-incubating</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-api-annotation-incubating</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.olingo</groupId>
+ <artifactId>olingo-odata2-core-incubating</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
new file mode 100644
index 0000000..db03a4c
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
@@ -0,0 +1,351 @@
+/**
+ * *****************************************************************************
+ * 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.odata2.core.annotation.data;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.annotation.edm.EdmMediaResourceContent;
+import org.apache.olingo.odata2.api.annotation.edm.EdmMediaResourceMimeType;
+import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.data.DataSource;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
+import org.apache.olingo.odata2.core.annotation.util.ClassHelper;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper.AnnotatedNavInfo;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper.ODataAnnotationException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+public class AnnotationInMemoryDs implements DataSource {
+
+ private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
+ private final Map<String, DataStore<Object>> dataStores = new HashMap<String, DataStore<Object>>();
+ private final boolean persistInMemory;
+
+ public AnnotationInMemoryDs(String packageToScan) {
+ this(packageToScan, true);
+ }
+
+ public AnnotationInMemoryDs(String packageToScan, boolean persistInMemory) {
+ this.persistInMemory = persistInMemory;
+ List<Class<?>> foundClasses = ClassHelper.loadClasses(packageToScan, new ClassHelper.ClassValidator() {
+ @Override
+ public boolean isClassValid(Class<?> c) {
+ return null != c.getAnnotation(org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet.class);
+ }
+ });
+
+ init(foundClasses);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void init(List<Class<?>> foundClasses) {
+ for (Class<?> clz : foundClasses) {
+
+ DataStore<Object> dhs = (DataStore<Object>) getDataStore(clz);
+ org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet entitySet =
+ clz.getAnnotation(org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet.class);
+ dataStores.put(entitySet.name(), dhs);
+ }
+ }
+
+ public <T> DataStore<T> getDataStore(Class<T> clazz) {
+ return DataStore.createInMemory(clazz, persistInMemory);
+ }
+
+ @Override
+ public List<?> readData(EdmEntitySet entitySet) throws ODataNotImplementedException,
+ ODataNotFoundException, EdmException, ODataApplicationException {
+
+ DataStore<Object> holder = getDataStore(entitySet);
+ if (holder != null) {
+ return new ArrayList<Object>(holder.read());
+ }
+
+ throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+ }
+
+ @Override
+ public Object readData(EdmEntitySet entitySet, Map<String, Object> keys)
+ throws ODataNotFoundException, EdmException, ODataApplicationException {
+
+ DataStore<Object> store = getDataStore(entitySet);
+ if (store != null) {
+ Object keyInstance = store.createInstance();
+ ANNOTATION_HELPER.setKeyFields(keyInstance, keys);
+
+ Object result = store.read(keyInstance);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+ }
+
+ @Override
+ public Object readData(EdmFunctionImport function, Map<String, Object> parameters, Map<String, Object> keys)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+ throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+ }
+
+ @Override
+ public Object readRelatedData(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetKeys)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+
+ DataStore<?> sourceStore = dataStores.get(sourceEntitySet.getName());
+ DataStore<?> targetStore = dataStores.get(targetEntitySet.getName());
+
+ AnnotatedNavInfo navInfo = ANNOTATION_HELPER.getCommonNavigationInfo(
+ sourceStore.getDataTypeClass(), targetStore.getDataTypeClass());
+ Field sourceField = navInfo.getFromField();
+ if (sourceField == null) {
+ throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
+ + "', targetStore='" + targetStore + "').");
+ }
+
+ Object navigationInstance = getValue(sourceField, sourceData);
+ List<Object> resultData = new ArrayList<Object>();
+ for (Object targetInstance : targetStore.read()) {
+ if (navigationInstance instanceof Collection) {
+ for (Object object : (Collection<?>) navigationInstance) {
+ if (ANNOTATION_HELPER.keyMatch(targetInstance, object)) {
+ resultData.add(targetInstance);
+ }
+ }
+ } else if (ANNOTATION_HELPER.keyMatch(targetInstance, navigationInstance)) {
+ resultData.add(targetInstance);
+ }
+ }
+
+ if (navInfo.getToMultiplicity() == EdmMultiplicity.MANY) {
+ if (targetKeys.isEmpty()) {
+ return resultData;
+ } else {
+ for (Object result : resultData) {
+ if (ANNOTATION_HELPER.keyMatch(result, targetKeys)) {
+ return result;
+ }
+ }
+ return null;
+ }
+ } else {
+ if (resultData.isEmpty()) {
+ return null;
+ }
+ return resultData.get(0);
+ }
+ }
+
+ @Override
+ public BinaryData readBinaryData(EdmEntitySet entitySet, Object mediaLinkEntryData)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+
+ Object data = ANNOTATION_HELPER.getValueForField(mediaLinkEntryData, EdmMediaResourceContent.class);
+ Object mimeType = ANNOTATION_HELPER.getValueForField(mediaLinkEntryData, EdmMediaResourceMimeType.class);
+
+ BinaryData db = new BinaryData((byte[]) data, String.valueOf(mimeType));
+ return db;
+ }
+
+ @Override
+ public Object newDataObject(EdmEntitySet entitySet)
+ throws ODataNotImplementedException, EdmException, ODataApplicationException {
+
+ DataStore<Object> dataStore = getDataStore(entitySet);
+ if (dataStore != null) {
+ return dataStore.createInstance();
+ }
+
+ throw new ODataRuntimeException("No DataStore found for entitySet with name: " + entitySet.getName());
+ }
+
+ @Override
+ public void writeBinaryData(EdmEntitySet entitySet, Object mediaEntityInstance, BinaryData binaryData)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+
+ try {
+ ANNOTATION_HELPER.setValueForAnnotatedField(
+ mediaEntityInstance, EdmMediaResourceContent.class, binaryData.getData());
+ ANNOTATION_HELPER.setValueForAnnotatedField(
+ mediaEntityInstance, EdmMediaResourceMimeType.class, binaryData.getMimeType());
+ } catch (ODataAnnotationException e) {
+ throw new ODataRuntimeException("Invalid media resource annotation at entity set '" + entitySet.getName()
+ + "' with message '" + e.getMessage() + "'.", e);
+ }
+ }
+
+ /**
+ * <p>Updates a single data object identified by the specified entity set and key fields of
+ * the data object.</p>
+ * @param entitySet the {@link EdmEntitySet} the object must correspond to
+ * @param data the data object of the new entity
+ * @return updated data object instance
+ * @throws org.apache.olingo.odata2.api.exception.ODataNotImplementedException
+ * @throws org.apache.olingo.odata2.api.edm.EdmException
+ * @throws org.apache.olingo.odata2.api.exception.ODataApplicationException
+ */
+ public Object updateData(EdmEntitySet entitySet, Object data)
+ throws ODataNotImplementedException, EdmException, ODataApplicationException {
+
+ DataStore<Object> dataStore = getDataStore(entitySet);
+ return dataStore.update(data);
+ }
+
+ @Override
+ public void deleteData(EdmEntitySet entitySet, Map<String, Object> keys)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+ DataStore<Object> dataStore = getDataStore(entitySet);
+ Object keyInstance = dataStore.createInstance();
+ ANNOTATION_HELPER.setKeyFields(keyInstance, keys);
+ dataStore.delete(keyInstance);
+ }
+
+ @Override
+ public void createData(EdmEntitySet entitySet, Object data)
+ throws ODataNotImplementedException, EdmException, ODataApplicationException {
+
+ DataStore<Object> dataStore = getDataStore(entitySet);
+ dataStore.create(data);
+ }
+
+ @Override
+ public void deleteRelation(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetKeys)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+ throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+ }
+
+ @Override
+ public void writeRelation(EdmEntitySet sourceEntitySet, Object sourceEntity, EdmEntitySet targetEntitySet,
+ Map<String, Object> targetEntityValues)
+ throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
+ // get common data
+ DataStore<Object> sourceStore = dataStores.get(sourceEntitySet.getName());
+ DataStore<Object> targetStore = dataStores.get(targetEntitySet.getName());
+
+ AnnotatedNavInfo commonNavInfo = ANNOTATION_HELPER.getCommonNavigationInfo(
+ sourceStore.getDataTypeClass(), targetStore.getDataTypeClass());
+
+ // get and validate source fields
+ Field sourceField = commonNavInfo.getFromField();
+ if (sourceField == null) {
+ throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
+ + "', targetStore='" + targetStore + "').");
+ }
+
+ // get related target entity
+ Object targetEntity = targetStore.createInstance();
+ ANNOTATION_HELPER.setKeyFields(targetEntity, targetEntityValues);
+ targetEntity = targetStore.read(targetEntity);
+
+ // set at source
+ setValueAtNavigationField(sourceEntity, sourceField, targetEntity);
+ // set at target
+ Field targetField = commonNavInfo.getToField();
+ if(targetField != null) {
+ setValueAtNavigationField(targetEntity, targetField, sourceEntity);
+ }
+ }
+
+ /**
+ * Set (Multiplicity != *) or add (Multiplicity == *) <code>value</code> at <code>field</code>
+ * of <code>instance</code>.
+ *
+ * @param instance
+ * @param field
+ * @param value
+ * @throws EdmException
+ */
+ private void setValueAtNavigationField(Object instance, Field field, Object value)
+ throws EdmException {
+ Class<?> fieldTypeClass = field.getType();
+ if (Collection.class.isAssignableFrom(fieldTypeClass)) {
+ @SuppressWarnings("unchecked")
+ Collection<Object> collection = (Collection<Object>) ANNOTATION_HELPER.getValueForField(
+ instance, field.getName(), EdmNavigationProperty.class);
+ if(collection == null) {
+ collection = new ArrayList<Object>();
+ setValue(instance, field, collection);
+ }
+ collection.add(value);
+ } else if(fieldTypeClass.isArray()) {
+ throw new ODataRuntimeException("Write relations for internal used arrays is not supported.");
+ } else {
+ setValue(instance, field, value);
+ }
+ }
+
+ /**
+ * Returns corresponding DataStore for EdmEntitySet or if no data store is registered an
+ * ODataRuntimeException is thrown.
+ * Never returns NULL.
+ *
+ * @param entitySet for which the corresponding DataStore is returned
+ * @return a DataStore object
+ * @throws EdmException
+ * @throws ODataRuntimeException if no DataStore is found
+ */
+ private DataStore<Object> getDataStore(EdmEntitySet entitySet) throws EdmException {
+ final String name = entitySet.getName();
+ DataStore<Object> dataStore = dataStores.get(name);
+ if (dataStore == null) {
+ throw new ODataRuntimeException("No DataStore found for entity set '" + entitySet + "'.");
+ }
+ return dataStore;
+ }
+
+ private Object getValue(Field field, Object instance) {
+ try {
+ boolean access = field.isAccessible();
+ field.setAccessible(true);
+ Object value = field.get(instance);
+ field.setAccessible(access);
+ return value;
+ } catch (IllegalArgumentException e) {
+ throw new ODataRuntimeException("Error for getting value of field '"
+ + field + "' at instance '" + instance + "'.", e);
+ } catch (IllegalAccessException e) {
+ throw new ODataRuntimeException("Error for getting value of field '"
+ + field + "' at instance '" + instance + "'.", e);
+ }
+ }
+
+ private void setValue(Object instance, Field field, Object value) {
+ try {
+ boolean access = field.isAccessible();
+ field.setAccessible(true);
+ field.set(instance, value);
+ field.setAccessible(access);
+ } catch (IllegalArgumentException e) {
+ throw new ODataRuntimeException("Error for setting value of field: '"
+ + field + "' at instance: '" + instance + "'.", e);
+ } catch (IllegalAccessException e) {
+ throw new ODataRuntimeException("Error for setting value of field: '"
+ + field + "' at instance: '" + instance + "'.", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
new file mode 100644
index 0000000..14183bf
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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.odata2.core.annotation.data;
+
+import org.apache.olingo.odata2.api.data.ValueAccess;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
+
+/**
+ *
+ */
+public class AnnotationValueAccess implements ValueAccess {
+ private final AnnotationHelper annotationHelper = new AnnotationHelper();
+
+ /**
+ * Retrieves the value of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the requested {@link EdmProperty}
+ * @return the requested property value
+ */
+ @Override
+ public <T> Object getPropertyValue(final T data, final EdmProperty property) throws ODataException {
+ if(data == null) {
+ return null;
+ } else if (annotationHelper.isEdmAnnotated(data)) {
+ return annotationHelper.getValueForProperty(data, property.getName());
+ }
+ throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+ }
+
+ /**
+ * Sets the value of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the {@link EdmProperty}
+ * @param value the new value of the property
+ */
+ @Override
+ public <T, V> void setPropertyValue(T data, final EdmProperty property, final V value) throws ODataException {
+ if (annotationHelper.isEdmAnnotated(data)) {
+ annotationHelper.setValueForProperty(data, property.getName(), value);
+ } else {
+ throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+ }
+ }
+
+ /**
+ * Retrieves the Java type of an EDM property for the given data object.
+ * @param data the Java data object
+ * @param property the requested {@link EdmProperty}
+ * @return the requested Java type
+ */
+ public <T> Class<?> getPropertyType(final T data, final EdmProperty property) throws ODataException {
+ if (annotationHelper.isEdmAnnotated(data)) {
+ Class<?> fieldType = annotationHelper.getFieldTypeForProperty(data, property.getName());
+ if (fieldType == null) {
+ throw new ODataException("No field type found for property " + property);
+ }
+ return fieldType;
+ }
+ throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+ }
+
+ /**
+ * Retrieves the value defined by a mapping object for the given data object.
+ * @param data the Java data object
+ * @param mapping the requested {@link EdmMapping}
+ * @return the requested value
+ */
+ public <T> Object getMappingValue(final T data, final EdmMapping mapping) throws ODataException {
+ if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
+ return annotationHelper.getValueForProperty(data, mapping.getMediaResourceMimeTypeKey());
+ }
+ return null;
+ }
+
+ /**
+ * Sets the value defined by a mapping object for the given data object.
+ * @param data the Java data object
+ * @param mapping the {@link EdmMapping}
+ * @param value the new value
+ */
+ public <T, V> void setMappingValue(T data, final EdmMapping mapping, final V value) throws ODataException {
+ if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
+ annotationHelper.setValueForProperty(data, mapping.getMediaResourceMimeTypeKey(), value);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
new file mode 100644
index 0000000..be3baac
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.odata2.core.annotation.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import org.apache.olingo.odata2.api.data.ValueAccess;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataHttpException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+
+/**
+ * Data access.
+ */
+public class BeanPropertyAccess implements ValueAccess {
+
+ @Override
+ public <T> Object getPropertyValue(final T data, final EdmProperty property) throws ODataException {
+ return getValue(data, getGetterMethodName(property));
+ }
+
+ @Override
+ public <T, V> void setPropertyValue(T data, final EdmProperty property, final V value) throws ODataException {
+ final String methodName = getSetterMethodName(getGetterMethodName(property));
+ if (methodName != null) {
+ setValue(data, methodName, value);
+ }
+ }
+
+ @Override
+ public <T> Class<?> getPropertyType(final T data, final EdmProperty property) throws ODataException {
+ return getType(data, getGetterMethodName(property));
+ }
+
+ @Override
+ public <T> Object getMappingValue(final T data, final EdmMapping mapping) throws ODataException {
+ if (mapping != null && mapping.getMimeType() != null) {
+ return getValue(data, mapping.getMimeType());
+ }
+ return null;
+ }
+
+ @Override
+ public <T, V> void setMappingValue(T data, final EdmMapping mapping, final V value) throws ODataException {
+ if (mapping != null && mapping.getMimeType() != null) {
+ setValue(data, getSetterMethodName(mapping.getMimeType()), value);
+ }
+ }
+
+ private String getGetterMethodName(final EdmProperty property) throws EdmException {
+ final String prefix = isBooleanProperty(property) ? "is" : "get";
+ final String defaultMethodName = prefix + property.getName();
+ return property.getMapping() == null || property.getMapping().getInternalName() == null ?
+ defaultMethodName : property.getMapping().getInternalName();
+ }
+
+ private boolean isBooleanProperty(final EdmProperty property) throws EdmException {
+ return property.isSimple()
+ && property.getType() == EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance();
+ }
+
+ private String getSetterMethodName(final String getterMethodName) {
+ return getterMethodName.contains(".") ?
+ null : getterMethodName.replaceFirst("^is", "set").replaceFirst("^get", "set");
+ }
+
+ private <T> Object getValue(final T data, final String methodName) throws ODataNotFoundException {
+ Object dataObject = data;
+
+ for (final String method : methodName.split("\\.", -1)) {
+ if (dataObject != null) {
+ try {
+ dataObject = dataObject.getClass().getMethod(method).invoke(dataObject);
+ } catch (SecurityException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ } catch (NoSuchMethodException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ } catch (IllegalArgumentException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ } catch (IllegalAccessException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ } catch (InvocationTargetException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ }
+ }
+ }
+
+ return dataObject;
+ }
+
+ private <T, V> void setValue(final T data, final String methodName, final V value)
+ throws ODataNotFoundException {
+ try {
+ boolean found = false;
+ for (final Method method : Arrays.asList(data.getClass().getMethods())) {
+ if (method.getName().equals(methodName)) {
+ found = true;
+ final Class<?> type = method.getParameterTypes()[0];
+ if (value == null) {
+ if (type.equals(byte.class) || type.equals(short.class) || type.equals(int.class)
+ || type.equals(long.class) || type.equals(char.class)) {
+ method.invoke(data, 0);
+ } else if (type.equals(float.class) || type.equals(double.class)) {
+ method.invoke(data, 0.0);
+ } else if (type.equals(boolean.class)) {
+ method.invoke(data, false);
+ } else {
+ method.invoke(data, value);
+ }
+ } else {
+ method.invoke(data, value);
+ }
+ break;
+ }
+ }
+ if (!found) {
+ throw new ODataNotFoundException(null);
+ }
+ } catch (SecurityException e) {
+ throw new ODataNotFoundException(null, e);
+ } catch (IllegalArgumentException e) {
+ throw new ODataNotFoundException(null, e);
+ } catch (IllegalAccessException e) {
+ throw new ODataNotFoundException(null, e);
+ } catch (InvocationTargetException e) {
+ throw new ODataNotFoundException(null, e);
+ }
+ }
+
+ private <T> Class<?> getType(final T data, final String methodName) throws ODataNotFoundException {
+ if (data == null) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON);
+ }
+
+ Class<?> type = data.getClass();
+ for (final String method : methodName.split("\\.", -1)) {
+ try {
+ type = type.getMethod(method).getReturnType();
+ if (type.isPrimitive()) {
+ if (type == boolean.class) {
+ type = Boolean.class;
+ } else if (type == byte.class) {
+ type = Byte.class;
+ } else if (type == short.class) {
+ type = Short.class;
+ } else if (type == int.class) {
+ type = Integer.class;
+ } else if (type == long.class) {
+ type = Long.class;
+ } else if (type == float.class) {
+ type = Float.class;
+ } else if (type == double.class) {
+ type = Double.class;
+ }
+ }
+ } catch (final SecurityException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ } catch (final NoSuchMethodException e) {
+ throw new ODataNotFoundException(ODataHttpException.COMMON, e);
+ }
+ }
+ return type;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/39485c57/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
new file mode 100644
index 0000000..696ab9a
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * 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.odata2.core.annotation.data;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ *
+ */
+public class DataStore<T> {
+
+ private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
+ private final List<T> dataStore;
+ private final Class<T> dataTypeClass;
+
+ private int idCounter = 1;
+
+ private static class InMemoryDataStore {
+ private static final Map<Class<?>, DataStore<?>> c2ds = new HashMap<Class<?>, DataStore<?>>();
+
+ @SuppressWarnings("unchecked")
+ static DataStore<?> getInstance(Class<?> clz, boolean createNewInstance) {
+ DataStore<?> ds = c2ds.get(clz);
+ if (createNewInstance || ds == null) {
+ ds = new DataStore<Object>((Class<Object>) clz);
+ c2ds.put(clz, ds);
+ }
+ return ds;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> DataStore<T> createInMemory(Class<T> clazz) {
+ return (DataStore<T>) InMemoryDataStore.getInstance(clazz, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> DataStore<T> createInMemory(Class<T> clazz, boolean keepExisting) {
+ return (DataStore<T>) InMemoryDataStore.getInstance(clazz, !keepExisting);
+ }
+
+ private DataStore(List<T> wrapStore, Class<T> clz) {
+ dataStore = Collections.synchronizedList(wrapStore);
+ dataTypeClass = clz;
+ }
+
+ private DataStore(Class<T> clz) {
+ this(new ArrayList<T>(), clz);
+ }
+
+ public Class<T> getDataTypeClass() {
+ return dataTypeClass;
+ }
+
+ public String getEntityTypeName() {
+ return ANNOTATION_HELPER.extractEntityTypeName(dataTypeClass);
+ }
+
+ public T createInstance() {
+ try {
+ return dataTypeClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new ODataRuntimeException("Unable to create instance of class '" + dataTypeClass + "'.", e);
+ } catch (IllegalAccessException e) {
+ throw new ODataRuntimeException("Unable to create instance of class '" + dataTypeClass + "'.", e);
+ }
+ }
+
+ public T read(T obj) {
+ List<Object> objKeys = getKeys(obj);
+ for (T stored : dataStore) {
+ if (objKeys.equals(getKeys(stored))) {
+ return stored;
+ }
+ }
+ return null;
+ }
+
+ public Collection<T> read() {
+ return Collections.unmodifiableCollection(dataStore);
+ }
+
+ public T create(T object) throws DataStoreException {
+ synchronized (dataStore) {
+ if (read(object) != null || getKeys(object).contains(null)) {
+ createKeys(object);
+ return this.create(object);
+ }
+ dataStore.add(object);
+ }
+ return object;
+ }
+
+ public T update(T object) {
+ synchronized (dataStore) {
+ T stored = read(object);
+ dataStore.remove(stored);
+ dataStore.add(object);
+ }
+ return object;
+ }
+
+ public T delete(T object) {
+ synchronized (dataStore) {
+ T stored = read(object);
+ if (stored != null) {
+ dataStore.remove(stored);
+ }
+ return stored;
+ }
+ }
+
+ private List<Object> getKeys(T object) {
+ Map<String, Object> keys = ANNOTATION_HELPER.getValueForAnnotatedFields(object, EdmKey.class);
+
+ // XXX: list should be in a defined order -> better to create an 'Key' object which is comparable
+ List<Object> keyList = new ArrayList<Object>(keys.values());
+ return keyList;
+ }
+
+ private T createKeys(T object) throws DataStoreException {
+ List<Field> fields = ANNOTATION_HELPER.getAnnotatedFields(object, EdmKey.class);
+ if (fields.isEmpty()) {
+ throw new DataStoreException("No EdmKey annotated fields found for class " + object.getClass());
+ }
+ Map<String, Object> fieldName2KeyValue = new HashMap<String, Object>();
+
+ for (Field field : fields) {
+ Object key = createKey(field);
+ fieldName2KeyValue.put(ANNOTATION_HELPER.getCanonicalName(field), key);
+ }
+
+ ANNOTATION_HELPER.setValuesToAnnotatedFields(object, EdmKey.class, fieldName2KeyValue);
+
+ return object;
+ }
+
+ private Object createKey(Field field) {
+ Class<?> type = field.getType();
+
+ if (type == String.class) {
+ return String.valueOf(idCounter++);
+ } else if (type == Integer.class || type == int.class) {
+ return Integer.valueOf(idCounter++);
+ } else if (type == Long.class || type == long.class) {
+ return Long.valueOf(idCounter++);
+ }
+
+ throw new UnsupportedOperationException("Automated key generation for type '" + type
+ + "' is not supported (caused on field '" + field + "').");
+ }
+
+ public static class DataStoreException extends ODataApplicationException {
+ private static final long serialVersionUID = 42L;
+
+ public DataStoreException(String message) {
+ this(message, null);
+ }
+
+ public DataStoreException(String message, Throwable cause) {
+ super(message, Locale.ENGLISH, cause);
+ }
+ }
+}