All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.uniks.networkparser.xml.EMFTokener Maven / Gradle / Ivy

package de.uniks.networkparser.xml;

/*
NetworkParser
The MIT License
Copyright (c) 2010-2016 Stefan Lindel https://github.com/fujaba/NetworkParser/

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import java.util.ArrayList;
import java.util.Collection;

import de.uniks.networkparser.EntityUtil;
import de.uniks.networkparser.IdMap;
import de.uniks.networkparser.MapEntity;
import de.uniks.networkparser.buffer.CharacterBuffer;
import de.uniks.networkparser.buffer.Tokener;
import de.uniks.networkparser.graph.Association;
import de.uniks.networkparser.graph.AssociationTypes;
import de.uniks.networkparser.graph.Attribute;
import de.uniks.networkparser.graph.Cardinality;
import de.uniks.networkparser.graph.Clazz;
import de.uniks.networkparser.graph.ClazzType;
import de.uniks.networkparser.graph.DataType;
import de.uniks.networkparser.graph.GraphList;
import de.uniks.networkparser.graph.GraphModel;
import de.uniks.networkparser.graph.Literal;
import de.uniks.networkparser.graph.util.AssociationSet;
import de.uniks.networkparser.interfaces.Entity;
import de.uniks.networkparser.interfaces.EntityList;
import de.uniks.networkparser.interfaces.SendableEntityCreator;
import de.uniks.networkparser.interfaces.SendableEntityCreatorIndexId;
import de.uniks.networkparser.list.SimpleKeyValueList;
import de.uniks.networkparser.list.SimpleList;
import de.uniks.networkparser.list.SimpleSet;

public class EMFTokener extends Tokener{
	public static final String ECORE = "ecore";
	public static final String EPACKAGE = "ecore:EPackage";
	public static final String EAttribute = "eAttributes";
	public static final String ECLASS = "eClassifiers";
	public static final String EREFERENCE = "eReferences";
	public static final String ETYPE = "eType";
	public static final String EDATATYPE ="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//";
	public static final String TYPE_ECLASS = "ecore:EClass";
	public static final String TYPE_EAttribute = "ecore:EAttribute";
	public static final String TYPE_EReferences = "ecore:EReference";
	public static final String TYPE_ESUPERTYPE = "eSuperTypes";
	public static final String TYPE_EEnum = "ecore:EEnum";
	public static final String EOpposite = "eOpposite";
	public static final String ATTRIBUTE_URL = "http://www.eclipse.org/emf/2002/Ecore#//";
	public static final String UPPERBOUND = "upperBound";
	public static final String XSI_TYPE = "xsi:type";
	public static final String XMI_ID = "xmi:id";
	public static final String NAME = "name";

	/**
	 * Skip the Current Entity to >.
	 */
	protected void skipEntity() {
		skipTo('>', false);
		// Skip >
		nextClean(false);
	}

	public String skipHeader() {
		boolean skip=false;
		CharacterBuffer tag;
		do {
			tag = this.getString(2);
			if(tag == null) {
				break;
			}
			if(tag.equals(") {
				for (Object childValue : (Collection) propertyValue) {
					XMLEntity child = new XMLEntity();

					parent.withChild(child);

					child.setType(propertyName);

					String typetag = childValue.getClass().getName().replaceAll("\\.", ":");

					child.put(XSI_TYPE, typetag);

					encodeChildren(childValue, child, map);
				}
			} else {
				XMLEntity child = new XMLEntity();

				parent.withChild(child);

				child.setType(propertyName);

				String typetag = propertyValue.getClass().getName().replaceAll("\\.", ":");

				child.put(XSI_TYPE, typetag);

				encodeChildren(propertyValue, child, map);
			}
		}
	}

	/**
	 * Decode a Element from EMF
	 *
	 * @param map decoding runtime values
	 * @param root The Root Element of Returnvalue
	 * @return decoded Object
	 */
	public Object decode(MapEntity map, Object root) {
		skipHeader();
		XMLEntity xmlEntity = new XMLEntity();
		xmlEntity.withValue(this.buffer);
		if(EPACKAGE.equals(xmlEntity.getTag())) {
			if(root instanceof GraphList) {
				return decoding(xmlEntity, (GraphList)root);
			}
			return decoding(xmlEntity, null);
		}
		// build root entity
		String tag = xmlEntity.getTag();
		String[] splitTag = tag.split("\\:");
		if(splitTag.length<2) {
			return null;
		}
		if(ECORE.equalsIgnoreCase(splitTag[0]) || root instanceof GraphModel) {
			GraphModel model;
			if(root == null || root instanceof GraphModel == false) {
				model = new GraphList();
			} else {
				model = (GraphModel) root;
			}
			return decodingClassModel(xmlEntity, model);
		}
		Object rootObject = null;
		SendableEntityCreator rootFactory;
		if(root == null) {
			String className = splitTag[1];
			rootFactory = getCreator(className, false, null);
			if (rootFactory != null) {
				rootObject = rootFactory.getSendableInstance(false);
			} else {
				// just use an ArrayList
				rootObject = new ArrayList();
			}
		}else {
			rootObject = root;
			rootFactory = getCreatorClass(root);
		}
		
		parsing(xmlEntity, rootFactory, rootObject, null);

		for(int i =0;i< notKey.size();i++) {
			XMLEntity itemXmlEntity = notKey.get(i);
			SimpleKeyValueList myRefs = notKey.getValueByIndex(i);
			String id = itemXmlEntity.getString(XMI_ID);
			Object item = getObject(id);
			
			SendableEntityCreator creator = getCreator(item.getClass().getName(), false, null);
			for(int r = 0; r  refs = getRef(value, itemXmlEntity, creator);
				for(String ref : refs) {
					Object object = getObject(ref);
					 if (object != null) {
						 creator.setValue(item, prop, object, "");
					 }
				}
			}
		}
		return rootObject;
	}

	private Object decodingClassModel(XMLEntity values, GraphModel model) {
		SimpleKeyValueList items = new SimpleKeyValueList();
		for(int c=0;c refs = getRef(key, child, null);
						for (String ref : refs)
                  {
                     Association back = new Association(items.get(ref));
                     found.with(back);
                  }
					}

					if(value.indexOf("/", 1) > 0) {
						// To Many
						found.with(Cardinality.MANY);
					}
				}
			}
		}
		//TODO CREATING METHOD BODY
		return model;
	}

	private SimpleList getRef(String value, XMLEntity xmlEntity, SendableEntityCreator rootFactory) {
		SimpleList result = new SimpleList();
	   if (value.startsWith("//@")) {
			for (String ref : value.split(" ")) {
				String myRef = "_" + ref.substring(3);
				if (myRef.indexOf('.') > 0) {
					myRef = myRef.replaceAll("\\.|/@", "");
				} else {
					myRef = "_" + myRef.subSequence(0, 1) + "0";
				}
				result.add(myRef);
			}
		} else if (value.startsWith("/")) {
			// maybe multiple separated by blanks
			String tagChar = xmlEntity.getTag().substring(0, 1);
			for (String ref : value.split(" ")) {
				ref = "_" + tagChar + ref.substring(1);
				if (getObject(ref) != null) {
					result.add(ref);
				}
			}
		} else if (value.indexOf('_') > 0) {
			// maybe multiple separated by blanks
			for (String ref : value.split(" ")) {
				if (getObject(ref) != null) {
				   result.add(ref);
				}
			}
		} else if (value.startsWith("$")) {
			for (String ref : value.split(" ")) {
				String myRef = "_" + ref.substring(1);
				if (rootFactory != null && getObject(myRef) != null) {
					result.add(myRef);
				}
			}
		}
		return result;
	}

	SimpleKeyValueList runningNumbers = new SimpleKeyValueList();
	SimpleKeyValueList> notKey = new SimpleKeyValueList>();
	
	@SuppressWarnings("unchecked")
	private void parsing(XMLEntity xmlEntity, SendableEntityCreator entityFactory, Object entityObject, String rootId) {
		String id = (String) xmlEntity.getValue(XMI_ID);
		Collection rootCollection = null;
		if (id == null) {
			String tag = xmlEntity.getTag();
			if (rootId != null) {
				rootId += tag;
				Integer num = runningNumbers.get(rootId);
				if (num == null) {
					num = 0;
				} else {
					num++;
				}
				runningNumbers.put(rootId, num);
				rootId += num;
			} else {
				rootId = "$";
			}
			if (xmlEntity.has("href")) {
				// might point to another xml file already loaded
				// might point to another xml file already loaded
				String refString = xmlEntity.getString("href");
				String[] split = refString.split("#//");

				if (split.length == 2) {
					String objectId = split[1];
					objectId = objectId.replace('@', '_');
					objectId = objectId.replace(".", "");
					Object object = getObject(objectId);
					
					if (object != null) {
						// yes we know it
						if (entityObject instanceof Collection) {
							rootCollection = (Collection) entityObject;
						}
						if (rootCollection != null) {
							rootCollection.add(object);
						} else {
							entityFactory.setValue(entityObject, tag, object, "");
						}
						return;
					} else {
						
					}
				}
				
				if (split.length == 2) {
					String objectId = split[1];
					objectId = objectId.replace('@', '$');
					objectId = objectId.replace(".", "");
					xmlEntity.put(XMI_ID, objectId);
				}
			}
			if(entityFactory instanceof SendableEntityCreatorIndexId) {
				// Get Creator
				String temp = xmlEntity.getString(IdMap.ID);
				if(temp != null) {
					rootId = temp;
				}
			}
		}

		if (rootId.startsWith("$")) {
			rootId = "_" + rootId.substring(1);
		}

		this.map.put(rootId, entityObject, true);
		if(xmlEntity.has(XMI_ID) == false) {
			xmlEntity.put(XMI_ID, rootId);
		}
		
		// set plain attributes
		if(entityFactory != null) {
			for (int i = 0; i < xmlEntity.size(); i++) {
				String key = xmlEntity.getKeyByIndex(i);
				String value = xmlEntity.getString(key);
				if (value == null) {
					continue;
				}
				value = value.trim();
				if ("".equals(value) || XMI_ID.equals(key)) {
					continue;
				}
				SimpleList myRefs = getRef(value, xmlEntity, entityFactory);
				if (myRefs.size() == 0) {
				   entityFactory.setValue(entityObject, key, value, "");
				}
				for (String myRef : myRefs) {
				   Object object = getObject(myRef);
				   if (object != null) {
					   entityFactory.setValue(entityObject, key, object, "");
				   } else {
					   // Link not know
					   SimpleKeyValueList list = notKey.get(xmlEntity);
					   if(list == null) {
						   list = new SimpleKeyValueList();
						   notKey.put(xmlEntity, list);
					   }
					   list.put(key, value);
					   break;
				   }
				}
			}
		}
		String tag;
		int pos;
		
		for(int i=0;i) entityObject;
				// take the type name from the tag
				pos = tag.indexOf(":");
				if(pos > 0) {
					typeName = tag.substring(pos+1);
				}else{
					typeName = tag;
				}
			}

			if (kid.has(XSI_TYPE)) {
				typeName = kid.getString(XSI_TYPE);
				typeName = typeName.replaceAll(":", ".");
			}
			if(typeName == null) {
				Object value = entityFactory.getValue(entityObject, tag);
				if(value != null) {
					if(value instanceof SimpleSet) {
						SimpleSet set = (SimpleSet) value;
						typeName = set.getTypClass().getName();
					}else {
						typeName = value.getClass().getName();
					}
				} else {
					typeName = tag;
				}
			}
			
			if (typeName != null) {
				SendableEntityCreator kidFactory = getCreator(typeName, false, null);
				if (kidFactory == null && typeName.endsWith("s")) {
					kidFactory = getCreator(typeName.substring(0, typeName.length() - 1), false, null);
				}
				if(kidFactory == null) {
					continue;
				}
				Object kidObject = kidFactory.getSendableInstance(false);

				parsing(kid, kidFactory, kidObject, rootId);
				if (rootCollection != null) {
					rootCollection.add(kidObject);
				} else {
					entityFactory.setValue(entityObject, tag, kidObject, "");
				}
			}
		}
	}

	public GraphList decoding(String content) {
		return decoding(new XMLEntity().withValue(content), null);
	}
	public GraphList decoding(Tokener content) {
		return decoding(new XMLEntity().withValue(this), null);
	}

	private GraphList decoding(XMLEntity ecore, GraphList model) {
		if(model == null) {
			model = new GraphList();
		}
		SimpleList superClazzes = new SimpleList();

		// add classes
		SimpleKeyValueList parentList=new SimpleKeyValueList();
		for(int i=0;i items = new SimpleKeyValueList();
		for(int i=0;i=0) {
				tgtClassName = tgtClassName.substring(tgtClassName.indexOf("#") + 3);
			}
			String tgtRoleName = eref.getString(EMFTokener.NAME);

			Association tgtAssoc = getOrCreate(items, model, tgtClassName, tgtRoleName);

			if (eref.has(UPPERBOUND)) {
				Object upperValue = eref.getValue(UPPERBOUND);
				if (upperValue instanceof Number) {
					if (((Number) upperValue).intValue() != 1) {
						tgtAssoc.with(Cardinality.MANY);
					}
				}
			}

			String srcRoleName = null;
			XMLEntity parent = (XMLEntity) parentList.getValueByIndex(i);
			String srcClassName = parent.getString(EMFTokener.NAME);
			if (!eref.has(EOpposite)) {
//				srcRoleName = tgtRoleName+"_back";
			}else{
				srcRoleName = EntityUtil.getId(eref.getString(EOpposite));
			}
			Association srcAssoc = getOrCreate(items, model, srcClassName, srcRoleName);
			// Create as Unidirection
			tgtAssoc.with(srcAssoc);
			srcAssoc.with(AssociationTypes.EDGE);
			
			tgtAssoc.getClazz().with(tgtAssoc);
			srcAssoc.getClazz().with(srcAssoc);
			
			model.with(tgtAssoc);
		}
		return model;
	}

	private Association getOrCreate(SimpleKeyValueList items, GraphList model, String className, String roleName) {
		if(className != null ) {
			int pos = className.indexOf("/");
			if(pos>0) {
				className = className.substring(pos+1);
			}
		}
		roleName = EntityUtil.toValidJavaId(roleName);
		String assocName = className+":"+roleName;
		Association edge = (Association) items.getValue(assocName);
		if(edge == null) {
			Clazz clazz = model.getNode(className);
			if(clazz == null) {
				// Create it
				clazz = model.createClazz(className);
			}
			if(clazz != null) {
				edge = new Association(clazz).with(Cardinality.ONE).with(roleName);
				clazz.with(edge);
				if(roleName != null) {
					items.add(assocName, edge);
				}
			}
		}
		return edge;
	}
}