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

org.openrdf.repository.object.advisers.FieldBehaviour Maven / Gradle / Ivy

Go to download

The Object Repository maps Java objects to and from RDF resources and OWL classes to Java classes in a non-intrusive manner that enables developers to work at the object level.

The newest version!
/*
 * Copyright (c) 2012 3 Round Stones Inc., Some rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution. 
 * - Neither the name of the openrdf.org nor the names of its contributors may
 *   be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 */
package org.openrdf.repository.object.advisers;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;

import org.openrdf.query.BindingSet;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.object.advice.Advice;
import org.openrdf.repository.object.advisers.helpers.PropertySet;
import org.openrdf.repository.object.traits.Mergeable;
import org.openrdf.repository.object.traits.ObjectMessage;
import org.openrdf.repository.object.traits.PropertyConsumer;
import org.openrdf.repository.object.traits.Refreshable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Reads and write properties to/from an RDF store before and after a method is
 * called that uses fields with an @Iri annotation.
 */
public final class FieldBehaviour implements Advice, Mergeable,
		Refreshable, PropertyConsumer {
	private final Logger logger = LoggerFactory.getLogger(FieldBehaviour.class);
	private final Class concept;
	private final Class type;
	private final Field field;
	private final PropertySet property;
	private final Object proxy;
	private volatile boolean populated;

	public FieldBehaviour(PropertySet property, Field field, Object proxy) {
		assert field != null;
		assert property != null;
		assert proxy != null;
		this.concept = field.getDeclaringClass();
		this.type = field.getType();
		this.field = field;
		this.property = property;
		this.proxy = proxy;
		try {
			field.setAccessible(true);
		} catch (SecurityException e) {
			logger.warn(e.toString(), e);
		}
	}

	@Override
	public String toString() {
		return field.toString();
	}

	public void usePropertyBindings(String binding, List results) {
		if (property instanceof PropertyConsumer) {
			String var = binding + "_" + field.getName();
			if (results.get(0).getBindingNames().contains(var)) {
				PropertyConsumer pc = (PropertyConsumer) property;
				pc.usePropertyBindings(var, results);
			}
		}
	}

	public void refresh() {
		property.refresh();
	}

	public void merge(Object source) throws RepositoryException {
		if (concept.isAssignableFrom(source.getClass())) {
			try {
				Object value = field.get(source);
				if (value != null) {
					if (Set.class.equals(this.type)) {
						property.addAll((Set) value);
					} else {
						property.add(value);
					}
				}
			} catch (IllegalArgumentException e) {
				throw new AssertionError(e);
			} catch (IllegalAccessException e) {
				IllegalAccessError error;
				error = new IllegalAccessError(e.getMessage());
				error.initCause(e);
				throw error;
			}
		}
	}

	public Object intercept(ObjectMessage message) throws Exception {
		if (populated)
			return message.proceed();
		Object fieldValue = getFieldValue();
		try {
			populateFields(fieldValue);
		} catch (IllegalAccessException e) {
			throw error(e);
		}
		try {
			populated = true;
			return message.proceed();
		} finally {
			populated = false;
			try {
				storeFields(fieldValue);
			} catch (IllegalAccessException e) {
				throw error(e);
			}
		}
	}

	private IllegalAccessError error(IllegalAccessException e) {
		IllegalAccessError error = new IllegalAccessError(e.getMessage());
		error.initCause(e);
		return error;
	}

	private void populateFields(Object fieldValue)
			throws IllegalAccessException {
		if (concept.isAssignableFrom(proxy.getClass())) {
			if (fieldValue != null && String.class.equals(type)) {
				field.set(proxy, fieldValue.toString());
			} else {
				field.set(proxy, fieldValue);
			}
		}
		for (Field f : proxy.getClass().getDeclaredFields()) {
			if (concept.isAssignableFrom(f.getType())) {
				Object behaviour = f.get(proxy);
				if (behaviour != null) {
					if (fieldValue != null && String.class.equals(type)) {
						field.set(behaviour, fieldValue.toString());
					} else {
						field.set(behaviour, fieldValue);
					}
				}
			}
		}
	}

	private void storeFields(Object populated) throws IllegalAccessException {
		if (concept.isAssignableFrom(proxy.getClass())) {
			Object get = field.get(proxy);
			if (get != populated) {
				setFieldValue(get);
			}
		}
		for (Field f : proxy.getClass().getDeclaredFields()) {
			if (concept.isAssignableFrom(f.getType())) {
				Object behaviour = f.get(proxy);
				if (behaviour != null) {
					Object get = field.get(behaviour);
					if (get != populated) {
						setFieldValue(get);
					}
				}
			}
		}
	}

	private Object getFieldValue() {
		if (Set.class.equals(type))
			return property.getAll();
		Object single = property.getSingle();
		if (single == null)
			return nil(type);
		return single;
	}

	private void setFieldValue(Object get) {
		if (Set.class.equals(type))
			property.setAll((Set) get);
		property.setSingle(get);
	}

	private Object nil(Class type) {
		if (!type.isPrimitive())
			return null;
		if (Void.TYPE.equals(type))
			return null;
		if (Boolean.TYPE.equals(type))
			return Boolean.FALSE;
		if (Character.TYPE.equals(type))
			return Character.valueOf((char) 0);
		if (Byte.TYPE.equals(type))
			return Byte.valueOf((byte) 0);
		if (Short.TYPE.equals(type))
			return Short.valueOf((short) 0);
		if (Integer.TYPE.equals(type))
			return Integer.valueOf((int) 0);
		if (Long.TYPE.equals(type))
			return Long.valueOf((long) 0);
		if (Float.TYPE.equals(type))
			return Float.valueOf((float) 0);
		if (Double.TYPE.equals(type))
			return Double.valueOf((double) 0);
		throw new AssertionError();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy