/**
*
*/
package com.sap.furcas.runtime.parser.impl.context;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sap.furcas.runtime.common.exceptions.ModelAdapterException;
import com.sap.furcas.runtime.common.interfaces.IModelElementInvestigator;
import com.sap.furcas.runtime.common.interfaces.IModelElementProxy;
/**
* During an injection, caches lookups within contexts
*/
class ContextLookUpCache {
Map<Context, Map<KeySignature, Object>> cache = new HashMap<Context, Map<KeySignature,Object>>();
// placeholder in cache to indicate context does not contain object
// private final static Object NOT_FOUND_OBJECT = new Object();
/**
* looks through all elements in the given context and checks using the modelAdapter
* whether they are of the given type and have the correct key value if they are.
* @param modelAdapter
* @param context
* @param valueTypeName
* @param keyValue
* @param keyName
* @return
* @throws ModelAdapterException
* @throws AmbiguousLookupException
*/
Object findCandidatesInContext(IModelElementInvestigator modelAdapter,
Context context, List<String> valueTypeName, Object keyValue,
String keyName) throws ModelAdapterException, AmbiguousLookupException {
// caching disabled because it may be buggy for creation of Objects during resolving of references
// KeySignature keySignature = new KeySignature(valueTypeName, keyValue, keyName);
// // caching because ModelManager Operations can take long
// Object candidate = lookUpInCache(context, keySignature);
//
// // candidate may be null, that means we never looked for it, or it may be the NOT_FOUND_OBJECT
// if (candidate == NOT_FOUND_OBJECT) {
// return null;
// }
//
//// if not found in cache
// if (candidate == null) {
Object candidate = lookUpInContext(modelAdapter, context,
valueTypeName, keyValue, keyName);
// // store for next cache lookup
// if (candidate == null) {
// cache.get(context).put(keySignature, NOT_FOUND_OBJECT);
// } else {
// cache.get(context).put(keySignature, candidate);
// }
//// }
return candidate;
}
/**
*
*/
public void clear() {
cache.clear();
}
// private Object lookUpInCache(Context context, KeySignature keySignature) {
//
// Map<KeySignature, Object> cachedContextSignatures = cache.get(context);
//
// if (cachedContextSignatures == null) {
// cachedContextSignatures = new HashMap<KeySignature, Object>();
// cache.put(context, cachedContextSignatures);
// return null;
// }
//
// // cache for context existed
// return cachedContextSignatures.get(keySignature);
//
// }
/** loops through elemens in context and first checks type than value
**/
private Object lookUpInContext(IModelElementInvestigator modelAdapter, Context context,
List<String> valueTypeName, Object keyValue, String keyName)
throws ModelAdapterException, AmbiguousLookupException {
Object candidate = null;
Object loopCandidate;
Object metatype = modelAdapter.getMetaType(valueTypeName);
for(ContextIterator i = context.iterator() ; i.hasNext() ; ) {
loopCandidate = i.next();
if (loopCandidate instanceof IModelElementProxy) {
loopCandidate = ((IModelElementProxy) loopCandidate).getRealObject();
}
// check type of context object is of valueTypeName
if (modelAdapter.instanceOf(loopCandidate, metatype)) {
// check key value (identity) of loop candidate
if (keyValue != null && keyValue.equals(modelAdapter.get(loopCandidate, keyName))) {
if (candidate == null ) {
candidate = loopCandidate;
} else {
if (candidate != loopCandidate ) {
throw new AmbiguousLookupException(context, candidate, loopCandidate);
} else { // element is duplicate in iterator, this is a bug, but not a harmful one
continue;
}
}
}
}
} // end for context
return candidate;
}
private class KeySignature {
private List<String> valueTypeName;
private Object keyValue;
private String keyName;
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return valueTypeName.toString() +'.'+keyName + '=' + keyValue;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((keyName == null) ? 0 : keyName.hashCode());
result = prime * result
+ ((keyValue == null) ? 0 : keyValue.hashCode());
result = prime * result
+ ((valueTypeName == null) ? 0 : valueTypeName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final KeySignature other = (KeySignature) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
if (keyValue == null) {
if (other.keyValue != null)
return false;
} else if (!keyValue.equals(other.keyValue))
return false;
if (valueTypeName == null) {
if (other.valueTypeName != null)
return false;
} else if (!valueTypeName.equals(other.valueTypeName))
return false;
return true;
}
}
}