/** * */ package com.sap.furcas.runtime.parser.textblocks; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.sap.furcas.runtime.common.exceptions.DeferredActionResolvingException; import com.sap.furcas.runtime.common.exceptions.ModelAdapterException; import com.sap.furcas.runtime.common.exceptions.ReferenceSettingException; import com.sap.furcas.runtime.common.interfaces.IBareModelAdapter; import com.sap.furcas.runtime.parser.ANTLR3LocationToken; import com.sap.furcas.runtime.parser.ModelElementCreationException; import com.sap.furcas.runtime.parser.impl.DefaultTextAwareModelAdapter; import com.sap.furcas.runtime.parser.impl.ModelElementProxy; /** * simple implementation using a simple resolution strategy and a IBareModelAdapter else. */ public class TextBlocksAwareModelAdapter extends DefaultTextAwareModelAdapter { private final IBareModelAdapter modelAdapter; /** * @param modelAdapter */ public TextBlocksAwareModelAdapter(IBareModelAdapter modelAdapter) { super(modelAdapter); if (modelAdapter == null) { throw new IllegalArgumentException(); } this.modelAdapter = modelAdapter; } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.ITextAwareModelAdapter#createOrResolveElement(java.util.List, java.util.Map, com.sap.mi.textual.grammar.antlr3.ANTLR3LocationToken, com.sap.mi.textual.grammar.antlr3.ANTLR3LocationToken) */ @Override public Object createOrResolveElement(List<String> typeName, Map<String, List<Object>> attributes, ANTLR3LocationToken firstToken, ANTLR3LocationToken lastToken, boolean resolveOnly, boolean createOnly) throws ModelAdapterException, ModelElementCreationException { // ModelElementProxy proxy = (ModelElementProxy) proxyObject; // If referenceOnly, merely resolve it, don't create it if (resolveOnly) { try { Collection<Object> resultSet = modelAdapter.queryElement(typeName, attributes); if (resultSet != null && resultSet.size()>=1) { if (resultSet.size()==1) { return resultSet.iterator().next(); } else { throw new ModelElementCreationException("Reference " + typeName + " with attributes " + attributes + " is ambiguous."); } } else { throw new ModelElementCreationException("Reference "+typeName + " with attributes " + attributes +" could not be resolved."); } } catch (ModelAdapterException e) { // TODO move this to getModelAdapter() and delete ModelElement on errors (?) throw new ModelElementCreationException("BUG: Exception resolving type " + typeName + " with attributes " + attributes + " : " + e.getMessage(), e); } } else { // create new object and set its attributes, this is the default behavior Object createdObject = null; //TODO:This is only a temporary solution //Re-Use ModelElement if there is one in the "old textblock with the same type" // AbstractToken tok = input.getTokenModelElementForParserToken(firstToken); // if(tok != null && tok.getParentBlock() != null) { // //check the reference version // TextBlock referenceVersionTB = TbVersionUtil.getOtherVersion(tok.getParentBlock(), VersionEnum.REFERENCE); // if(referenceVersionTB != null) { // for (RefObject ro : referenceVersionTB.getCorrespondingModelElements()) { // //if type equals given name re-use that element // if(((MofClass)ro.refMetaObject()).getQualifiedName().equals(typeName)){ // if(createdObject != null) { // ParsingTextblocksActivator.logWarning("Multiple elements could be re-used, during update phase, we're using the first one:" + ro); // } // createdObject = ro; // } // } // } // } //nothing found, so create a new element if(true /*createdObject == null*/) { createdObject = modelAdapter.createElement(typeName); } if(createdObject == null) { return null; } Set<String> features = attributes.keySet(); for (String prop : features) { List<Object> valueList = attributes.get(prop); for (Iterator<Object> iterator = valueList.iterator(); iterator.hasNext();) { // TODO: for single value properties, cause error when trying to set more than once? Object value = iterator.next(); if (value instanceof ModelElementProxy) { ModelElementProxy valueProxy = (ModelElementProxy) value; value = valueProxy.getRealObject(); //TODO this should be checked after delayed references have been resolved as //due to semantically predicated templates elements may be resolved later on // if (value == null) // throw new RuntimeException("Bug: proxy value for '" +prop +"' of type "+valueProxy.getType()+" had not been resolved."); } try { set(createdObject, prop, value); } catch (ModelAdapterException e) { // TODO move this to getModelAdapter() and delete ModelElement on errors (?) throw new ModelElementCreationException("Exception setting feature " + prop + " for object " + createdObject + " to " + value + ": " + e.getMessage(), e); } } } return createdObject; } } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#createEnumLiteral(java.util.List, java.lang.String) */ @Override public Object createEnumLiteral(List<String> enumName, String name) throws ModelAdapterException { return modelAdapter.createEnumLiteral(enumName, name); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#hasDeferredActions() */ @Override public boolean hasDeferredActions() { return modelAdapter.hasDeferredActions(); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#performAllDeferredActions() */ @Override public Map<Object, Object> performAllDeferredActions() throws DeferredActionResolvingException { return modelAdapter.performAllDeferredActions(); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#set(java.lang.Object, java.lang.String, java.lang.Object) */ @Override public void set(Object modelElement, String prop, Object value) throws ModelAdapterException { modelAdapter.set(modelElement, prop, value); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#set(java.lang.Object, java.lang.String, java.lang.Object, int) */ @Override public void set(Object modelElement, String prop, Object value, int index) throws ModelAdapterException { modelAdapter.set(modelElement, prop, value, index); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#setMQLReference(java.lang.Object, java.lang.String, java.lang.Object, java.lang.String, java.lang.Object) */ @Override public Object setReferenceWithOCLQuery(Object modelElement, String propertyName, Object keyValue, String oclQuery, Object contextElement, Object currentForeachElement) throws ModelAdapterException, ReferenceSettingException { return modelAdapter.setReferenceWithOCLQuery(modelElement, propertyName, keyValue, oclQuery, contextElement, currentForeachElement); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#setReference(java.lang.Object, java.lang.String, java.util.List, java.lang.String, java.lang.Object) */ @Override public Object setReferenceWithLookup(Object sourceModelElement, String referencePropertyName, List<String> targetType, String targetKeyName, Object targetKeyValue) throws ModelAdapterException, ReferenceSettingException { return modelAdapter.setReferenceWithLookup(sourceModelElement, referencePropertyName, targetType, targetKeyName, targetKeyValue); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelAdapter#setWithinContextObject(java.lang.Object, java.lang.String, java.util.List, java.lang.String, java.lang.Object, java.lang.Object) */ @Override public Object setReferenceWithContextLookup(Object modelElement, String propertyName, List<String> valueTypeName, String keyName, Object keyValue, Object contextObject) throws ModelAdapterException, ReferenceSettingException { return modelAdapter.setReferenceWithContextLookup(modelElement, propertyName, valueTypeName, keyName, keyValue, contextObject); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelElementInvestigator#get(java.lang.Object, java.lang.String) */ @Override public Object get(Object modelElement, String propertyName) throws ModelAdapterException { return modelAdapter.get(modelElement, propertyName); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelElementInvestigator#getMetaType(java.util.List) */ @Override public Object getMetaType(List<String> typeName) throws ModelAdapterException { return modelAdapter.getMetaType(typeName); } /* (non-Javadoc) * @see com.sap.mi.textual.grammar.IModelElementInvestigator#instanceOf(java.lang.Object, java.lang.Object) */ @Override public boolean instanceOf(Object instance, Object metaType) throws ModelAdapterException { return modelAdapter.instanceOf(instance, metaType); } public void setTextBlocksStream(ITextBlocksTokenStream input) { // no-op; token stream not used by this class } }