/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.dm.eo.model;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.logging.FlexoLogger;
/**
* @author gpolet
*
*/
public class EOJoin extends EOObject {
private static final Logger logger = FlexoLogger.getLogger(EOJoin.class.getPackage().getName());
private static final String SOURCE_ATTRIBUTE_KEY = "sourceAttribute";
private static final String DESTINATION_ATTRIBUTE_KEY = "destinationAttribute";
private EOAttribute sourceAttribute;
private EOAttribute destinationAttribute;
private EORelationship relationship;
/**
* @param m
* @return
*/
public static EOJoin createJoinFromMap(Map<Object, Object> map, EORelationship relationship) {
EOJoin join = new EOJoin(relationship);
join.setOriginalMap(map);
return join;
}
private EOJoin(EORelationship relationship) {
this.relationship = relationship;
}
public EOJoin(EORelationship relationship, EOAttribute source, EOAttribute destination) throws IllegalArgumentException,
InvalidJoinException {
this(relationship);
setOriginalMap(new HashMap<Object, Object>());
setSourceAttribute(source);
setDestinationAttribute(destination);
}
public EOAttribute getDestinationAttribute() {
return destinationAttribute;
}
public void setDestinationAttribute(EOAttribute destinationAttribute) throws InvalidJoinException {
if (relationship != null) {
if (destinationAttribute != null && destinationAttribute.getEntity() != relationship.getDestinationEntity()) {
throw new IllegalArgumentException(
"The destination attribute that has been set is not from the destination entity of the relationship");
}
checkJoinValidity(sourceAttribute, destinationAttribute);
}
if (this.destinationAttribute != destinationAttribute) {
if (relationship != null && this.destinationAttribute != null) {
relationship.removeFromDestinationAttributes(this.destinationAttribute);
}
this.destinationAttribute = destinationAttribute;
if (relationship != null && destinationAttribute != null) {
relationship.addToDestinationAttributes(destinationAttribute);
}
if (destinationAttribute != null) {
getOriginalMap().put(DESTINATION_ATTRIBUTE_KEY, destinationAttribute.getName());
} else {
getOriginalMap().remove(DESTINATION_ATTRIBUTE_KEY);
}
}
}
public EOAttribute getSourceAttribute() {
return sourceAttribute;
}
private void checkJoinValidity(EOAttribute src, EOAttribute dest) throws InvalidJoinException {
if (src != null && dest != null) {
String srcExternalType = src.getExternalType();
String destExternalType = dest.getExternalType();
if (srcExternalType == null && src.getPrototype() != null) {
srcExternalType = src.getPrototype().getExternalType();
}
if (destExternalType == null && dest.getPrototype() != null) {
destExternalType = dest.getPrototype().getExternalType();
}
if (srcExternalType != null && destExternalType != null) {
if (!srcExternalType.equals(destExternalType)) {
throw new InvalidJoinException(srcExternalType + " cannot be join with " + destExternalType);
}
}
}
}
public void setSourceAttribute(EOAttribute sourceAttribute) throws IllegalArgumentException, InvalidJoinException {
if (relationship != null) {
if (sourceAttribute != null && sourceAttribute.getEntity() != relationship.getEntity()) {
throw new IllegalArgumentException(
"The source attribute that has been set is not from the source entity of the relationship");
}
checkJoinValidity(sourceAttribute, destinationAttribute);
}
if (this.sourceAttribute != sourceAttribute) {
if (relationship != null && this.sourceAttribute != null) {
relationship.removeFromSourceAttributes(this.sourceAttribute);
}
this.sourceAttribute = sourceAttribute;
if (relationship != null && sourceAttribute != null) {
relationship.addToSourceAttributes(sourceAttribute);
}
if (sourceAttribute != null) {
getOriginalMap().put(SOURCE_ATTRIBUTE_KEY, sourceAttribute.getName());
} else {
getOriginalMap().remove(SOURCE_ATTRIBUTE_KEY);
}
}
}
/**
* Overrides resolveObjects
*
* @throws InvalidJoinException
* @throws IllegalArgumentException
*
* @see org.openflexo.foundation.dm.eo.model.EOObject#resolveObjects()
*/
@Override
protected void resolveObjects() {
String src = (String) getOriginalMap().get(SOURCE_ATTRIBUTE_KEY);
if (src != null) {
EOAttribute att = getRelationship().getEntity().attributeNamed(src);
if (att != null) {
try {
setSourceAttribute(att);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not resolve source attribute " + src + " in entity named "
+ getRelationship().getEntity().getName());
}
}
}
String dest = (String) getOriginalMap().get(DESTINATION_ATTRIBUTE_KEY);
if (dest != null) {
if (getRelationship().getDestinationEntity() != null) {
EOAttribute att = getRelationship().getDestinationEntity().attributeNamed(dest);
if (att != null) {
try {
setDestinationAttribute(att);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not resolve destination attribute " + src + " in entity named "
+ getRelationship().getDestinationEntity().getName());
}
}
} else if (logger.isLoggable(Level.WARNING)) {
logger.warning("Destination attribute is not null but the destination entity cannot be resolved");
}
}
}
public EORelationship getRelationship() {
return relationship;
}
public void setRelationship(EORelationship relationship) {
if (getRelationship() != relationship) {
if (getRelationship() != null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("This should not happen: trying to change join from relationship");
}
if (getSourceAttribute() != null) {
getRelationship().removeFromSourceAttributes(getSourceAttribute());
}
if (getDestinationAttribute() != null) {
getRelationship().removeFromDestinationAttributes(getDestinationAttribute());
}
}
this.relationship = relationship;
if (relationship != null) {
if (getSourceAttribute() != null) {
if (getSourceAttribute().getEntity() == relationship.getEntity()) {
relationship.addToSourceAttributes(getSourceAttribute());
} else {
try {
setSourceAttribute(null);
} catch (InvalidJoinException e) {
// NEVER APPEND because arg is null
}
}
}
if (getDestinationAttribute() != null) {
if (getDestinationAttribute().getEntity() == relationship.getDestinationEntity()) {
relationship.addToDestinationAttributes(getDestinationAttribute());
} else {
try {
setDestinationAttribute(null);
} catch (InvalidJoinException e) {
// NEVER APPEND because arg is null
}
}
}
}
}
}
/**
*
*/
public void synchronizeObjectWithOriginalMap() {
Map<Object, Object> map = getOriginalMap();
if (getSourceAttribute() != null) {
map.put(SOURCE_ATTRIBUTE_KEY, getSourceAttribute().getName());
} else {
map.remove(SOURCE_ATTRIBUTE_KEY);
}
if (getDestinationAttribute() != null) {
map.put(DESTINATION_ATTRIBUTE_KEY, getDestinationAttribute().getName());
} else {
map.remove(DESTINATION_ATTRIBUTE_KEY);
}
}
/**
* Overrides delete
*
* @see org.openflexo.foundation.dm.eo.model.EOObject#delete()
*/
@Override
public void delete() {
try {
setSourceAttribute(null);
setDestinationAttribute(null);
} catch (InvalidJoinException e) {
// NEVER APPEND because arg is null
}
if (relationship != null) {
relationship.removeJoin(this);
}
}
/**
* Overrides clearObjects
*
* @see org.openflexo.foundation.dm.eo.model.EOObject#clearObjects()
*/
@Override
protected void clearObjects() {
sourceAttribute = null;
destinationAttribute = null;
}
public String getPListRepresentation() {
return FlexoPropertyListSerialization.getPListRepresentation(getMapRepresentation());
}
/**
* @return
*/
public Map<Object, Object> getMapRepresentation() {
Map<Object, Object> map = new HashMap<Object, Object>();
if (getSourceAttribute() != null) {
map.put(SOURCE_ATTRIBUTE_KEY, getSourceAttribute().getName());
} else {
map.remove(SOURCE_ATTRIBUTE_KEY);
}
if (getDestinationAttribute() != null) {
map.put(DESTINATION_ATTRIBUTE_KEY, getDestinationAttribute().getName());
} else {
map.remove(DESTINATION_ATTRIBUTE_KEY);
}
return map;
}
}