/**
* Copyright 2009-2013 Oy Vaadin Ltd
*
* Licensed 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 com.vaadin.addon.jpacontainer.fieldfactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.EntityItemProperty;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.v7.data.Property;
import com.vaadin.v7.data.Validator.InvalidValueException;
import com.vaadin.v7.ui.Form;
/**
* TODO test in buffered mode the situation where the field is initially null.
*/
public class OneToOneForm extends Form {
private Object createdInstance;
private String backReferenceId;
@SuppressWarnings("rawtypes")
private EntityItem editedEntityItem;
private Object masterEntity;
private EntityItemProperty property;
@Override
public void setPropertyDataSource(Property newDataSource) {
property = (EntityItemProperty) newDataSource;
masterEntity = property.getItem().getEntity();
// TODO, should use item from generated JPAContainer instead of
// beanitem??
if (newDataSource.getValue() == null) {
try {
createdInstance = newDataSource.getType().newInstance();
if (isBuffered()) {
tryToSetBackReference();
}
editedEntityItem = createItemForInstance(createdInstance);
setItemDataSource(editedEntityItem, getVisiblePropertyIds());
if (isBuffered()) {
newDataSource.setValue(editedEntityItem.getEntity());
createdInstance = null;
}
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
editedEntityItem = getItemForInstance(newDataSource.getValue());
setItemDataSource(editedEntityItem, getVisiblePropertyIds());
}
// super.setPropertyDataSource(newDataSource);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection<?> getVisiblePropertyIds() {
String[] visibleProperties = getJPAContainerFieldFactory()
.getVisibleProperties(editedEntityItem.getEntity().getClass());
Collection<Object> itemPropertyIds;
if (visibleProperties == null) {
itemPropertyIds = new LinkedHashSet(
editedEntityItem.getItemPropertyIds());
} else {
itemPropertyIds = new LinkedHashSet(
Arrays.asList(visibleProperties));
}
// always remove the backReferenceId to avoid eternal loop
// TODO should not trust on convention only
itemPropertyIds.remove(backReferenceId);
return itemPropertyIds;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private EntityItem getItemForInstance(Object createdInstance) {
JPAContainer jpaContainer = getContainer(createdInstance);
EntityItem item = jpaContainer.getItem(jpaContainer.getEntityProvider()
.getIdentifier(createdInstance));
return item;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private EntityItem createItemForInstance(Object createdInstance) {
JPAContainer jpaContainer = getContainer(createdInstance);
if (!isBuffered()) {
// don't actually insert the new item, just create an item around
// it, expect cascades are set in the "owning" entity.
jpaContainer.setWriteThrough(false);
}
Object itemId = jpaContainer.addEntity(createdInstance);
return jpaContainer.getItem(itemId);
}
private JPAContainer<?> getContainer(Object createdInstance) {
FieldFactory formFieldFactory = getJPAContainerFieldFactory();
JPAContainer<?> jpaContainer = formFieldFactory.createJPAContainerFor(
property.getItem().getContainer(), createdInstance.getClass(),
!isBuffered());
return jpaContainer;
}
private FieldFactory getJPAContainerFieldFactory() {
FieldFactory formFieldFactory = (FieldFactory) getFormFieldFactory();
return formFieldFactory;
}
private void tryToSetBackReference() {
try {
Method method = createdInstance.getClass().getMethod(
"set" + masterEntity.getClass().getSimpleName(),
masterEntity.getClass());
method.setAccessible(true);
method.invoke(createdInstance, masterEntity);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void commit() throws SourceException, InvalidValueException {
super.commit();
if (createdInstance != null) {
property.setValue(createdInstance);
}
}
public void setBackReferenceId(String simpleName) {
backReferenceId = simpleName;
}
}