├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── org │ └── emfjson │ └── mongo │ ├── MongoHandler.java │ ├── bson │ └── codecs │ │ └── JsonWriter.java │ └── streams │ ├── MongoInputStream.java │ └── MongoOutputStream.java └── test ├── java └── org │ └── emfjson │ └── mongo │ ├── TestSuite.java │ ├── bench │ └── Benchmark.java │ └── tests │ ├── DynamicTest.java │ ├── LoadReferenceTest.java │ ├── MongoHandlerLoadTest.java │ ├── MongoHandlerSaveAndLoadTest.java │ ├── MongoHandlerSaveTest.java │ └── UseIdTest.java └── resources └── model.xcore /.gitignore: -------------------------------------------------------------------------------- 1 | java-gen -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | services: 3 | - mongodb 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MongoDB Adapter for Eclipse Modeling Framework (EMF) 2 | 3 | [![Build Status](https://secure.travis-ci.org/emfjson/emfjson-mongo.png)](http://travis-ci.org/emfjson/emfjson-mongo) 4 | 5 | An easy to use adapter that works on top of the EMF Resource API to store and retrieve EMF Models on MongoDB. 6 | 7 | ### Download 8 | 9 | Add the following dependency to your pom file. 10 | 11 | ```xml 12 | 13 | org.emfjson 14 | emfjson-mongo 15 | 0.3.0 16 | 17 | ``` 18 | 19 | You can also find the jars in [maven central](http://search.maven.org/#search|ga|1|emfjson-mongo) 20 | 21 | ### Usage 22 | 23 | Setup the ResourceSet: 24 | 25 | ```java 26 | ResourceSet resourceSet = new ResourceSetImpl(); 27 | 28 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 29 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 30 | resourceSet.getURIConverter().getURIHandlers().add(0, new MongoHandler()); 31 | ``` 32 | 33 | Create a Resource with a URI pointing to MongoDB. The URI must contains 3 segments identifying the database, the collection and the document id. 34 | 35 | The URI should have the form ```mongodb://{host}[:{port}]/{db}/{collection}/{id}``` 36 | 37 | ```java 38 | URI uri = URI.createURI("mongodb://localhost:27017/emfjson-test/models/model1"); 39 | Resource resource = resourceSet.createResource(uri); 40 | ``` 41 | 42 | Alternatively, you can use a URI mapping: 43 | 44 | ```java 45 | resourceSet.getURIConverter().getURIMap().put( 46 | URI.createURI("http://resources/"), 47 | URI.createURI("mongodb://localhost:27017/emfjson-test/models/")); 48 | 49 | Resource resource = resourceSet.createResource(URI.createURI("http://resources/model1")); 50 | ``` 51 | 52 | Override the name of the field to avoid problem with the reserved name of Bson. And set the uri handler, to avoid problem with external resources. 53 | 54 | ```java 55 | HashMap DEFAULT_OPTIONS = new HashMap(); 56 | DEFAULT_OPTIONS.put(EMFJs.OPTION_URI_HANDLER, new IdentityURIHandler()); 57 | DEFAULT_OPTIONS.put(EMFJs.OPTION_REF_FIELD, "_ref"); 58 | resourceSet.getLoadOptions().putAll(DEFAULT_OPTIONS); 59 | ``` 60 | 61 | Saving documents 62 | 63 | ```java 64 | EPackage p = EcoreFactory.eINSTANCE.createEPackage(); 65 | p.setName("p"); 66 | 67 | EClass c = EcoreFactory.eINSTANCE.createEClass(); 68 | c.setName("A"); 69 | 70 | p.getEClassifiers().add(c); 71 | 72 | resource.getContents().add(p); 73 | resource.save(null); 74 | ``` 75 | 76 | Loading document 77 | 78 | ```java 79 | resource.load(null); 80 | ``` 81 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | org.emfjson 5 | emfjson-mongo 6 | 0.4.0-SNAPSHOT 7 | jar 8 | 9 | 10 | org.sonatype.oss 11 | oss-parent 12 | 7 13 | 14 | 15 | 16 | 17 | EPL 18 | www.eclipse.org/legal/epl-v10.html 19 | 20 | 21 | 22 | 23 | GitHub Issues 24 | https://github.com/ghillairet/mongo-emfjson/issues 25 | 26 | 27 | 28 | 29 | ghillairet 30 | G. Hillairet 31 | g.hillairet@gmail.com 32 | 33 | 34 | 35 | 36 | scm:git:git@github.com:ghillairet/mongo-emfjson.git 37 | scm:git:git@github.com:ghillairet/mongo-emfjson.git 38 | scm:git:git@github.com:ghillairet/mongo-emfjson.git 39 | 40 | 41 | 42 | 1.7 43 | 1.7 44 | true 45 | UTF-8 46 | 2.11.1-v20150805-0538 47 | 2.11.0-v20150805-0538 48 | 2.11.0-v20150806-0404 49 | 2.9.1 50 | 1.2.0 51 | 1.3.1 52 | 1.1.100 53 | 54 | 55 | 56 | 57 | org.emfjson 58 | emfjson-jackson 59 | 1.0.0-rc.1 60 | 61 | 62 | 63 | org.mongodb 64 | mongodb-driver 65 | 3.2.2 66 | 67 | 68 | 69 | org.eclipse.emf 70 | org.eclipse.emf.ecore.xcore.lib 71 | ${ecore-xcore-lib-version} 72 | provided 73 | 74 | 75 | 76 | junit 77 | junit 78 | 4.12 79 | test 80 | 81 | 82 | 83 | org.assertj 84 | assertj-core 85 | 2.2.0 86 | test 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.apache.maven.plugins 94 | maven-compiler-plugin 95 | 3.1 96 | 97 | 1.7 98 | 1.7 99 | 100 | 101 | 102 | 103 | org.apache.maven.plugins 104 | maven-javadoc-plugin 105 | 2.10 106 | 107 | -Xdoclint:none 108 | false 109 | 110 | 111 | 112 | 113 | org.codehaus.mojo 114 | build-helper-maven-plugin 115 | 1.9.1 116 | 117 | 118 | add-test-source 119 | generate-test-sources 120 | 121 | add-test-source 122 | 123 | 124 | 125 | ${basedir}/src/test/java-gen 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | maven-clean-plugin 134 | 2.6.1 135 | 136 | 137 | 138 | src/test/java-gen 139 | 140 | 141 | 142 | 143 | 144 | 145 | org.apache.maven.plugins 146 | maven-release-plugin 147 | 2.5.2 148 | 149 | @{project.version} 150 | 151 | 152 | 153 | 154 | org.eclipse.xtext 155 | xtext-maven-plugin 156 | ${xtext-version} 157 | 158 | 159 | generate-test-sources 160 | 161 | generate 162 | 163 | 164 | 165 | 166 | 167 | 168 | org.eclipse.xtext.ecore.EcoreSupport 169 | 170 | 171 | org.eclipse.emf.codegen.ecore.xtext.GenModelSupport 172 | 173 | 174 | org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup 175 | 176 | 177 | ${project.basedir}/src/test/java-gen 178 | 179 | 180 | 181 | 182 | 183 | ${basedir}/src/test/resources 184 | 185 | 186 | 187 | 188 | org.eclipse.text 189 | org.eclipse.text 190 | 3.5.101 191 | 192 | 193 | org.eclipse.core 194 | org.eclipse.core.resources 195 | 3.7.100 196 | 197 | 198 | org.eclipse.xtext 199 | org.eclipse.xtext.ecore 200 | ${xtext-version} 201 | 202 | 203 | org.eclipse.emf 204 | org.eclipse.emf.codegen.ecore.xtext 205 | ${ecore-xtext-version} 206 | 207 | 208 | org.eclipse.emf 209 | org.eclipse.emf.common 210 | ${emf-common-version} 211 | 212 | 213 | org.eclipse.emf 214 | org.eclipse.emf.ecore 215 | ${emf-version} 216 | 217 | 218 | org.eclipse.emf 219 | org.eclipse.emf.ecore.xmi 220 | ${emf-version} 221 | 222 | 223 | org.eclipse.emf 224 | org.eclipse.emf.codegen 225 | ${emf-codegen-version} 226 | 227 | 228 | org.eclipse.emf 229 | org.eclipse.emf.codegen.ecore 230 | ${emf-codegen-version} 231 | 232 | 233 | org.eclipse.emf 234 | org.eclipse.emf.ecore.xcore 235 | ${ecore-xcore-version} 236 | 237 | 238 | org.eclipse.emf 239 | org.eclipse.emf.ecore.xcore.lib 240 | ${ecore-xcore-lib-version} 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /src/main/java/org/emfjson/mongo/MongoHandler.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo; 2 | 3 | import com.mongodb.MongoClient; 4 | import com.mongodb.client.MongoCollection; 5 | import org.bson.Document; 6 | import org.eclipse.emf.common.util.URI; 7 | import org.eclipse.emf.ecore.resource.impl.URIHandlerImpl; 8 | import org.emfjson.mongo.streams.MongoInputStream; 9 | import org.emfjson.mongo.streams.MongoOutputStream; 10 | 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.io.OutputStream; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | public class MongoHandler extends URIHandlerImpl { 18 | 19 | public static final String ID_FIELD = "_id"; 20 | public static final String TYPE_FIELD = "_type"; 21 | public static final String CONTENTS_FIELD = "contents"; 22 | 23 | private final MongoClient client; 24 | 25 | public MongoHandler(MongoClient client) { 26 | this.client = client; 27 | } 28 | 29 | @Override 30 | public boolean canHandle(URI uri) { 31 | return uri.scheme().equals("mongodb"); 32 | } 33 | 34 | @Override 35 | public InputStream createInputStream(URI uri, Map options) throws IOException { 36 | return new MongoInputStream(this, uri, options); 37 | } 38 | 39 | @Override 40 | public OutputStream createOutputStream(URI uri, Map options) throws IOException { 41 | return new MongoOutputStream(this, uri, options); 42 | } 43 | 44 | @Override 45 | public void delete(URI uri, Map options) throws IOException { 46 | final MongoCollection collection = getCollection(uri); 47 | final Map filter = new HashMap<>(); 48 | filter.put(ID_FIELD, uri.segment(2)); 49 | filter.put(TYPE_FIELD, "resource"); 50 | 51 | collection.findOneAndDelete(new Document(filter)); 52 | } 53 | 54 | @Override 55 | public boolean exists(URI uri, Map options) { 56 | final MongoCollection collection = getCollection(uri); 57 | final Map filter = new HashMap<>(); 58 | filter.put(ID_FIELD, uri.segment(2)); 59 | filter.put(TYPE_FIELD, "resource"); 60 | 61 | return collection.find(new Document(filter)).limit(1).first() != null; 62 | } 63 | 64 | protected String db(URI uri) { 65 | String databaseName = uri.segment(0); 66 | if (databaseName == null) 67 | throw new IllegalArgumentException("Cannot find database name from uri " + uri); 68 | 69 | return databaseName; 70 | } 71 | 72 | protected String collection(URI uri) { 73 | final String collectionName = uri.segment(1); 74 | if (collectionName == null) 75 | throw new IllegalArgumentException("Cannot find collection name from uri " + uri); 76 | 77 | return collectionName; 78 | } 79 | 80 | public MongoCollection getCollection(URI uri) { 81 | if (uri.segmentCount() < 3) 82 | throw new IllegalArgumentException(); 83 | 84 | return client.getDatabase(uri.segment(0)).getCollection(uri.segment(1)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/emfjson/mongo/bson/codecs/JsonWriter.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.bson.codecs; 2 | 3 | import org.bson.*; 4 | import org.bson.json.JsonMode; 5 | import org.bson.json.JsonWriterSettings; 6 | import org.bson.types.ObjectId; 7 | 8 | import java.io.IOException; 9 | import java.io.Writer; 10 | 11 | import static javax.xml.bind.DatatypeConverter.printBase64Binary; 12 | 13 | public class JsonWriter extends org.bson.json.JsonWriter { 14 | 15 | private final JsonWriterSettings settings; 16 | 17 | public JsonWriter(Writer writer) { 18 | this(writer, new JsonWriterSettings()); 19 | } 20 | 21 | public JsonWriter(final Writer writer, final JsonWriterSettings settings) { 22 | super(writer, settings); 23 | this.settings = settings; 24 | if (settings.getOutputMode().equals(JsonMode.SHELL)) 25 | throw new IllegalArgumentException("JsonMode must not be SHELL"); 26 | setContext(new Context(null, BsonContextType.TOP_LEVEL, "")); 27 | } 28 | 29 | @Override 30 | protected void doWriteStartDocument() { 31 | try { 32 | if (getState() == State.VALUE || getState() == State.SCOPE_DOCUMENT) { 33 | writeNameHelper(getName()); 34 | } 35 | getWriter().write("{"); 36 | 37 | BsonContextType contextType = (getState() == State.SCOPE_DOCUMENT) ? BsonContextType.SCOPE_DOCUMENT 38 | : BsonContextType.DOCUMENT; 39 | setContext(new Context(getContext(), contextType, settings.getIndentCharacters())); 40 | } catch (IOException e) { 41 | throwBSONException(e); 42 | } 43 | } 44 | 45 | @Override 46 | protected void doWriteStartArray() { 47 | try { 48 | writeNameHelper(getName()); 49 | getWriter().write("["); 50 | setContext(new Context(getContext(), BsonContextType.ARRAY, settings.getIndentCharacters())); 51 | } catch (IOException e) { 52 | throwBSONException(e); 53 | } 54 | } 55 | 56 | @Override 57 | protected void doWriteBinaryData(final BsonBinary binary) { 58 | writeStartDocument(); 59 | writeString("$binary", printBase64Binary(binary.getData())); 60 | writeString("$type", Integer.toHexString(binary.getType() & 0xFF)); 61 | writeEndDocument(); 62 | } 63 | 64 | @Override 65 | public void doWriteBoolean(final boolean value) { 66 | try { 67 | writeNameHelper(getName()); 68 | getWriter().write(value ? "true": "false"); 69 | } catch (IOException e) { 70 | throwBSONException(e); 71 | } 72 | } 73 | 74 | @Override 75 | protected void doWriteDateTime(final long value) { 76 | try { 77 | writeNameHelper(getName()); 78 | getWriter().write(Long.toString(value)); 79 | } catch (IOException e) { 80 | throwBSONException(e); 81 | } 82 | } 83 | 84 | @Override 85 | protected void doWriteDBPointer(final BsonDbPointer value) { 86 | writeStartDocument(); 87 | writeString("$ref", value.getNamespace()); 88 | writeObjectId("$id", value.getId()); 89 | writeEndDocument(); 90 | } 91 | 92 | @Override 93 | protected void doWriteDouble(final double value) { 94 | try { 95 | writeNameHelper(getName()); 96 | getWriter().write(Double.toString(value)); 97 | setState(getNextState()); 98 | } catch (IOException e) { 99 | throwBSONException(e); 100 | } 101 | } 102 | 103 | @Override 104 | protected void doWriteInt32(final int value) { 105 | try { 106 | writeNameHelper(getName()); 107 | getWriter().write(Integer.toString(value)); 108 | } catch (IOException e) { 109 | throwBSONException(e); 110 | } 111 | } 112 | 113 | @Override 114 | protected void doWriteInt64(final long value) { 115 | try { 116 | writeNameHelper(getName()); 117 | getWriter().write(Long.toString(value)); 118 | } catch (IOException e) { 119 | throwBSONException(e); 120 | } 121 | } 122 | 123 | @Override 124 | protected void doWriteJavaScript(final String code) { 125 | writeStartDocument(); 126 | writeString("$code", code); 127 | writeEndDocument(); 128 | } 129 | 130 | @Override 131 | protected void doWriteJavaScriptWithScope(final String code) { 132 | writeStartDocument(); 133 | writeString("$code", code); 134 | writeName("$scope"); 135 | } 136 | 137 | @Override 138 | protected void doWriteMaxKey() { 139 | writeStartDocument(); 140 | writeInt32("$maxKey", 1); 141 | writeEndDocument(); 142 | } 143 | 144 | @Override 145 | protected void doWriteMinKey() { 146 | writeStartDocument(); 147 | writeInt32("$minKey", 1); 148 | writeEndDocument(); 149 | } 150 | 151 | @Override 152 | public void doWriteNull() { 153 | try { 154 | writeNameHelper(getName()); 155 | getWriter().write("null"); 156 | } catch (IOException e) { 157 | throwBSONException(e); 158 | } 159 | } 160 | 161 | @Override 162 | public void doWriteObjectId(final ObjectId objectId) { 163 | writeStartDocument(); 164 | writeString("$oid", objectId.toString()); 165 | writeEndDocument(); 166 | } 167 | 168 | @Override 169 | public void doWriteRegularExpression(final BsonRegularExpression regularExpression) { 170 | try { 171 | writeNameHelper(getName()); 172 | getWriter().write("/"); 173 | String escaped = (regularExpression.getPattern().equals("")) ? "(?:)" 174 | : regularExpression.getPattern().replace("/", "\\/"); 175 | getWriter().write(escaped); 176 | getWriter().write("/"); 177 | getWriter().write(regularExpression.getOptions()); 178 | } catch (IOException e) { 179 | throwBSONException(e); 180 | } 181 | } 182 | 183 | @Override 184 | public void doWriteString(final String value) { 185 | try { 186 | writeNameHelper(getName()); 187 | writeStringHelper(value); 188 | } catch (IOException e) { 189 | throwBSONException(e); 190 | } 191 | } 192 | 193 | @Override 194 | public void doWriteSymbol(final String value) { 195 | writeStartDocument(); 196 | writeString("$symbol", value); 197 | writeEndDocument(); 198 | } 199 | 200 | @Override 201 | public void doWriteTimestamp(final BsonTimestamp value) { 202 | writeStartDocument(); 203 | writeStartDocument("$timestamp"); 204 | writeInt32("t", value.getTime()); 205 | writeInt32("i", value.getInc()); 206 | writeEndDocument(); 207 | writeEndDocument(); 208 | } 209 | 210 | @Override 211 | public void doWriteUndefined() { 212 | try { 213 | writeNameHelper(getName()); 214 | getWriter().write("undefined"); 215 | } catch (IOException e) { 216 | throwBSONException(e); 217 | } 218 | } 219 | 220 | private void throwBSONException(final IOException e) { 221 | throw new BSONException("Wrapping IOException", e); 222 | } 223 | 224 | private void writeNameHelper(final String name) throws IOException { 225 | switch (getContext().getContextType()) { 226 | case ARRAY: 227 | // don't write Array element names in JSON 228 | if (getContext().hasElements()) { 229 | getWriter().write(", "); 230 | } 231 | break; 232 | case DOCUMENT: 233 | case SCOPE_DOCUMENT: 234 | if (getContext().hasElements()) { 235 | getWriter().write(","); 236 | } 237 | if (settings.isIndent()) { 238 | getWriter().write(settings.getNewLineCharacters()); 239 | getWriter().write(getContext().getIndentation()); 240 | } else { 241 | getWriter().write(" "); 242 | } 243 | writeStringHelper(name); 244 | getWriter().write(" : "); 245 | break; 246 | case TOP_LEVEL: 247 | break; 248 | default: 249 | throw new BSONException("Invalid contextType."); 250 | } 251 | 252 | getContext().hasElements(true); 253 | } 254 | 255 | private void writeStringHelper(final String str) throws IOException { 256 | getWriter().write('"'); 257 | for (final char c : str.toCharArray()) { 258 | switch (c) { 259 | case '"': 260 | getWriter().write("\\\""); 261 | break; 262 | case '\\': 263 | getWriter().write("\\\\"); 264 | break; 265 | case '\b': 266 | getWriter().write("\\b"); 267 | break; 268 | case '\f': 269 | getWriter().write("\\f"); 270 | break; 271 | case '\n': 272 | getWriter().write("\\n"); 273 | break; 274 | case '\r': 275 | getWriter().write("\\r"); 276 | break; 277 | case '\t': 278 | getWriter().write("\\t"); 279 | break; 280 | default: 281 | switch (Character.getType(c)) { 282 | case Character.UPPERCASE_LETTER: 283 | case Character.LOWERCASE_LETTER: 284 | case Character.TITLECASE_LETTER: 285 | case Character.OTHER_LETTER: 286 | case Character.DECIMAL_DIGIT_NUMBER: 287 | case Character.LETTER_NUMBER: 288 | case Character.OTHER_NUMBER: 289 | case Character.SPACE_SEPARATOR: 290 | case Character.CONNECTOR_PUNCTUATION: 291 | case Character.DASH_PUNCTUATION: 292 | case Character.START_PUNCTUATION: 293 | case Character.END_PUNCTUATION: 294 | case Character.INITIAL_QUOTE_PUNCTUATION: 295 | case Character.FINAL_QUOTE_PUNCTUATION: 296 | case Character.OTHER_PUNCTUATION: 297 | case Character.MATH_SYMBOL: 298 | case Character.CURRENCY_SYMBOL: 299 | case Character.MODIFIER_SYMBOL: 300 | case Character.OTHER_SYMBOL: 301 | getWriter().write(c); 302 | break; 303 | default: 304 | getWriter().write("\\u"); 305 | getWriter().write(Integer.toHexString((c & 0xf000) >> 12)); 306 | getWriter().write(Integer.toHexString((c & 0x0f00) >> 8)); 307 | getWriter().write(Integer.toHexString((c & 0x00f0) >> 4)); 308 | getWriter().write(Integer.toHexString(c & 0x000f)); 309 | break; 310 | } 311 | break; 312 | } 313 | } 314 | getWriter().write('"'); 315 | } 316 | 317 | @Override 318 | protected Context getContext() { 319 | return (Context) super.getContext(); 320 | } 321 | 322 | /** 323 | * The context for the writer, inheriting all the values from 324 | * {@link org.bson.AbstractBsonWriter.Context}, and additionally providing 325 | * settings for the indentation level and whether there are any child 326 | * elements at this level. 327 | */ 328 | public class Context extends org.bson.json.JsonWriter.Context { 329 | private final String indentation; 330 | 331 | public String getIndentation() { 332 | return indentation; 333 | } 334 | 335 | private boolean hasElements; 336 | 337 | public boolean hasElements() { 338 | return hasElements; 339 | } 340 | 341 | public void hasElements(boolean hasElements) { 342 | this.hasElements = hasElements; 343 | } 344 | 345 | /** 346 | * Creates a new context. 347 | * 348 | * @param parentContext the parent context that can be used for going back up to 349 | * the parent level 350 | * @param contextType the type of this context 351 | * @param indentChars the String to use for indentation at this level. 352 | */ 353 | public Context(final Context parentContext, final BsonContextType contextType, final String indentChars) { 354 | super(parentContext, contextType, indentChars); 355 | this.indentation = (parentContext == null) ? indentChars: parentContext.indentation + indentChars; 356 | } 357 | 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /src/main/java/org/emfjson/mongo/streams/MongoInputStream.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.streams; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.mongodb.client.MongoCollection; 6 | import org.bson.Document; 7 | import org.bson.codecs.DocumentCodec; 8 | import org.bson.codecs.EncoderContext; 9 | import org.eclipse.emf.common.util.URI; 10 | import org.eclipse.emf.ecore.resource.Resource; 11 | import org.eclipse.emf.ecore.resource.URIConverter.Loadable; 12 | import org.emfjson.jackson.annotations.EcoreReferenceInfo; 13 | import org.emfjson.jackson.module.EMFModule; 14 | import org.emfjson.mongo.MongoHandler; 15 | import org.emfjson.mongo.bson.codecs.JsonWriter; 16 | 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.io.StringWriter; 20 | import java.util.Map; 21 | 22 | import static org.emfjson.jackson.databind.EMFContext.Attributes.RESOURCE; 23 | 24 | public class MongoInputStream extends InputStream implements Loadable { 25 | 26 | private final Map options; 27 | private final URI uri; 28 | private MongoHandler handler; 29 | 30 | private final ObjectMapper mapper = new ObjectMapper(); 31 | 32 | public MongoInputStream(MongoHandler handler, URI uri, Map options) { 33 | this.uri = uri; 34 | this.options = options; 35 | this.handler = handler; 36 | 37 | EMFModule module = new EMFModule(); 38 | module.setReferenceInfo(new EcoreReferenceInfo.Base("_ref")); 39 | mapper.registerModule(module); 40 | } 41 | 42 | @Override 43 | public void loadResource(Resource resource) throws IOException { 44 | final MongoCollection collection = handler.getCollection(uri); 45 | 46 | if (!resource.getContents().isEmpty()) { 47 | resource.getContents().clear(); 48 | } 49 | 50 | final String id = uri.segment(2); 51 | final Document filter = new Document(MongoHandler.ID_FIELD, id); 52 | final Document document = collection 53 | .find(filter) 54 | .limit(1) 55 | .first(); 56 | 57 | if (document == null) { 58 | throw new IOException("Cannot find document with " + MongoHandler.ID_FIELD + " " + id); 59 | } 60 | 61 | JsonWriter writer = new JsonWriter(new StringWriter()); 62 | new DocumentCodec().encode(writer, document, 63 | EncoderContext.builder() 64 | .isEncodingCollectibleDocument(true) 65 | .build()); 66 | readJson(resource, writer.getWriter().toString()); 67 | } 68 | 69 | private void readJson(Resource resource, String data) throws IOException { 70 | final JsonNode rootNode = mapper.readTree(data); 71 | final JsonNode contents = rootNode.has(MongoHandler.CONTENTS_FIELD) ? 72 | rootNode.get(MongoHandler.CONTENTS_FIELD): 73 | null; 74 | 75 | if (contents != null) { 76 | mapper.reader() 77 | .withAttribute(RESOURCE, resource) 78 | .treeToValue(contents, Resource.class); 79 | } 80 | } 81 | 82 | @Override 83 | public int read() throws IOException { 84 | return 0; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/emfjson/mongo/streams/MongoOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.streams; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.JsonNode; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.databind.node.ObjectNode; 7 | import com.mongodb.client.MongoCollection; 8 | import org.bson.Document; 9 | import org.eclipse.emf.common.util.URI; 10 | import org.eclipse.emf.ecore.resource.Resource; 11 | import org.eclipse.emf.ecore.resource.URIConverter.Saveable; 12 | import org.emfjson.jackson.annotations.EcoreReferenceInfo; 13 | import org.emfjson.jackson.module.EMFModule; 14 | import org.emfjson.mongo.MongoHandler; 15 | 16 | import java.io.ByteArrayOutputStream; 17 | import java.io.IOException; 18 | import java.util.Map; 19 | 20 | public class MongoOutputStream extends ByteArrayOutputStream implements Saveable { 21 | 22 | private final Map options; 23 | private final URI uri; 24 | private final MongoHandler handler; 25 | 26 | private final ObjectMapper mapper = new ObjectMapper(); 27 | 28 | public MongoOutputStream(MongoHandler handler, URI uri, Map options) { 29 | this.handler = handler; 30 | this.uri = uri; 31 | this.options = options; 32 | 33 | EMFModule module = new EMFModule(); 34 | module.setReferenceInfo(new EcoreReferenceInfo.Base("_ref")); 35 | mapper.registerModule(module); 36 | } 37 | 38 | @Override 39 | public void saveResource(Resource resource) throws IOException { 40 | if (uri == null) { 41 | throw new IOException(); 42 | } 43 | 44 | final MongoCollection collection = handler.getCollection(uri); 45 | final String data = toJson(resource); 46 | 47 | if (data == null) { 48 | throw new IOException("Error during saving"); 49 | } 50 | 51 | final Document filter = new Document(MongoHandler.ID_FIELD, uri.segment(2)); 52 | if (collection.find(filter).limit(1).first() == null) { 53 | collection.insertOne(Document.parse(data)); 54 | } else { 55 | collection.findOneAndReplace(filter, Document.parse(data)); 56 | } 57 | } 58 | 59 | private String toJson(Resource resource) throws JsonProcessingException { 60 | final JsonNode contents = mapper.valueToTree(resource); 61 | final ObjectNode resourceNode = mapper.createObjectNode(); 62 | final String id = uri.segment(2); 63 | 64 | resourceNode.put(MongoHandler.ID_FIELD, id); 65 | resourceNode.put(MongoHandler.TYPE_FIELD, "resource"); 66 | resourceNode.set(MongoHandler.CONTENTS_FIELD, contents); 67 | 68 | return mapper.writeValueAsString(resourceNode); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/TestSuite.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo; 2 | 3 | import org.emfjson.mongo.tests.*; 4 | import org.junit.runner.RunWith; 5 | import org.junit.runners.Suite; 6 | 7 | @RunWith(Suite.class) 8 | @Suite.SuiteClasses({ 9 | MongoHandlerSaveTest.class, 10 | MongoHandlerLoadTest.class, 11 | LoadReferenceTest.class, 12 | MongoHandlerSaveAndLoadTest.class, 13 | UseIdTest.class, 14 | DynamicTest.class 15 | }) 16 | public class TestSuite { 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/bench/Benchmark.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.bench; 2 | 3 | import com.mongodb.MongoClient; 4 | import org.eclipse.emf.common.util.URI; 5 | import org.eclipse.emf.ecore.EObject; 6 | import org.eclipse.emf.ecore.resource.Resource; 7 | import org.eclipse.emf.ecore.resource.ResourceSet; 8 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 9 | import org.emfjson.jackson.resource.JsonResourceFactory; 10 | import org.emfjson.model.ModelFactory; 11 | import org.emfjson.model.TestA; 12 | import org.emfjson.model.TestB; 13 | import org.emfjson.mongo.MongoHandler; 14 | 15 | import java.io.IOException; 16 | import java.util.ArrayList; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | public class Benchmark { 22 | 23 | static URI mongoURI = URI.createURI("mongodb://localhost:27017/emfjson-test/bench"); 24 | static long times = 20; 25 | 26 | static List createModel() { 27 | List contents = new ArrayList<>(); 28 | 29 | for (int i = 0; i < 500; i++) { 30 | 31 | TestA a = ModelFactory.eINSTANCE.createTestA(); 32 | a.setStringValue("A" + i); 33 | contents.add(a); 34 | 35 | for (int j = 0; j < 200; j++) { 36 | 37 | TestB b = ModelFactory.eINSTANCE.createTestB(); 38 | b.setStringValue("B" + i + "-" + j); 39 | a.getContainBs().add(b); 40 | } 41 | } 42 | 43 | return contents; 44 | } 45 | 46 | static long performSave(Resource resource, Map options) { 47 | long start = System.currentTimeMillis(); 48 | try { 49 | resource.save(options); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | return System.currentTimeMillis() - start; 54 | } 55 | 56 | public static void main(String[] args) { 57 | long sum = 0; 58 | Map options = new HashMap<>(); 59 | 60 | final MongoClient client = new MongoClient(); 61 | 62 | for (int i = 0; i < times; i++) { 63 | ResourceSet resourceSet = new ResourceSetImpl(); 64 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 65 | resourceSet.getURIConverter().getURIHandlers().add(0, new MongoHandler(client)); 66 | 67 | Resource resource = resourceSet.createResource(mongoURI.appendSegment("test")); 68 | resource.getContents().addAll(createModel()); 69 | 70 | sum += performSave(resource, options); 71 | } 72 | 73 | long average = sum / times; 74 | 75 | System.out.println("Average time for storing " + (500 * 200) + " elements: " + average / 1000. + " seconds."); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/DynamicTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.mongodb.MongoClient; 4 | import org.eclipse.emf.common.util.URI; 5 | import org.eclipse.emf.ecore.*; 6 | import org.eclipse.emf.ecore.resource.Resource; 7 | import org.eclipse.emf.ecore.resource.ResourceSet; 8 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 9 | import org.eclipse.emf.ecore.util.EcoreUtil; 10 | import org.emfjson.jackson.resource.JsonResourceFactory; 11 | import org.emfjson.mongo.MongoHandler; 12 | import org.junit.After; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import java.io.IOException; 17 | import java.util.Collection; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import static org.junit.Assert.*; 22 | 23 | public class DynamicTest { 24 | 25 | private ResourceSetImpl resourceSet; 26 | private MongoClient client; 27 | 28 | private Map options = new HashMap<>(); 29 | private URI testURI1 = URI.createURI("mongodb://localhost:27017/emfjson-test/models/foo"); 30 | private URI testURI2 = URI.createURI("mongodb://localhost:27017/emfjson-test/models/foo-model"); 31 | 32 | @Before 33 | public void setUp() throws IOException { 34 | client = new MongoClient(); 35 | 36 | MongoHandler handler = new MongoHandler(client); 37 | resourceSet = new ResourceSetImpl(); 38 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 39 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 40 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 41 | resourceSet.getLoadOptions().putAll(options); 42 | 43 | resourceSet.getURIConverter().getURIMap().put( 44 | URI.createURI("http://test/foo"), testURI1); 45 | 46 | resourceSet.getURIConverter().getURIMap().put( 47 | URI.createURI("http://test/foo-model"), testURI2); 48 | 49 | createModel(createPackage(resourceSet), resourceSet); 50 | resourceSet.getResources().clear(); 51 | } 52 | 53 | @After 54 | public void tearDown() { 55 | client.getDatabase("emfjson-test").drop(); 56 | } 57 | 58 | @Test 59 | public void testLoadModel() throws IOException { 60 | Resource resource = resourceSet.createResource(URI.createURI("http://test/foo-model")); 61 | assertNotNull(resource); 62 | assertTrue(resource.getContents().isEmpty()); 63 | 64 | resource.load(options); 65 | 66 | assertEquals(1, resource.getContents().size()); 67 | 68 | EObject root = resource.getContents().get(0); 69 | 70 | assertEquals("A", root.eClass().getName()); 71 | } 72 | 73 | private EPackage createPackage(ResourceSet resourceSet) throws IOException { 74 | EPackage foo = EcoreFactory.eINSTANCE.createEPackage(); 75 | foo.setName("foo"); 76 | foo.setNsPrefix("foo"); 77 | foo.setNsURI("http://test/foo"); 78 | 79 | EClass a = EcoreFactory.eINSTANCE.createEClass(); 80 | a.setName("A"); 81 | 82 | EClass b = EcoreFactory.eINSTANCE.createEClass(); 83 | b.setName("B"); 84 | b.getESuperTypes().add(a); 85 | 86 | EAttribute label = EcoreFactory.eINSTANCE.createEAttribute(); 87 | label.setName("label"); 88 | label.setEType(EcorePackage.Literals.ESTRING); 89 | 90 | EReference bs = EcoreFactory.eINSTANCE.createEReference(); 91 | bs.setName("bs"); 92 | bs.setEType(b); 93 | bs.setUpperBound(-1); 94 | bs.setContainment(true); 95 | 96 | a.getEStructuralFeatures().add(label); 97 | a.getEStructuralFeatures().add(bs); 98 | 99 | foo.getEClassifiers().add(a); 100 | foo.getEClassifiers().add(b); 101 | 102 | Resource resource = resourceSet.createResource(URI.createURI("http://test/foo")); 103 | 104 | resource.getContents().add(foo); 105 | resource.save(options); 106 | 107 | return foo; 108 | } 109 | 110 | @SuppressWarnings("unchecked") 111 | private void createModel(EPackage p, ResourceSet resourceSet) throws IOException { 112 | EClass a = (EClass) p.getEClassifier("A"); 113 | EClass b = (EClass) p.getEClassifier("B"); 114 | 115 | EObject a1 = EcoreUtil.create(a); 116 | EObject b1 = EcoreUtil.create(a); 117 | EObject b2 = EcoreUtil.create(a); 118 | 119 | a1.eSet(a.getEStructuralFeature("label"), "a1"); 120 | b1.eSet(b.getEStructuralFeature("label"), "b1"); 121 | b2.eSet(b.getEStructuralFeature("label"), "b2"); 122 | 123 | ((Collection) a1.eGet(a.getEStructuralFeature("bs"))).add(b1); 124 | ((Collection) a1.eGet(a.getEStructuralFeature("bs"))).add(b2); 125 | 126 | Resource resource = resourceSet.createResource(URI.createURI("http://test/foo-model")); 127 | 128 | resource.getContents().add(a1); 129 | resource.save(options); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/LoadReferenceTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.JsonNode; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.mongodb.MongoClient; 7 | import com.mongodb.client.MongoCollection; 8 | import org.bson.Document; 9 | import org.eclipse.emf.common.util.URI; 10 | import org.eclipse.emf.ecore.EClass; 11 | import org.eclipse.emf.ecore.EcorePackage; 12 | import org.eclipse.emf.ecore.resource.Resource; 13 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 14 | import org.eclipse.emf.ecore.util.EcoreUtil; 15 | import org.emfjson.jackson.resource.JsonResourceFactory; 16 | import org.emfjson.model.ModelPackage; 17 | import org.emfjson.model.TestA; 18 | import org.emfjson.model.TestB; 19 | import org.emfjson.mongo.MongoHandler; 20 | import org.junit.After; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | import static org.assertj.core.api.Assertions.assertThat; 28 | 29 | public class LoadReferenceTest { 30 | 31 | private MongoClient client; 32 | private ResourceSetImpl resourceSet; 33 | private MongoHandler handler; 34 | private URI testURI = URI.createURI("mongodb://localhost:27017/test/models"); 35 | 36 | @Before 37 | public void setUp() throws JsonProcessingException { 38 | client = new MongoClient(); 39 | 40 | handler = new MongoHandler(client); 41 | resourceSet = new ResourceSetImpl(); 42 | 43 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 44 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 45 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 46 | 47 | Map options = new HashMap<>(); 48 | 49 | resourceSet.getLoadOptions().putAll(options); 50 | } 51 | 52 | private String uri(EClass eClass) { 53 | return EcoreUtil.getURI(eClass).toString(); 54 | } 55 | 56 | @After 57 | public void tearDown() { 58 | client.getDatabase("test").drop(); 59 | } 60 | 61 | protected void fixtureOne() throws JsonProcessingException { 62 | MongoCollection c1 = handler.getCollection(testURI.appendSegment("c1")); 63 | MongoCollection c2 = handler.getCollection(testURI.appendSegment("c2")); 64 | 65 | ObjectMapper mapper = new ObjectMapper(); 66 | JsonNode content_c1 = mapper.createObjectNode() 67 | .put("_id", "c1") 68 | .put("_type", "resource") 69 | .set("contents", mapper.createObjectNode() 70 | .put("eClass", uri(ModelPackage.Literals.TEST_A)) 71 | .set("oneB", mapper.createObjectNode() 72 | .put("eClass", uri(ModelPackage.Literals.TEST_B)) 73 | .put("_ref", "mongodb://localhost:27017/test/models/c2#/"))); 74 | 75 | JsonNode content_c2 = mapper.createObjectNode() 76 | .put("_id", "c2") 77 | .put("_type", "resource") 78 | .set("contents", mapper.createObjectNode() 79 | .put("eClass", uri(ModelPackage.Literals.TEST_B))); 80 | 81 | c1.insertOne(Document.parse(mapper.writeValueAsString(content_c1))); 82 | c2.insertOne(Document.parse(mapper.writeValueAsString(content_c2))); 83 | } 84 | 85 | @Test 86 | public void testLoadingCrossReference() throws JsonProcessingException { 87 | fixtureOne(); 88 | 89 | Resource c1 = resourceSet.getResource(testURI.appendSegment("c1"), true); 90 | 91 | TestA a = (TestA) c1.getContents().get(0); 92 | 93 | assertThat(a.getOneB()) 94 | .isNotNull(); 95 | 96 | Resource c2 = resourceSet.getResource(testURI.appendSegment("c2"), true); 97 | 98 | assertThat(c2.getContents()) 99 | .hasSize(1); 100 | 101 | assertThat(a.getOneB()) 102 | .isSameAs(c2.getContents().get(0)); 103 | } 104 | 105 | protected void fixtureTwo() throws JsonProcessingException { 106 | MongoCollection c1 = handler.getCollection(testURI.appendSegment("c1")); 107 | MongoCollection c2 = handler.getCollection(testURI.appendSegment("c2")); 108 | MongoCollection c3 = handler.getCollection(testURI.appendSegment("c3")); 109 | 110 | ObjectMapper mapper = new ObjectMapper(); 111 | JsonNode content_c1 = mapper.createObjectNode() 112 | .put("_id", "c1") 113 | .put("_type", "resource") 114 | .set("contents", mapper.createObjectNode() 115 | .put("eClass", uri(ModelPackage.Literals.TEST_A)) 116 | .set("manyBs", mapper.createArrayNode() 117 | .add(mapper.createObjectNode() 118 | .put("eClass", uri(ModelPackage.Literals.TEST_B)) 119 | .put("_ref", "mongodb://localhost:27017/test/models/c2#/")) 120 | .add(mapper.createObjectNode() 121 | .put("eClass", uri(ModelPackage.Literals.TEST_B)) 122 | .put("_ref", "mongodb://localhost:27017/test/models/c3#/")))); 123 | 124 | JsonNode content_c2 = mapper.createObjectNode() 125 | .put("_id", "c2") 126 | .put("_type", "resource") 127 | .set("contents", mapper.createObjectNode() 128 | .put("eClass", uri(ModelPackage.Literals.TEST_B))); 129 | 130 | JsonNode content_c3 = mapper.createObjectNode() 131 | .put("_id", "c3") 132 | .put("_type", "resource") 133 | .set("contents", mapper.createObjectNode() 134 | .put("eClass", uri(ModelPackage.Literals.TEST_B))); 135 | 136 | c1.insertOne(Document.parse(mapper.writeValueAsString(content_c1))); 137 | c2.insertOne(Document.parse(mapper.writeValueAsString(content_c2))); 138 | c3.insertOne(Document.parse(mapper.writeValueAsString(content_c3))); 139 | } 140 | 141 | @Test 142 | public void testLoadingManyCrossReference() throws JsonProcessingException { 143 | fixtureTwo(); 144 | 145 | Resource c1 = resourceSet.getResource(testURI.appendSegment("c1"), true); 146 | 147 | TestA a = (TestA) c1.getContents().get(0); 148 | 149 | assertThat(a.getManyBs()) 150 | .hasSize(2); 151 | 152 | Resource c2 = resourceSet.getResource(testURI.appendSegment("c2"), true); 153 | Resource c3 = resourceSet.getResource(testURI.appendSegment("c3"), true); 154 | 155 | assertThat(c2.getContents()) 156 | .hasSize(1); 157 | assertThat(c3.getContents()) 158 | .hasSize(1); 159 | assertThat(a.getManyBs()).containsExactly( 160 | (TestB) c2.getContents().get(0), 161 | (TestB) c3.getContents().get(0)); 162 | } 163 | 164 | } 165 | 166 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/MongoHandlerLoadTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.JsonNode; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.mongodb.BasicDBObject; 7 | import com.mongodb.MongoClient; 8 | import com.mongodb.client.MongoCollection; 9 | import org.bson.Document; 10 | import org.eclipse.emf.common.util.URI; 11 | import org.eclipse.emf.ecore.EClass; 12 | import org.eclipse.emf.ecore.EPackage; 13 | import org.eclipse.emf.ecore.EcorePackage; 14 | import org.eclipse.emf.ecore.resource.Resource; 15 | import org.eclipse.emf.ecore.resource.ResourceSet; 16 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 17 | import org.emfjson.jackson.resource.JsonResourceFactory; 18 | import org.emfjson.mongo.MongoHandler; 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.io.IOException; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | 27 | public class MongoHandlerLoadTest { 28 | 29 | private ResourceSet resourceSet; 30 | private MongoClient client; 31 | private URI testURI = URI.createURI("mongodb://localhost:27017/emfjson-test/models/model1"); 32 | 33 | @Before 34 | public void setUp() throws JsonProcessingException { 35 | client = new MongoClient(); 36 | 37 | MongoHandler handler = new MongoHandler(client); 38 | resourceSet = new ResourceSetImpl(); 39 | 40 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 41 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 42 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 43 | 44 | MongoCollection collection = handler.getCollection(testURI); 45 | 46 | ObjectMapper mapper = new ObjectMapper(); 47 | JsonNode content = mapper.createObjectNode() 48 | .put("_id", "model1") 49 | .put("_type", "resource") 50 | .set("contents", mapper.createObjectNode() 51 | .put("eClass", "http://www.eclipse.org/emf/2002/Ecore#//EPackage") 52 | .put("name", "p") 53 | .set("eClassifiers", mapper.createArrayNode() 54 | .add(mapper.createObjectNode() 55 | .put("eClass", "http://www.eclipse.org/emf/2002/Ecore#//EClass") 56 | .put("name", "A")))); 57 | 58 | collection.deleteOne(new BasicDBObject("_id", "model1")); 59 | collection.insertOne(Document.parse(mapper.writeValueAsString(content))); 60 | } 61 | 62 | @After 63 | public void tearDown() { 64 | client.getDatabase("emfjson-test").drop(); 65 | } 66 | 67 | @Test 68 | public void testLoad() throws IOException { 69 | Resource resource = resourceSet.createResource(testURI); 70 | resource.load(null); 71 | 72 | assertEquals(1, resource.getContents().size()); 73 | assertEquals(EcorePackage.Literals.EPACKAGE, resource.getContents().get(0).eClass()); 74 | 75 | EPackage p = (EPackage) resource.getContents().get(0); 76 | 77 | assertEquals("p", p.getName()); 78 | assertEquals(1, p.getEClassifiers().size()); 79 | assertEquals(EcorePackage.Literals.ECLASS, p.getEClassifiers().get(0).eClass()); 80 | 81 | EClass c = (EClass) p.getEClassifiers().get(0); 82 | assertEquals("A", c.getName()); 83 | } 84 | 85 | @Test 86 | public void testLoadWithUriMapping() throws IOException { 87 | resourceSet.getURIConverter().getURIMap().put( 88 | URI.createURI("http://resources/"), 89 | URI.createURI("mongodb://localhost:27017/emfjson-test/models/")); 90 | 91 | Resource resource = resourceSet.createResource(URI.createURI("http://resources/model1")); 92 | resource.load(null); 93 | 94 | assertEquals(1, resource.getContents().size()); 95 | assertEquals(EcorePackage.Literals.EPACKAGE, resource.getContents().get(0).eClass()); 96 | 97 | EPackage p = (EPackage) resource.getContents().get(0); 98 | 99 | assertEquals("p", p.getName()); 100 | assertEquals(1, p.getEClassifiers().size()); 101 | assertEquals(EcorePackage.Literals.ECLASS, p.getEClassifiers().get(0).eClass()); 102 | 103 | EClass c = (EClass) p.getEClassifiers().get(0); 104 | assertEquals("A", c.getName()); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/MongoHandlerSaveAndLoadTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.mongodb.MongoClient; 6 | import com.mongodb.client.MongoCollection; 7 | import org.bson.Document; 8 | import org.eclipse.emf.common.util.URI; 9 | import org.eclipse.emf.ecore.EcorePackage; 10 | import org.eclipse.emf.ecore.resource.Resource; 11 | import org.eclipse.emf.ecore.resource.ResourceSet; 12 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 13 | import org.eclipse.emf.ecore.util.EcoreUtil; 14 | import org.emfjson.jackson.resource.JsonResourceFactory; 15 | import org.emfjson.model.ModelPackage; 16 | import org.emfjson.model.TestA; 17 | import org.emfjson.mongo.MongoHandler; 18 | import org.junit.After; 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | 22 | import java.io.IOException; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | public class MongoHandlerSaveAndLoadTest { 27 | 28 | private ResourceSet resourceSet; 29 | private MongoClient client; 30 | private MongoHandler handler; 31 | private URI testURI = URI.createURI("mongodb://localhost:27017/emfjson-test/models/model1"); 32 | 33 | @Before 34 | public void setUp() { 35 | client = new MongoClient(); 36 | handler = new MongoHandler(client); 37 | resourceSet = new ResourceSetImpl(); 38 | 39 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 40 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 41 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 42 | } 43 | 44 | @After 45 | public void tearDown() { 46 | client.getDatabase("emfjson-test").drop(); 47 | } 48 | 49 | @Test 50 | public void testSaveThenLoadNode() throws IOException { 51 | MongoCollection models = handler.getCollection(testURI); 52 | 53 | ObjectMapper mapper = new ObjectMapper(); 54 | JsonNode content_model1 = mapper.createObjectNode() 55 | .put("_id", "model1") 56 | .put("_type", "resource") 57 | .set("contents", mapper.createObjectNode() 58 | .put("eClass", EcoreUtil.getURI(ModelPackage.Literals.TEST_A).toString()) 59 | .put("stringValue", "testStringValue") 60 | .put("intValue", 1234) 61 | .put("booleanValue", true) 62 | .put("longValue", 12345678900L)); 63 | 64 | 65 | models.insertOne(Document.parse(mapper.writeValueAsString(content_model1))); 66 | 67 | Resource resource = resourceSet.createResource(testURI); 68 | resource.load(null); 69 | 70 | assertEquals(1, resource.getContents().size()); 71 | assertEquals(ModelPackage.Literals.TEST_A, resource.getContents().get(0).eClass()); 72 | 73 | TestA ta = (TestA) resource.getContents().get(0); 74 | 75 | assertEquals("testStringValue", ta.getStringValue()); 76 | assertEquals(1234, ta.getIntValue().intValue()); 77 | assertEquals(true, ta.getBooleanValue()); 78 | assertEquals(12345678900L, ta.getLongValue().longValue()); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/MongoHandlerSaveTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.mongodb.BasicDBObject; 4 | import com.mongodb.MongoClient; 5 | import com.mongodb.client.MongoCollection; 6 | import org.bson.Document; 7 | import org.eclipse.emf.common.util.URI; 8 | import org.eclipse.emf.ecore.EClass; 9 | import org.eclipse.emf.ecore.EPackage; 10 | import org.eclipse.emf.ecore.EcoreFactory; 11 | import org.eclipse.emf.ecore.EcorePackage; 12 | import org.eclipse.emf.ecore.resource.Resource; 13 | import org.eclipse.emf.ecore.resource.ResourceSet; 14 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 15 | import org.emfjson.jackson.resource.JsonResourceFactory; 16 | import org.emfjson.mongo.MongoHandler; 17 | import org.junit.After; 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | 21 | import java.io.IOException; 22 | import java.util.List; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | public class MongoHandlerSaveTest { 27 | 28 | private ResourceSet resourceSet; 29 | private MongoClient client; 30 | private MongoHandler handler; 31 | private URI testURI = URI.createURI("mongodb://localhost:27017/emfjson-test/models/model1"); 32 | 33 | @Before 34 | public void setUp() { 35 | client = new MongoClient(); 36 | handler = new MongoHandler(client); 37 | resourceSet = new ResourceSetImpl(); 38 | 39 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 40 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory()); 41 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 42 | } 43 | 44 | @After 45 | public void tearDown() { 46 | client.getDatabase("emfjson-test").drop(); 47 | } 48 | 49 | @Test 50 | public void testSave() throws IOException { 51 | Resource resource = resourceSet.createResource(testURI); 52 | 53 | EPackage p = EcoreFactory.eINSTANCE.createEPackage(); 54 | p.setName("p"); 55 | EClass c = EcoreFactory.eINSTANCE.createEClass(); 56 | c.setName("A"); 57 | p.getEClassifiers().add(c); 58 | 59 | resource.getContents().add(p); 60 | resource.save(null); 61 | 62 | checkDocument(testURI); 63 | } 64 | 65 | @Test 66 | public void testSaveWithUriMapping() throws IOException { 67 | resourceSet.getURIConverter().getURIMap().put( 68 | URI.createURI("http://resources/"), 69 | URI.createURI("mongodb://localhost:27017/emfjson-test/models/")); 70 | 71 | Resource resource = resourceSet.createResource(URI.createURI("http://resources/model1")); 72 | 73 | EPackage p = EcoreFactory.eINSTANCE.createEPackage(); 74 | p.setName("p"); 75 | EClass c = EcoreFactory.eINSTANCE.createEClass(); 76 | c.setName("A"); 77 | p.getEClassifiers().add(c); 78 | 79 | resource.getContents().add(p); 80 | resource.save(null); 81 | 82 | checkDocument(testURI); 83 | } 84 | 85 | private void checkDocument(URI uri) { 86 | MongoCollection collection = handler.getCollection(uri); 87 | 88 | assertNotNull(collection); 89 | 90 | Document document = collection.find(new BasicDBObject("_id", "model1")).first(); 91 | 92 | assertNotNull(document); 93 | assertEquals("model1", document.get("_id")); 94 | assertEquals("resource", document.get("_type")); 95 | 96 | Document contents = (Document) document.get("contents"); 97 | 98 | assertEquals(3, contents.keySet().size()); 99 | assertEquals("http://www.eclipse.org/emf/2002/Ecore#//EPackage", contents.getString("eClass")); 100 | assertEquals("p", contents.getString("name")); 101 | 102 | assertTrue(contents.get("eClassifiers") instanceof List); 103 | 104 | List eClassifiers = (List) contents.get("eClassifiers"); 105 | Document first = eClassifiers.get(0); 106 | assertEquals("http://www.eclipse.org/emf/2002/Ecore#//EClass", first.getString("eClass")); 107 | assertEquals("A", first.getString("name")); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/org/emfjson/mongo/tests/UseIdTest.java: -------------------------------------------------------------------------------- 1 | package org.emfjson.mongo.tests; 2 | 3 | import com.mongodb.MongoClient; 4 | import com.mongodb.client.FindIterable; 5 | import com.mongodb.client.MongoCollection; 6 | import org.bson.Document; 7 | import org.eclipse.emf.common.util.URI; 8 | import org.eclipse.emf.ecore.EClass; 9 | import org.eclipse.emf.ecore.EPackage; 10 | import org.eclipse.emf.ecore.EcoreFactory; 11 | import org.eclipse.emf.ecore.EcorePackage; 12 | import org.eclipse.emf.ecore.resource.Resource; 13 | import org.eclipse.emf.ecore.resource.ResourceSet; 14 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; 15 | import org.eclipse.emf.ecore.util.EcoreUtil; 16 | import org.emfjson.jackson.module.EMFModule; 17 | import org.emfjson.jackson.resource.JsonResource; 18 | import org.emfjson.jackson.resource.JsonResourceFactory; 19 | import org.emfjson.mongo.MongoHandler; 20 | import org.junit.After; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | 24 | import java.io.IOException; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import static org.junit.Assert.*; 30 | 31 | public class UseIdTest { 32 | 33 | private ResourceSet resourceSet; 34 | private MongoHandler handler; 35 | private MongoClient client; 36 | 37 | @Before 38 | public void setUp() { 39 | client = new MongoClient(); 40 | handler = new MongoHandler(client); 41 | resourceSet = new ResourceSetImpl(); 42 | 43 | resourceSet.getPackageRegistry().put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); 44 | resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new JsonResourceFactory() { 45 | @Override 46 | public Resource createResource(URI uri) { 47 | return new JsonResource(uri) { 48 | @Override 49 | protected boolean useUUIDs() { 50 | return true; 51 | } 52 | }; 53 | } 54 | }); 55 | resourceSet.getURIConverter().getURIHandlers().add(0, handler); 56 | } 57 | 58 | @After 59 | public void tearDown() { 60 | client.getDatabase("emfjson-test").drop(); 61 | } 62 | 63 | private Map getOptions() { 64 | Map options = new HashMap<>(); 65 | options.put(EMFModule.Feature.OPTION_USE_ID.name(), true); 66 | return options; 67 | } 68 | 69 | @Test 70 | public void testSave() throws IOException { 71 | Resource resource = resourceSet.createResource( 72 | URI.createURI("mongodb://localhost:27017/emfjson-test/models/model-test-uuid-1")); 73 | 74 | EPackage p = EcoreFactory.eINSTANCE.createEPackage(); 75 | p.setName("p"); 76 | EClass c = EcoreFactory.eINSTANCE.createEClass(); 77 | c.setName("A"); 78 | p.getEClassifiers().add(c); 79 | 80 | resource.getContents().add(p); 81 | 82 | String pId = EcoreUtil.getURI(p).fragment(); 83 | String cId = EcoreUtil.getURI(c).fragment(); 84 | 85 | resource.save(getOptions()); 86 | 87 | MongoCollection collection = handler.getCollection(resource.getURI()); 88 | FindIterable objects = collection.find(new Document("_id", "model-test-uuid-1")); 89 | 90 | assertNotNull(objects); 91 | 92 | Document document = objects.iterator().next(); 93 | 94 | Document contents = (Document) document.get("contents"); 95 | assertNotNull(contents); 96 | 97 | assertTrue(contents.containsKey("_id")); 98 | assertEquals(pId, contents.get("_id")); 99 | 100 | List eClassifiers = (List) contents.get("eClassifiers"); 101 | assertEquals(1, eClassifiers.size()); 102 | 103 | Document cObject = (Document) eClassifiers.get(0); 104 | assertTrue(cObject.containsKey("_id")); 105 | assertEquals(cId, cObject.get("_id")); 106 | } 107 | 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/test/resources/model.xcore: -------------------------------------------------------------------------------- 1 | @GenModel( 2 | bundleManifest="false", 3 | modelDirectory="emfjson-mongo/src/test/java-gen", 4 | rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl", 5 | complianceLevel="7.0" 6 | ) 7 | package org.emfjson.model 8 | 9 | class TestA { 10 | String stringValue 11 | String[*] multiStringValues 12 | Integer intValue 13 | Integer[*] multiIntValues 14 | Boolean booleanValue 15 | Boolean[*] multiBooleanValues 16 | TestKind kind 17 | TestKind[*] multiKinds 18 | Long longValue 19 | Long[*] multiLongValues 20 | 21 | refers TestB oneB 22 | refers TestB[*] manyBs 23 | contains TestB containB 24 | contains TestB[*] containBs 25 | } 26 | 27 | class TestB extends TestA {} 28 | 29 | enum TestKind { 30 | one = 0, 31 | two as "Two" = 1, 32 | three as "Three-is-Three" = 2 33 | } --------------------------------------------------------------------------------