EMF(Eclipse Modeling Framework)是基於結構化模型的代碼生成與運行時框架,支援從 Ecore、UML、XML Schema、註解 Java 接口生成模型代碼,並提供反射 API、變更通知、跨文檔引用、驗證與持久化能力。本文解析核心概念並演示動態模型用法。
EObject(相當 java.lang.Object),提供 eClass()、eGet/eSet、eContainer()、Notifier 變更監聽;適用於開發期模型未知、需解析任意 XML Schema 等場景。
EcoreFactory ef = EcoreFactory.eINSTANCE;
EcorePackage ep = EcorePackage.eINSTANCE;
// Company 類
EClass company = ef.createEClass(); company.setName("Company");
EAttribute cName = ef.createEAttribute(); cName.setName("name"); cName.setEType(ep.getEString());
company.getEStructuralFeatures().add(cName);
// Employee 類
EClass employee = ef.createEClass(); employee.setName("Employee");
EAttribute eName = ef.createEAttribute(); eName.setName("name"); eName.setEType(ep.getEString());
employee.getEStructuralFeatures().add(eName);
// Department 類
EClass dept = ef.createEClass(); dept.setName("Department");
EAttribute dNo = ef.createEAttribute(); dNo.setName("number"); dNo.setEType(ep.getEInt());
dept.getEStructuralFeatures().add(dNo);
// 關聯:Department → Employee* (containment)
EReference deptEmps = ef.createEReference();
deptEmps.setName("employees"); deptEmps.setEType(employee);
deptEmps.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
deptEmps.setContainment(true);
dept.getEStructuralFeatures().add(deptEmps);
// 關聯:Company → Department* (containment)
EReference compDepts = ef.createEReference();
compDepts.setName("department"); compDepts.setEType(dept);
compDepts.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
compDepts.setContainment(true);
company.getEStructuralFeatures().add(compDepts);
// Package
EPackage pkg = ef.createEPackage();
pkg.setName("company"); pkg.setNsPrefix("company"); pkg.setNsURI("https:///com.example.company.ecore");
pkg.getEClassifiers().addAll(Arrays.asList(employee, dept, company));
EFactory factory = pkg.getEFactoryInstance();
EObject companyObj = factory.create(company);
companyObj.eSet(cName, "MyCompany");
EObject emp = factory.create(employee);
emp.eSet(eName, "John");
EObject dep = factory.create(dept);
dep.eSet(dNo, 123);
((List)dep.eGet(deptEmps)).add(emp);
((List)companyObj.eGet(compDepts)).add(dep);
ResourceSet rs = new ResourceSetImpl();
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
Resource res = rs.createResource(URI.createFileURI("c:/temp/company.xmi"));
res.getContents().add(companyObj);
res.save(null); // 生成 XMI 文件
// 反序列化
rs.getPackageRegistry().put(pkg.getNsURI(), pkg);
res.load(null);
XSDEcoreBuilder builder = new XSDEcoreBuilder();
ResourceSet rs = new ResourceSetImpl();
Collection pkgs = builder.generate(URI.createFileURI("c:/temp/ipo.xsd"));
// pkgs 已自動註冊到 rs,可直接載入對應 XML 實例
Map opts = new HashMap();
opts.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
Resource xmlRes = rs.createResource(URI.createFileURI("c:/temp/ipo.xml"));
xmlRes.load(opts);
EMF 2.1+ 還支援無 Schema 的 XML 載入(GenericXMLResourceFactoryImpl),並能自動解析 xsi:schemaLocation。
EMF 將「模型」提升為一等公民,賦予領域建模以代碼生成、運行時反射、持久化與驗證的完整工程化能力。