Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.modelcc.language.syntax.ObjectWrapper Maven / Gradle / Ivy
Go to download
ModelCC is a model-based parser generator (a.k.a. compiler compiler) that decouples language specification from language processing, avoiding some of the problems caused by grammar-driven parser generators. ModelCC receives a conceptual model as input, along with constraints that annotate it. It is then able to create a parser for the desired textual language and the generated parser fully automates the instantiation of the language conceptual model. ModelCC also includes a built-in reference resolution mechanism that results in abstract syntax graphs, rather than mere abstract syntax trees.
/*
* ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
*/
package org.modelcc.language.syntax;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.modelcc.io.java.Reflection;
import org.modelcc.language.metamodel.MemberCollection;
import org.modelcc.language.metamodel.CompositeLanguageElement;
import org.modelcc.language.metamodel.LanguageModel;
import org.modelcc.language.metamodel.LanguageElement;
import org.modelcc.language.metamodel.LanguageMember;
/**
* Object Wrapper.
*
* @author Luis Quesada ([email protected] ) & Fernando Berzal ([email protected] )
*/
public class ObjectWrapper implements Serializable
{
/**
* Wrapped object.
*/
private Object o;
/**
* Track used for basic elements.
*/
private Object track;
/**
* The model.
*/
private LanguageModel m;
/**
* Key
*/
private boolean key;
/**
* Hash code
*/
private int hash;
/**
* The map.
*/
private Map mymap;
/**
* Constructor
* @param o the object
* @param m the model.
* @param track used for basic elements.
*/
public ObjectWrapper(Object o, LanguageModel m, Object track)
{
this.o = o;
this.m = m;
this.track = track;
this.hash = track.hashCode();
this.mymap = new HashMap();
this.mymap.put(o, (this));
}
/**
* Constructor
* @param o the object
* @param m the model.
* @param hash the hash code.
* @param mymap my mappings.
*/
protected ObjectWrapper (Object o, LanguageModel m, int hash, Map mymap, boolean key)
{
this.o = o;
this.m = m;
this.hash = hash;
this.key = key;
this.mymap = mymap;
}
/**
* Element members
* @param cme Composite element
* @param key is key?
* @return key members when key is true, all members when key is false
*/
private static List getMembers (CompositeLanguageElement cme, boolean key)
{
if (key)
return cme.getKeyMembers();
else
return cme.getMembers();
}
/**
* Gets a ObjectWrapper
* @param o the object to wrap
* @param m the model
* @param map the object wrappers map.
* @return the object wrapper.
*/
public static ObjectWrapper createObjectWrapper(Object o,LanguageModel m,Map map)
{
return createObjectWrapper(o,m,map,null,false);
}
/**
* Gets a KeyWrapper
* @param o the object to wrap
* @param m the model
* @param map the object wrappers map.
* @return the key wrapper.
*/
public static ObjectWrapper createKeyWrapper (Object o,LanguageModel m,Map map)
{
return createObjectWrapper(o,m,map,null,true);
}
/**
* Gets a ObjectWrapper
* @param o the object to wrap
* @param m the model
* @param map the object wrappers map.
* @param added last added mappings.
* @return the object wrapper.
*/
private static ObjectWrapper createObjectWrapper (
Object o,
LanguageModel m,
Map map,
Map added,
boolean key )
{
int hash = 0;
ObjectWrapper kw = map.get(o);
if (kw != null) {
if (added != null) {
added.putAll(kw.mymap);
}
return kw;
}
LanguageElement e = m.getClassToElement().get(o.getClass());
Map myadded = new HashMap();
if (e instanceof CompositeLanguageElement) {
hash = hashComposite(o, m, map, key, myadded, (CompositeLanguageElement) e);
} else {
hash = o.hashCode();
}
//System.err.println("LE "+e +"OBJ "+o+" "+o.getClass()+" hash="+hash);
ObjectWrapper th = new ObjectWrapper(o, m, hash, myadded, key);
map.put(o,th);
if (added != null)
added.putAll(myadded);
return th;
}
private static int hashComposite(
Object o, LanguageModel m,
Map map, boolean key,
Map myadded, CompositeLanguageElement me)
{
int hash = 0;
try {
for (LanguageMember em: getMembers(me,key) ) {
Field fld = Reflection.findField(me.getElementClass(),em.getID());
fld.setAccessible(true);
Object val = fld.get(o);
if (val == null) {
hash *= 53;
} else {
if (MemberCollection.class.isAssignableFrom(em.getClass())) {
hash = hashCollection(m, map, myadded, (MemberCollection) em, val, hash);
} else {
ObjectWrapper ow = createObjectWrapper(val,m,map,myadded,key);
map.put(val,ow);
hash += val.toString().hashCode(); // vs. ow.hashCode();
hash *= 53;
}
}
}
} catch (Exception ex) {
Logger.getLogger(ObjectWrapper.class.getName()).log(Level.SEVERE, null, ex);
}
return hash;
}
private static int hashCollection(
LanguageModel m, Map map, Map myadded,
MemberCollection mem, Object val, int hash)
{
switch (mem.getCollection()) {
case ARRAY:
Object[] array = (Object[])val;
for (int j = 0;j < array.length;j++) {
ObjectWrapper ow = createObjectWrapper(array[j],m,map,myadded,false);
map.put(array[j],ow);
hash += ow.hashCode();
hash *= 53;
}
break;
case LIST:
List list = (List)val;
for (int j = 0;j < list.size();j++) {
ObjectWrapper ow = createObjectWrapper(list.get(j),m,map,myadded,false);
map.put(list.get(j),ow);
hash += ow.hashCode();
hash *= 53;
}
break;
case SET:
Set dictionary = new HashSet();
Set set = (Set)val;
for (Object on: set) {
ObjectWrapper ow = createObjectWrapper(on,m,map,myadded,false);
map.put(on,ow);
dictionary.add(ow);
}
for (ObjectWrapper w: dictionary) {
hash += w.hashCode();
}
hash *= 53;
break;
}
return hash;
}
// equals
@Override
public boolean equals(Object obj)
{
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ObjectWrapper other = (ObjectWrapper) obj;
if (key != other.key)
return false;
if (hashCode()!=other.hashCode())
return false;
LanguageElement me = m.getClassToElement().get(o.getClass());
if (CompositeLanguageElement.class.isAssignableFrom(me.getClass())) {
return equalsComposite(other);
} else {
return track.equals(other.track);
}
}
private boolean equalsComposite(ObjectWrapper other)
{
CompositeLanguageElement cme = (CompositeLanguageElement) m.getClassToElement().get(o.getClass());
try {
for (LanguageMember em: getMembers(cme,key) ) {
Field fld = Reflection.findField(cme.getElementClass(),em.getID());
fld.setAccessible(true);
Object val = fld.get(o);
Object val2 = fld.get(other.o);
if (val == null && val2 == null) {
} else if (val != null && val2 == null) {
return false;
} else if (val == null && val2 != null) {
return false;
} else if (MemberCollection.class.isAssignableFrom(em.getClass())) {
return equalsCollection(other, (MemberCollection) em, val, val2);
} else {
return val.toString().equals(val2.toString());
}
}
} catch (Exception ex) {
Logger.getLogger(ObjectWrapper.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
private boolean equalsCollection (ObjectWrapper other, MemberCollection mem, Object val, Object val2)
{
Map mymap2 = other.mymap;
switch (mem.getCollection()) {
case ARRAY:
Object[] array = (Object[])val;
Object[] array2 = (Object[])val2;
if (array.length!=array2.length)
return false;
for (int j=0; j set = (Set)val;
Set set2 = (Set)val2;
Set wrappers = new HashSet();
Set wrappers2 = new HashSet();
for (Object obj: set)
wrappers.add(createObjectWrapper(obj, m, mymap));
for (Object obj: set2)
wrappers2.add(createObjectWrapper(obj, m, mymap2));
if (wrappers.size()!=wrappers2.size())
return false;
for (Object obj: wrappers) {
if (!wrappers2.contains(obj))
return false;
}
break;
}
return true;
}
@Override
public final int hashCode()
{
return hash;
}
@Override
public String toString ()
{
return "Wrapper for "+(key?"KEY ":"")+o.getClass()+": "+o+" ("+track+") hash="+hash;
}
}