我已經創建的類SimpleModelSerializer
能夠輕鬆讀寫EMF模型的紀念並從不同的格式。使用readMemento
和writeMemento
方法處理IMemento
。該類可以很容易地擴展到其他格式。
它是很最小,只能處理簡單的模型。以下是一些限制條件:
- 非包含引用不處理。
- 不處理特徵值的分型輸入。
- EPackage必須位於全局包註冊表中。
- 它可能只是在很多有效的模型上崩潰。
- 未執行驗證。
- 對擴展元數據的支持非常少。
- 很多其他的事情...
儘管它是用於保存簡單的小事情,例如查看配置非常有用。
這是代碼:
/**
* Contains code for reading and writing EMF models to and from other formats.
*/
public class SimpleModelSerializer {
public interface ModelReader {
List<String> getMultiAttribute(String name);
String getAttribute(String name);
String getDefaultAttribute(String name);
List<ModelReader> getChildren(String name);
}
public interface ModelWriter {
void setAttribute(String name, String value);
void setDefaultAttribute(String name, String value);
void setMultiAttribute(String name, List<String> values);
ModelWriter createChild(String name);
}
@SuppressWarnings("unchecked")
private static void setFeature(EObject o, EStructuralFeature feature, Object value) {
if (feature.isMany()) {
((List<Object>) o.eGet(feature)).add(value);
} else {
o.eSet(feature, value);
}
}
@SuppressWarnings("unchecked")
private static List<?> getFeature(EObject o, EStructuralFeature feature) {
if (feature.isMany()) {
return (List<Object>) o.eGet(feature);
} else {
return Collections.singletonList(o.eGet(feature));
}
}
public static <T extends EObject> T readMemento(IMemento mem, EClass cls, Class<T> instCls, ExtendedMetaData meta) {
return readCastedObject(cls, instCls, new MementoReader(mem), meta);
}
public static <T extends EObject> List<T> readMementos(IMemento mem, String name, EClass cls, Class<T> instCls, ExtendedMetaData meta) {
return readObjects(cls, instCls, new MementoReader(mem), name, meta);
}
public static <T extends EObject> List<T> readObjects(EClass cls, Class<T> instCls, ModelReader reader, String name, ExtendedMetaData meta) {
List<T> result = new ArrayList<>();
for (ModelReader childReader : reader.getChildren(name)) {
result.add(instCls.cast(readObject(cls, childReader, meta)));
}
return result;
}
public static <T extends EObject> T readCastedObject(EClass cls, Class<T> instCls, ModelReader reader, ExtendedMetaData meta) {
return instCls.cast(readObject(cls, reader, meta));
}
public static EObject readObject(EClass cls, ModelReader reader, ExtendedMetaData meta) {
if (meta == null) meta = ExtendedMetaData.INSTANCE;
EObject obj = EcoreUtil.create(cls);
for (EStructuralFeature feature : cls.getEAllStructuralFeatures()) {
if (feature.isTransient()) continue;
String name = meta.getName(feature);
List<Object> values = new ArrayList<>();
if (feature instanceof EAttribute) {
EAttribute attr = (EAttribute) feature;
List<String> attrs;
if (attr.isMany()) attrs = reader.getMultiAttribute(name);
else if (name.equals(":0")) attrs = singletonList(reader.getDefaultAttribute(name));
else attrs = singletonList(reader.getAttribute(name));
for (String attrText : attrs) {
if (attrText != null) {
values.add(EcoreUtil.createFromString(attr.getEAttributeType(), attrText));
}
}
} else if (feature instanceof EReference) {
EReference ref = (EReference) feature;
for (ModelReader childReader : reader.getChildren(name)) {
values.add(readObject(ref.getEReferenceType(), childReader, meta));
}
}
for (Object value : values) {
setFeature(obj, feature, value);
}
}
return obj;
}
public static void writeMemento(IMemento mem, EObject o, ExtendedMetaData meta) {
writeObject(new MementoWriter(mem), o, meta);
}
public static void writeMementos(IMemento mem, String childName, Collection<? extends EObject> os, ExtendedMetaData meta) {
MementoWriter writer = new MementoWriter(mem);
for (EObject o : os) {
writeObject(writer.createChild(childName), o, meta);
}
}
public static void writeObject(ModelWriter writer, EObject obj, ExtendedMetaData meta) {
if (meta == null) meta = ExtendedMetaData.INSTANCE;
EClass cls = obj.eClass();
for (EStructuralFeature feature : cls.getEAllStructuralFeatures()) {
if (feature.isTransient()) continue;
String name = meta.getName(feature);
if (feature instanceof EAttribute) {
List<String> outputValues = new ArrayList<>();
for (Object e : getFeature(obj, feature)) {
if (!Objects.equals(e, feature.getDefaultValue())) {
String textValue = EcoreUtil.convertToString((EDataType) feature.getEType(), e);
outputValues.add(textValue);
}
}
if (feature.isMany()) {
writer.setMultiAttribute(name, outputValues);
} else if (!outputValues.isEmpty()) {
if (name.equals(":0")) {
writer.setDefaultAttribute(name, outputValues.get(0));
} else {
writer.setAttribute(name, outputValues.get(0));
}
}
} else if (feature instanceof EReference) {
for (Object value : getFeature(obj, feature)) {
if (value != null) {
writeObject(writer.createChild(name), (EObject) value, meta);
}
}
}
}
}
private static class MementoReader implements ModelReader {
private final IMemento memento;
public MementoReader(IMemento memento) {
this.memento = memento;
}
@Override
public String getDefaultAttribute(String name) {
return memento.getTextData();
}
@Override
public String getAttribute(String name) {
return memento.getString(name);
}
@Override
public List<String> getMultiAttribute(String name) {
IMemento[] childMems = memento.getChildren(name);
List<String> attrs = new ArrayList<>(childMems.length);
for (IMemento mem : childMems) {
attrs.add(mem.getTextData());
}
return attrs;
}
@Override
public List<ModelReader> getChildren(String name) {
return Arrays.stream(memento.getChildren(name)).map(MementoReader::new).collect(toList());
}
}
private static class MementoWriter implements ModelWriter {
private final IMemento memento;
public MementoWriter(IMemento memento) {
this.memento = memento;
}
@Override
public void setAttribute(String name, String value) {
memento.putString(name, value);
}
@Override
public void setMultiAttribute(String name, List<String> values) {
for (String value : values) {
memento.createChild(name).putTextData(value);
}
}
@Override
public ModelWriter createChild(String name) {
return new MementoWriter(memento.createChild(name));
}
@Override
public void setDefaultAttribute(String name, String value) {
memento.putTextData(value);
}
}
}
你需要什麼樣的信息存儲? IMemento僅適用於相對較少量的字符串。 –
我想存儲整個模型信息,任何建議... – Arun