/**
* 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.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
package org.sintef.thingml.resource.thingml.mopp;
/**
* Standard implementation of <code>IContextDependentURIFragment</code>.
*
* @param <ContainerType> the type of the object that contains the reference which
* shall be resolved by this fragment.
* @param <ReferenceType> the type of the reference which shall be resolved by
* this fragment.
*/
public abstract class ThingmlContextDependentURIFragment<ContainerType extends org.eclipse.emf.ecore.EObject, ReferenceType extends org.eclipse.emf.ecore.EObject> implements org.sintef.thingml.resource.thingml.IThingmlContextDependentURIFragment<ReferenceType> {
protected String identifier;
protected ContainerType container;
protected org.eclipse.emf.ecore.EReference reference;
protected int positionInReference;
protected org.eclipse.emf.ecore.EObject proxy;
protected org.sintef.thingml.resource.thingml.IThingmlReferenceResolveResult<ReferenceType> result;
private boolean resolving;
public ThingmlContextDependentURIFragment(String identifier, ContainerType container, org.eclipse.emf.ecore.EReference reference, int positionInReference, org.eclipse.emf.ecore.EObject proxy) {
this.identifier = identifier;
this.container = container;
this.reference = reference;
this.positionInReference = positionInReference;
this.proxy = proxy;
}
public boolean isResolved() {
return result != null;
}
public org.sintef.thingml.resource.thingml.IThingmlReferenceResolveResult<ReferenceType> resolve() {
if (resolving) {
return null;
}
resolving = true;
if (result == null || !result.wasResolved()) {
result = new org.sintef.thingml.resource.thingml.mopp.ThingmlReferenceResolveResult<ReferenceType>(false);
// set an initial default error message
result.setErrorMessage(getStdErrorMessage());
org.sintef.thingml.resource.thingml.IThingmlReferenceResolver<ContainerType, ReferenceType> resolver = getResolver();
// do the actual resolving
resolver.resolve(getIdentifier(), getContainer(), getReference(), getPositionInReference(), false, result);
// EMFText allows proxies to resolve to multiple objects. The first one is
// returned, the others are added here to the reference.
if (result.wasResolvedMultiple()) {
handleMultipleResults();
}
}
resolving = false;
return result;
}
public abstract org.sintef.thingml.resource.thingml.IThingmlReferenceResolver<ContainerType, ReferenceType> getResolver();
private void handleMultipleResults() {
org.eclipse.emf.common.util.EList<org.eclipse.emf.ecore.EObject> list = null;
Object temp = container.eGet(reference);
if (temp instanceof org.eclipse.emf.common.util.EList<?>) {
list = org.sintef.thingml.resource.thingml.util.ThingmlCastUtil.cast(temp);
}
boolean first = true;
for (org.sintef.thingml.resource.thingml.IThingmlReferenceMapping<ReferenceType> mapping : result.getMappings()) {
if (first) {
first = false;
} else if (list != null) {
addResultToList(mapping, proxy, list);
} else {
new org.sintef.thingml.resource.thingml.util.ThingmlRuntimeUtil().logError(container.eClass().getName() + "." + reference.getName() + " has multiplicity 1 but was resolved to multiple elements", null);
}
}
}
private void addResultToList(org.sintef.thingml.resource.thingml.IThingmlReferenceMapping<ReferenceType> mapping, org.eclipse.emf.ecore.EObject proxy, org.eclipse.emf.common.util.EList<org.eclipse.emf.ecore.EObject> list) {
org.eclipse.emf.ecore.EObject target = null;
int proxyPosition = list.indexOf(proxy);
if (mapping instanceof org.sintef.thingml.resource.thingml.IThingmlElementMapping<?>) {
target = ((org.sintef.thingml.resource.thingml.IThingmlElementMapping<ReferenceType>) mapping).getTargetElement();
} else if (mapping instanceof org.sintef.thingml.resource.thingml.IThingmlURIMapping<?>) {
target = org.eclipse.emf.ecore.util.EcoreUtil.copy(proxy);
org.eclipse.emf.common.util.URI uri = ((org.sintef.thingml.resource.thingml.IThingmlURIMapping<ReferenceType>) mapping).getTargetIdentifier();
((org.eclipse.emf.ecore.InternalEObject) target).eSetProxyURI(uri);
} else {
assert false;
}
try {
// if target is an another proxy and list is "unique" add() will try to resolve
// the new proxy to check for uniqueness. There seems to be no way to avoid that.
// Until now this does not cause any problems.
if (proxyPosition + 1 == list.size()) {
list.add(target);
} else {
list.add(proxyPosition + 1, target);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
private String getStdErrorMessage() {
String typeName = this.getReference().getEType().getName();
String msg = typeName + " '" + identifier + "' not declared";
return msg;
}
public String getIdentifier() {
return identifier;
}
public ContainerType getContainer() {
return container;
}
public org.eclipse.emf.ecore.EReference getReference() {
return reference;
}
public int getPositionInReference() {
return positionInReference;
}
public org.eclipse.emf.ecore.EObject getProxy() {
return proxy;
}
}