/**
* Copyright (c) 2011 - 2015, Lunifera GmbH (Gross Enzersdorf), Loetz KG (Heidelberg)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florian Pirchner - Initial implementation
*/
package org.lunifera.dsl.entity.xtext.linker;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.diagnostics.IDiagnosticConsumer;
import org.eclipse.xtext.util.OnChangeEvictingCache;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
import org.lunifera.dsl.entity.xtext.extensions.Constants;
import org.lunifera.dsl.semantic.common.types.LDataType;
import org.lunifera.dsl.semantic.common.types.LScalarType;
import org.lunifera.dsl.semantic.common.types.LType;
import org.lunifera.dsl.semantic.common.types.LTypedPackage;
import org.lunifera.dsl.semantic.common.types.LunTypesFactory;
import org.lunifera.dsl.semantic.entity.LBean;
import org.lunifera.dsl.semantic.entity.LEntity;
import org.lunifera.dsl.semantic.entity.LEntityAttribute;
import org.lunifera.dsl.semantic.entity.LEntityModel;
import org.lunifera.dsl.semantic.entity.LunEntityFactory;
import org.lunifera.dsl.xtext.lazyresolver.LazyJvmTypeLinker;
import com.google.inject.Inject;
public class EntityLinker extends LazyJvmTypeLinker {
@Inject
private OnChangeEvictingCache cache;
@Override
protected void doLinkModel(final EObject model, IDiagnosticConsumer consumer) {
super.doLinkModel(model, consumer);
cache.execWithoutCacheClear(model.eResource(),
new IUnitOfWork.Void<Resource>() {
@Override
public void process(Resource state) throws Exception {
TreeIterator<EObject> iterator = model.eAllContents();
while (iterator.hasNext()) {
EObject eObject = iterator.next();
if (eObject instanceof LEntity) {
LEntity entity = (LEntity) eObject;
if (entity.isHistorized()) {
applyHistorized(entity);
} else if (entity.isTimedependent()) {
applyTimedependent(entity);
}
}
}
}
});
}
protected void afterModelLinked(EObject model,
IDiagnosticConsumer diagnosticsConsumer) {
super.afterModelLinked(model, diagnosticsConsumer);
// load the super types eager to ensure sub types resolving
LEntityModel lModel = (LEntityModel) model;
for (LTypedPackage lPkg : lModel.getPackages()) {
for (LType lType : lPkg.getTypes()) {
if (lType instanceof LEntity) {
LEntity lEntity = (LEntity) lType;
lEntity.getSuperType();
} else if (lType instanceof LBean) {
LBean lBean = (LBean) lType;
lBean.getSuperType();
}
}
}
}
/**
* Applies the synthetic attributes for historized entities.
*
* @param entity
*/
protected void applyHistorized(LEntity entity) {
LTypedPackage pkg = (LTypedPackage) entity.eContainer();
LEntityAttribute ooid = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
ooid.setName(Constants.PROP__OID);
ooid.setType(findInternalOID(entity, pkg));
entity.getFeatures().add(ooid);
LEntityAttribute version = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
version.setName(Constants.PROP__VERSION);
version.setType(findInternalDatatype(entity, pkg,
Constants.DT_INTERNAL_OBJECT_VERSION));
entity.getFeatures().add(version);
LEntityAttribute current = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
current.setName(Constants.PROP__ISCURRENT);
current.setType(findInternalDatatype(entity, pkg,
Constants.DT_INTERNAL_IS_CURRENT_VERSION));
entity.getFeatures().add(current);
}
/**
* Applies the synthetic attributes for historized entities.
*
* @param entity
*/
protected void applyTimedependent(LEntity entity) {
LTypedPackage pkg = (LTypedPackage) entity.eContainer();
LEntityAttribute ooid = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
ooid.setName(Constants.PROP__OID);
ooid.setType(findInternalOID(entity, pkg));
entity.getFeatures().add(ooid);
LEntityAttribute validFrom = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
validFrom.setName(Constants.PROP__VALID_FROM);
validFrom.setType(findInternalValidDate(entity, pkg,
Constants.DT_INTERNAL_VALID_FROM));
entity.getFeatures().add(validFrom);
LEntityAttribute validUntil = LunEntityFactory.eINSTANCE
.createLEntityAttribute();
validUntil.setName(Constants.PROP__VALID_UNTIL);
validUntil.setType(findInternalValidDate(entity, pkg,
Constants.DT_INTERNAL_VALID_UNTIL));
entity.getFeatures().add(validUntil);
}
/**
* Tries to find the datatype to be used for valid from and valid until.
*
* @param entity
* @param pkg
* @return
*/
private LDataType findInternalValidDate(LEntity entity, LTypedPackage pkg,
String dtName) {
LDataType datatype = null;
for (LType type : pkg.getTypes()) {
if (type instanceof LDataType) {
LDataType temp = (LDataType) type;
if (temp.getName().equals(dtName)) {
datatype = temp;
break;
}
}
}
if (datatype == null) {
datatype = LunTypesFactory.eINSTANCE.createLDataType();
datatype.setName(dtName);
datatype.setDate(true);
datatype.setDateType(entity.getTimedependentDateType());
pkg.getTypes().add(datatype);
}
return datatype;
}
/**
* Tries to find the datatype to be used for valid from and valid until.
*
* @param entity
* @param pkg
* @return
*/
private LScalarType findInternalOID(LEntity entity, LTypedPackage pkg) {
LDataType datatype = null;
for (LType type : pkg.getTypes()) {
if (!type.eIsProxy() && type instanceof LDataType) {
LDataType temp = (LDataType) type;
if (temp.getName().equals(Constants.DT_INTERNAL_OBJECT_ID)) {
datatype = temp;
break;
}
}
}
if (datatype == null) {
datatype = LunTypesFactory.eINSTANCE.createLDataType();
datatype.setName(Constants.DT_INTERNAL_OBJECT_ID);
datatype.setSyntheticFlag(true);
datatype.setSyntheticSelector(Constants.DT_INTERNAL_OBJECT_ID);
// will be resolved later to avoid entity.super calls. Entity.super
// would resolve cross references too early.
datatype.setSyntheticType(entity);
pkg.getTypes().add(datatype);
}
return datatype;
}
/**
* Tries to find the datatype to be used for valid from and valid until.
*
* @param entity
* @param pkg
* @return
*/
private LDataType findInternalDatatype(LEntity entity, LTypedPackage pkg,
String syntheticType) {
LDataType datatype = null;
for (LType type : pkg.getTypes()) {
if (type instanceof LDataType) {
LDataType temp = (LDataType) type;
if (temp.getName().equals(syntheticType)) {
datatype = temp;
break;
}
}
}
if (datatype == null) {
datatype = LunTypesFactory.eINSTANCE.createLDataType();
datatype.setName(syntheticType);
datatype.setSyntheticFlag(true);
datatype.setSyntheticSelector(syntheticType);
pkg.getTypes().add(datatype);
}
return datatype;
}
}