Search code examples
javaeclipse-emf

How to persist EMF objects to OutputStream?


This how I persist two EMF objects (a static shelf and a dynamic md5) into a zipped binary file:

static void save(Shelf shelf, String file, EClass md5class) throws Exception { 
  EObject md5 = stringToMD5EObject("0x0abc", md5class); 
  Resource resource = createResource(file, md5class.getEPackage(), shelf.eClass().getEPackage());
  resource.getContents().add(md5); 
  resource.getContents().add(shelf); 
  resource.save(options());
}
static Resource createResource(String file, EPackage... packages) {
  ResourceSet resourceSet = new ResourceSetImpl();
  Resource.Factory factory = uri -> new BinaryResourceImpl(uri);
  resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("bin", factory); 
  for (EPackage p : packages) resourceSet.getPackageRegistry().put(p.getNsURI(), p);
  URI fileURI = URI.createFileURI(new File(file).getAbsolutePath());
  return resourceSet.createResource(fileURI);
}
static Map<String, Object> options() {
  return Collections.singletonMap(BinaryResourceImpl.OPTION_ZIP, Boolean.TRUE);
}

The question is how to configure the resource if I'm given an already open OutputStream, that is without no access whatsoever to the filename?


Solution

  • Here's a solution for future reference:

    static {
        options = Collections.singletonMap(BinaryResourceImpl.OPTION_ZIP, true);
    }
    
    public void save(OutputStream outputStream, EObject ... eObject) throws Exception {
        Resource resource = createResource(Arrays.stream(eObject).map(x -> x.eClass().getEPackage()));
        Arrays.stream(eObject).forEach(resource.getContents()::add);
        resource.save(outputStream, options);
    }
    
    public EList<EObject> load(InputStream inputStream, EPackage ... packages) throws Exception {
        Resource resource = createResource(Arrays.stream(packages));
        resource.load(inputStream, options);
        return resource.getContents();
    }
        
    private Resource createResource(Stream<EPackage> packages) {
        ResourceSet resourceSet = new ResourceSetImpl();
        Resource.Factory resourceFactory = __ -> new BinaryResourceImpl();
        resourceSet.getResourceFactoryRegistry().getContentTypeToFactoryMap().put("*", resourceFactory);
        packages.forEach(p -> resourceSet.getPackageRegistry().put(p.getNsURI(), p));
        return resourceSet.createResource(null);
    }