=UTF-8
3 | encoding/plugin=UTF-8
4 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
3 | org.eclipse.jdt.core.compiler.compliance=1.5
4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
7 | org.eclipse.jdt.core.compiler.release=disabled
8 | org.eclipse.jdt.core.compiler.source=1.5
9 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 | pkg : grunt.file.readJSON("package.json"),
5 | concat : {
6 | js : {
7 | files : {
8 | "output/bimserverapi-%VERSION%.js" : [ "bimserverapipromise.js", "bimserverapiwebsocket.js", "geometry.js", "ifc4.js", "ifc2x3tc1.js", "model.js", "translations_en.js", "bimserverclient.js" ]
9 | },
10 | }
11 | },
12 | uglify : {
13 | dist : {
14 | files : {
15 | "output/bimserverapi-%VERSION%.min.js" : [ "output/bimserverapi-%VERSION%.js" ]
16 | }
17 | }
18 | },
19 | copy : {
20 | main : {
21 | files : [{
22 | expand : true,
23 | src : [ "plugin/*" ],
24 | dest : "output/"
25 | }]
26 | }
27 | },
28 | zip: {
29 | "output/bimserverapi-source-%VERSION%.zip": ["bimserverapipromise.js", "bimserverapiwebsocket.js", "geometry.js", "ifc4.js", "ifc2x3tc1.js", "model.js", "translations_en.js", "bimserverclient.js"]
30 | }
31 | });
32 |
33 | grunt.loadNpmTasks("grunt-contrib-concat");
34 | grunt.loadNpmTasks("grunt-contrib-uglify");
35 | grunt.loadNpmTasks("grunt-zip");
36 |
37 | grunt.registerTask("default", [ "concat", "uglify"]);
38 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BIMserver-JavaScript-API
2 |
3 | A JavaScript API for the OpenSource BIMserver.
4 |
5 | ## Usage
6 | ### Static import
7 | Download the [combined minified library](https://raw.githubusercontent.com/opensourceBIM/BIMserver-JavaScript-API/master/build/bimserverapi.js) and include it in your HTML.
8 |
9 | ```html
10 |
11 | ```
12 |
13 | The ``?_v=%VERSION%`` addition is there for efficient caching purposes. Any server system serving these files can tell the client to cache these files indefinitely.
14 |
15 | ### Import as an ES6 module
16 | If you are using a transpiler such as [Typescript](https://www.typescriptlang.org/) or [Babel](http://babeljs.io/), or a bundler such as [Webpack](https://webpack.js.org/) or [Rollup](https://rollupjs.org/), you can import the module using the [Import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) syntax.
17 |
18 | It is also possible to load the ES6 module directly into the browser, however not all browser support this yet.
19 |
20 | ```javascript
21 | import { BimServerClient } from './js/bimserverclient.js';
22 | const api = new BimServerClient("../..");
23 | api.init((client, version) => {
24 | console.log(version.version);
25 | });
26 | ```
27 |
28 | ### Dynamic import
29 | When the location on the API is not known in advance, you can use dynamic loading, in most browsers you'll need to use a "dev" version for this to work (Chrome 64 for example).
30 |
31 | ```javascript
32 | var address = "http://addressofapi";
33 | Promise.all([
34 | address + "/bimserverclient.js",
35 | address + "/bimserverapipromise.js"
36 | ].map(x => import(x)))
37 | .then(([BimServerClient, BimServerApiPromise]) => {
38 | var api = new BimServerClient.BimServerClient("../..");
39 | api.init((client, version) => {
40 | document.getElementById("version").innerHTML = JSON.stringify(version.version, 0, 2);
41 | });
42 | });
43 | ```
44 |
45 | ### Version returned from BIMserver instance
46 | To do.
47 |
48 | ## API documentation
49 | To do.
50 |
51 | ## Build the library
52 | * Install [Node.js](https://nodejs.org/)
53 | * Clone (or download and unzip) the project to your file system:
54 | ```
55 | git clone https://github.com/opensourceBIM/BIMserver-JavaScript-API.git
56 | ```
57 | * Go to the project directory
58 | ```
59 | cd BIMserver-JavaScript-API
60 | ```
61 | * Install build dependencies
62 | ```
63 | npm install
64 | ```
65 | * Run the build script
66 | ```
67 | npm run build
68 | ```
69 | The compiled file is located at ``build/bimserverapi.js``
70 |
--------------------------------------------------------------------------------
/bimserverapipromise.js:
--------------------------------------------------------------------------------
1 | export class BimServerApiPromise {
2 | constructor(counter = null) {
3 | this.isDone = false;
4 | this.chains = [];
5 | this.callback = null;
6 | this.counter = counter;
7 | }
8 |
9 | done(callback) {
10 | if (this.isDone) {
11 | callback();
12 | } else {
13 | if (this.callback != null) {
14 | if (this.callback instanceof Array) {
15 | this.callback.push(callback);
16 | } else {
17 | this.callback = [this.callback, callback];
18 | }
19 | } else {
20 | this.callback = callback;
21 | }
22 | }
23 | return this;
24 | }
25 |
26 | inc() {
27 | if (this.counter == null) {
28 | this.counter = 0;
29 | }
30 | this.counter++;
31 | }
32 |
33 | dec() {
34 | if (this.counter == null) {
35 | this.counter = 0;
36 | }
37 | this.counter--;
38 | if (this.counter === 0) {
39 | this.done = true;
40 | this.fire();
41 | }
42 | }
43 |
44 | fire() {
45 | if (this.isDone) {
46 | console.log("Promise already fired, not triggering again...");
47 | return;
48 | }
49 | this.isDone = true;
50 | if (this.callback != null) {
51 | if (this.callback instanceof Array) {
52 | this.callback.forEach((cb) => {
53 | cb();
54 | });
55 | } else {
56 | this.callback();
57 | }
58 | }
59 | }
60 |
61 | chain(otherPromise) {
62 | let promises;
63 | if (otherPromise instanceof Array) {
64 | promises = otherPromise;
65 | } else {
66 | promises = [otherPromise];
67 | }
68 | promises.forEach((promise) => {
69 | if (!promise.isDone) {
70 | this.chains.push(promise);
71 | promise.done(() => {
72 | for (let i = this.chains.length - 1; i >= 0; i--) {
73 | if (this.chains[i] == promise) {
74 | this.chains.splice(i, 1);
75 | }
76 | }
77 | if (this.chains.length === 0) {
78 | this.fire();
79 | }
80 | });
81 | }
82 | });
83 | if (this.chains.length === 0) {
84 | this.fire();
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/bimserverapiwebsocket.js:
--------------------------------------------------------------------------------
1 | export class BimServerApiWebSocket {
2 | constructor(baseUrl, bimServerApi) {
3 | this.connected = false;
4 | this.openCallbacks = [];
5 | this.endPointId = null;
6 | this.listener = null;
7 | this.tosend = [];
8 | this.tosendAfterConnect = [];
9 | this.messagesReceived = 0;
10 | this.intervalId = null;
11 | this.baseUrl = baseUrl;
12 | this.bimServerApi = bimServerApi;
13 | }
14 |
15 | connect(callback = null) {
16 | if (this.connected) {
17 | if (callback != null) {
18 | callback();
19 | }
20 | return Promise.resolve();
21 | }
22 | console.info("Connecting websocket");
23 | var promise = new Promise((resolve, reject) => {
24 | this.openCallbacks.push(() => {
25 | resolve();
26 | });
27 | if (callback != null) {
28 | if (typeof callback === "function") {
29 | this.openCallbacks.push(callback);
30 | } else {
31 | console.error("Callback was not a function", callback);
32 | }
33 | }
34 |
35 | // Concatenate in case of relative URL
36 | let hostname = this.bimServerApi.baseUrl.toString();
37 | if (!hostname.startsWith("http:") && !hostname.startsWith("https:")) {
38 | if (hostname.startsWith('//')) {
39 | hostname = window.location.protocol + hostname;
40 | } else if (hostname.startsWith('/')) {
41 | hostname = window.location.origin + hostname;
42 | } else {
43 | hostname = window.location.href + hostname;
44 | }
45 | }
46 |
47 | const location = hostname.replace('http://', 'ws://').replace('https://', 'wss://') + "/stream";
48 |
49 | try {
50 | this._ws = new WebSocket(location);
51 | this._ws.binaryType = "arraybuffer";
52 | this._ws.onopen = this._onopen.bind(this);
53 | this._ws.onmessage = this._onmessage.bind(this);
54 | this._ws.onclose = this._onclose.bind(this);
55 | this._ws.onerror = this._onerror.bind(this);
56 | } catch (err) {
57 | console.error(err);
58 | this.bimServerApi.notifier.setError("WebSocket error" + (err.message !== undefined ? (": " + err.message) : ""));
59 | }
60 | });
61 | return promise;
62 | }
63 |
64 | _onerror(err) {
65 | console.log(err);
66 | this.bimServerApi.notifier.setError("WebSocket error" + (err.message !== undefined ? (": " + err.message) : ""));
67 | }
68 |
69 | _onopen() {
70 | this.intervalId = setInterval(() => {
71 | this.send({"hb": true});
72 | }, 30 * 1000); // Send hb every 30 seconds
73 | while (this.tosendAfterConnect.length > 0 && this._ws.readyState == 1) {
74 | const messageArray = this.tosendAfterConnect.splice(0, 1);
75 | this._sendWithoutEndPoint(messageArray[0]);
76 | }
77 | }
78 |
79 | _sendWithoutEndPoint(message) {
80 | if (this._ws && this._ws.readyState == 1) {
81 | this._ws.send(message);
82 | } else {
83 | this.tosendAfterConnect.push(message);
84 | }
85 | }
86 |
87 | _send(message) {
88 | if (this._ws && this._ws.readyState == 1 && this.endPointId != null) {
89 | this._ws.send(message);
90 | } else {
91 | console.log("Waiting", message);
92 | this.tosend.push(message);
93 | }
94 | }
95 |
96 | send(object) {
97 | const str = JSON.stringify(object);
98 | this.bimServerApi.log("Sending", str);
99 | this._send(str);
100 | }
101 |
102 | _onmessage(message) {
103 | this.messagesReceived++;
104 | if (this.messagesReceived % 10 === 0) {
105 | // console.log(this.messagesReceived);
106 | }
107 | if (message.data instanceof ArrayBuffer) {
108 | this.listener(message.data);
109 | } else {
110 | const incomingMessage = JSON.parse(message.data);
111 | if (incomingMessage.id != null) {
112 | var id = incomingMessage.id;
113 | if (this.bimServerApi.websocketCalls.has(id)) {
114 | var fn = this.bimServerApi.websocketCalls.get(id);
115 | fn(incomingMessage);
116 | this.bimServerApi.websocketCalls.delete(id);
117 | }
118 | } else {
119 | this.bimServerApi.log("incoming", incomingMessage);
120 | if (incomingMessage.welcome !== undefined) {
121 | this._sendWithoutEndPoint(JSON.stringify({"token": this.bimServerApi.token}));
122 | } else if (incomingMessage.endpointid !== undefined) {
123 | this.endPointId = incomingMessage.endpointid;
124 | this.connected = true;
125 | this.openCallbacks.forEach((callback) => {
126 | callback();
127 | });
128 | while (this.tosend.length > 0 && this._ws.readyState == 1) {
129 | const messageArray = this.tosend.splice(0, 1);
130 | console.log(messageArray[0]);
131 | this._send(messageArray[0]);
132 | }
133 | this.openCallbacks = [];
134 | } else {
135 | if (incomingMessage.request !== undefined) {
136 | this.listener(incomingMessage.request);
137 | } else if (incomingMessage.requests !== undefined) {
138 | incomingMessage.requests.forEach((request) => {
139 | this.listener(request);
140 | });
141 | }
142 | }
143 | }
144 | }
145 | }
146 |
147 | _onclose(m) {
148 | console.log("WebSocket closed", m);
149 | clearInterval(this.intervalId);
150 | this._ws = null;
151 | this.connected = false;
152 | this.openCallbacks = [];
153 | this.endpointid = null;
154 | }
155 | }
--------------------------------------------------------------------------------
/bimserverclient.js:
--------------------------------------------------------------------------------
1 | import {BimServerApiPromise} from './bimserverapipromise.js';
2 | import {BimServerApiWebSocket} from './bimserverapiwebsocket.js';
3 | import {geometry} from './geometry.js';
4 | import {ifc2x3tc1} from './ifc2x3tc1.js';
5 | import {ifc4} from './ifc4.js';
6 | import {Model} from './model.js';
7 | import {translations} from './translations_en.js';
8 |
9 | //export { default as BimServerApiPromise } from './bimserverapipromise.js';
10 | //export { default as BimServerApiWebSocket } from './bimserverapiwebsocket.js';
11 | //export { default as Model } from './model.js';
12 |
13 | //import {XMLHttpRequest from 'xhr2';
14 |
15 | // Where does this come frome? The API crashes on the absence of this
16 | // member function?
17 | String.prototype.firstUpper = function () {
18 | return this.charAt(0).toUpperCase() + this.slice(1);
19 | };
20 |
21 | export class BimServerClient {
22 | constructor(baseUrl, notifier = null, translate = null) {
23 | this.interfaceMapping = {
24 | "ServiceInterface": "org.bimserver.ServiceInterface",
25 | "NewServicesInterface": "org.bimserver.NewServicesInterface",
26 | "AuthInterface": "org.bimserver.AuthInterface",
27 | "OAuthInterface": "org.bimserver.OAuthInterface",
28 | "SettingsInterface": "org.bimserver.SettingsInterface",
29 | "AdminInterface": "org.bimserver.AdminInterface",
30 | "PluginInterface": "org.bimserver.PluginInterface",
31 | "MetaInterface": "org.bimserver.MetaInterface",
32 | "LowLevelInterface": "org.bimserver.LowLevelInterface",
33 | "NotificationRegistryInterface": "org.bimserver.NotificationRegistryInterface",
34 | };
35 |
36 | // translate function override
37 | this.translateOverride = translate;
38 |
39 | // Current BIMserver token
40 | this.token = null;
41 |
42 | // Base URL of the BIMserver
43 | this.baseUrl = baseUrl;
44 | if (this.baseUrl.substring(this.baseUrl.length - 1) == "/") {
45 | this.baseUrl = this.baseUrl.substring(0, this.baseUrl.length - 1);
46 | }
47 |
48 | // JSON endpoint on BIMserver
49 | this.address = this.baseUrl + "/json";
50 |
51 | // Notifier, default implementation does nothing
52 | this.notifier = notifier;
53 | if (this.notifier == null) {
54 | this.notifier = {
55 | setInfo: function (message) {
56 | console.log("[default]", message);
57 | },
58 | setSuccess: function () {},
59 | setError: function () {},
60 | resetStatus: function () {},
61 | resetStatusQuick: function () {},
62 | clear: function () {}
63 | };
64 | }
65 |
66 | // ID -> Resolve method
67 | this.websocketCalls = new Map();
68 |
69 | // The websocket client
70 | this.webSocket = new BimServerApiWebSocket(baseUrl, this);
71 | this.webSocket.listener = this.processNotification.bind(this);
72 |
73 | // Cached user object
74 | this.user = null;
75 |
76 | // Keeps track of the unique ID's required to handle websocket calls that return something
77 | this.idCounter = 0;
78 |
79 | this.listeners = {};
80 |
81 | // this.autoLoginTried = false;
82 |
83 | // Cache for serializers, PluginClassName(String) -> Serializer
84 | this.serializersByPluginClassName = [];
85 |
86 | // Whether debugging is enabled, just a lot more logging
87 | this.debug = false;
88 |
89 | // Mapping from ChannelId -> Listener (function)
90 | this.binaryDataListener = {};
91 |
92 | // This mapping keeps track of the prototype objects per class, will be lazily popuplated by the getClass method
93 | this.classes = {};
94 |
95 | // Schema name (String) -> Schema
96 | this.schemas = {};
97 | }
98 |
99 | init(callback) {
100 | var promise = new Promise((resolve, reject) => {
101 | this.call("AdminInterface", "getServerInfo", {}, (serverInfo) => {
102 | this.version = serverInfo.version;
103 | //const versionString = this.version.major + "." + this.version.minor + "." + this.version.revision;
104 |
105 | this.schemas.geometry = geometry.classes;
106 | this.addSubtypesToSchema(this.schemas.geometry);
107 |
108 | this.schemas.ifc2x3tc1 = ifc2x3tc1.classes;
109 | this.addSubtypesToSchema(this.schemas.ifc2x3tc1);
110 |
111 | this.schemas.ifc4 = ifc4.classes;
112 | this.addSubtypesToSchema(this.schemas.ifc4);
113 |
114 | if (callback != null) {
115 | callback(this, serverInfo);
116 | }
117 | resolve(serverInfo);
118 | }, (error) => { reject(error); });
119 | });
120 | return promise;
121 | }
122 |
123 | addSubtypesToSchema(classes) {
124 | for (let typeName in classes) {
125 | const type = classes[typeName];
126 | if (type.superclasses != null) {
127 | type.superclasses.forEach((superClass) => {
128 | let directSubClasses = classes[superClass].directSubClasses;
129 | if (directSubClasses == null) {
130 | directSubClasses = [];
131 | classes[superClass].directSubClasses = directSubClasses;
132 | }
133 | directSubClasses.push(typeName);
134 | });
135 | }
136 | }
137 | }
138 |
139 | getAllSubTypes(schema, typeName, callback) {
140 | const type = schema[typeName];
141 | if (type.directSubClasses != null) {
142 | type.directSubClasses.forEach((subTypeName) => {
143 | callback(subTypeName);
144 | this.getAllSubTypes(schema, subTypeName, callback);
145 | });
146 | }
147 | }
148 |
149 | log(message, message2) {
150 | if (this.debug) {
151 | console.log(message, message2);
152 | }
153 | }
154 |
155 | translate(key) {
156 | if (this.translateOverride !== null) {
157 | return this.translateOverride(key);
158 | }
159 | key = key.toUpperCase();
160 | if (translations != null) {
161 | const translated = translations[key];
162 | if (translated == null) {
163 | console.warn("translation for " + key + " not found, using key");
164 | return key;
165 | }
166 | return translated;
167 | }
168 | this.error("no translations");
169 | return key;
170 | }
171 |
172 | login(username, password, callback, errorCallback, options) {
173 | if (options == null) {
174 | options = {};
175 | }
176 | const request = {
177 | username: username,
178 | password: password
179 | };
180 | this.call("AuthInterface", "login", request, (data) => {
181 | this.token = data;
182 | if (options.done !== false) {
183 | this.notifier.setInfo(this.translate("LOGIN_DONE"), 2000);
184 | }
185 | this.resolveUser(callback);
186 | }, errorCallback, options.busy === false ? false : true, options.done === false ? false : true, options.error === false ? false : true);
187 | }
188 |
189 | downloadViaWebsocket(msg) {
190 | msg.action = "download";
191 | msg.token = this.token;
192 | this.webSocket.send(msg);
193 | }
194 |
195 | setBinaryDataListener(topicId, listener) {
196 | this.binaryDataListener[topicId] = listener;
197 | }
198 |
199 | clearBinaryDataListener(topicId) {
200 | delete this.binaryDataListener[topicId];
201 | }
202 |
203 | processNotification(message) {
204 | if (message instanceof ArrayBuffer) {
205 | if (message == null || message.byteLength == 0) {
206 | return;
207 | }
208 | const view = new DataView(message, 0, 8);
209 | const topicId = view.getUint32(0, true) + 0x100000000 * view.getUint32(4, true); // TopicId's are of type long (64 bit)
210 | const listener = this.binaryDataListener[topicId];
211 | if (listener != null) {
212 | listener(message);
213 | } else {
214 | console.error("No listener for topicId", topicId, message);
215 | }
216 | } else {
217 | const intf = message["interface"];
218 | if (this.listeners[intf] != null) {
219 | if (this.listeners[intf][message.method] != null) {
220 | let ar = null;
221 | this.listeners[intf][message.method].forEach((listener) => {
222 | if (ar == null) {
223 | // Only parse the arguments once, or when there are no listeners, not even once
224 | ar = [];
225 | let i = 0;
226 | for (let key in message.parameters) {
227 | ar[i++] = message.parameters[key];
228 | }
229 | }
230 | listener.apply(null, ar);
231 | });
232 | } else {
233 | console.log("No listeners on interface " + intf + " for method " + message.method);
234 | }
235 | } else {
236 | console.log("No listeners for interface " + intf);
237 | }
238 | }
239 | }
240 |
241 | resolveUser(callback) {
242 | this.call("AuthInterface", "getLoggedInUser", {}, (data) => {
243 | this.user = data;
244 | if (callback != null) {
245 | callback(this.user);
246 | }
247 | });
248 | }
249 |
250 | logout(callback) {
251 | this.call("AuthInterface", "logout", {}, () => {
252 | this.notifier.setInfo(this.translate("LOGOUT_DONE"));
253 | callback();
254 | });
255 | }
256 |
257 | generateRevisionDownloadUrl(settings) {
258 | return this.baseUrl + "/download?token=" + this.token + (settings.zip ? "&zip=on" : "") + "&topicId=" + settings.topicId;
259 | }
260 |
261 | generateExtendedDataDownloadUrl(edid) {
262 | return this.baseUrl + "/download?token=" + this.token + "&action=extendeddata&edid=" + edid;
263 | }
264 |
265 | getJsonSerializer(callback) {
266 | this.getSerializerByPluginClassName("org.bimserver.serializers.JsonSerializerPlugin").then((serializer) => {
267 | callback(serializer);
268 | });
269 | }
270 |
271 | getJsonStreamingSerializer(callback) {
272 | this.getSerializerByPluginClassName("org.bimserver.serializers.JsonStreamingSerializerPlugin").then((serializer) => {
273 | callback(serializer);
274 | });
275 | }
276 |
277 | getMinimalJsonStreamingSerializer(callback) {
278 | this.getSerializerByPluginClassName("org.bimserver.serializers.MinimalJsonStreamingSerializerPlugin").then((serializer) => {
279 | callback(serializer);
280 | });
281 | }
282 |
283 | getSerializerByPluginClassName(pluginClassName) {
284 | if (this.serializersByPluginClassName[pluginClassName] != null) {
285 | return this.serializersByPluginClassName[pluginClassName];
286 | } else {
287 | var promise = new Promise((resolve, reject) => {
288 | this.call("PluginInterface", "getSerializerByPluginClassName", {
289 | pluginClassName: pluginClassName
290 | }, (serializer) => {
291 | resolve(serializer);
292 | });
293 | });
294 |
295 | this.serializersByPluginClassName[pluginClassName] = promise;
296 |
297 | return promise;
298 | }
299 | }
300 |
301 | getMessagingSerializerByPluginClassName(pluginClassName, callback) {
302 | if (this.serializersByPluginClassName[pluginClassName] == null) {
303 | this.call("PluginInterface", "getMessagingSerializerByPluginClassName", {
304 | pluginClassName: pluginClassName
305 | }, (serializer) => {
306 | this.serializersByPluginClassName[pluginClassName] = serializer;
307 | callback(serializer);
308 | });
309 | } else {
310 | callback(this.serializersByPluginClassName[pluginClassName]);
311 | }
312 | }
313 |
314 | register(interfaceName, methodName, callback, registerCallback) {
315 | if (callback == null) {
316 | throw "Cannot register null callback";
317 | }
318 | if (this.listeners[interfaceName] == null) {
319 | this.listeners[interfaceName] = {};
320 | }
321 | if (this.listeners[interfaceName][methodName] == null) {
322 | this.listeners[interfaceName][methodName] = new Set();
323 | }
324 | this.listeners[interfaceName][methodName].add(callback);
325 | if (registerCallback != null) {
326 | registerCallback();
327 | }
328 | }
329 |
330 | registerNewRevisionOnSpecificProjectHandler(poid, handler, callback) {
331 | this.register("NotificationInterface", "newRevision", handler, () => {
332 | this.call("NotificationRegistryInterface", "registerNewRevisionOnSpecificProjectHandler", {
333 | endPointId: this.webSocket.endPointId,
334 | poid: poid
335 | }, () => {
336 | if (callback != null) {
337 | callback();
338 | }
339 | });
340 | });
341 | }
342 |
343 | registerNewExtendedDataOnRevisionHandler(roid, handler, callback) {
344 | this.register("NotificationInterface", "newExtendedData", handler, () => {
345 | this.call("NotificationRegistryInterface", "registerNewExtendedDataOnRevisionHandler", {
346 | endPointId: this.webSocket.endPointId,
347 | roid: roid
348 | }, () => {
349 | if (callback != null) {
350 | callback();
351 | }
352 | });
353 | });
354 | }
355 |
356 | registerNewUserHandler(handler, callback) {
357 | this.register("NotificationInterface", "newUser", handler, () => {
358 | this.call("NotificationRegistryInterface", "registerNewUserHandler", {
359 | endPointId: this.webSocket.endPointId
360 | }, () => {
361 | if (callback != null) {
362 | callback();
363 | }
364 | });
365 | });
366 | }
367 |
368 | unregisterNewUserHandler(handler, callback) {
369 | this.unregister(handler);
370 | this.call("NotificationRegistryInterface", "unregisterNewUserHandler", {
371 | endPointId: this.webSocket.endPointId
372 | }, () => {
373 | if (callback != null) {
374 | callback();
375 | }
376 | });
377 | }
378 |
379 | unregisterChangeProgressProjectHandler(poid, newHandler, closedHandler, callback) {
380 | this.unregister(newHandler);
381 | this.unregister(closedHandler);
382 | this.call("NotificationRegistryInterface", "unregisterChangeProgressOnProject", {
383 | poid: poid,
384 | endPointId: this.webSocket.endPointId
385 | }, callback);
386 | }
387 |
388 | registerChangeProgressProjectHandler(poid, newHandler, closedHandler, callback) {
389 | this.register("NotificationInterface", "newProgressOnProjectTopic", newHandler, () => {
390 | this.register("NotificationInterface", "closedProgressOnProjectTopic", closedHandler, () => {
391 | this.call("NotificationRegistryInterface", "registerChangeProgressOnProject", {
392 | poid: poid,
393 | endPointId: this.webSocket.endPointId
394 | }, () => {
395 | if (callback != null) {
396 | callback();
397 | }
398 | });
399 | });
400 | });
401 | }
402 |
403 | unregisterChangeProgressServerHandler(newHandler, closedHandler, callback) {
404 | this.unregister(newHandler);
405 | this.unregister(closedHandler);
406 | if (this.webSocket.endPointId != null) {
407 | this.call("NotificationRegistryInterface", "unregisterChangeProgressOnServer", {
408 | endPointId: this.webSocket.endPointId
409 | }, callback);
410 | }
411 | }
412 |
413 | registerChangeProgressServerHandler(newHandler, closedHandler, callback) {
414 | this.register("NotificationInterface", "newProgressOnServerTopic", newHandler, () => {
415 | this.register("NotificationInterface", "closedProgressOnServerTopic", closedHandler, () => {
416 | this.call("NotificationRegistryInterface", "registerChangeProgressOnServer", {
417 | endPointId: this.webSocket.endPointId
418 | }, () => {
419 | if (callback != null) {
420 | callback();
421 | }
422 | });
423 | });
424 | });
425 | }
426 |
427 | unregisterChangeProgressRevisionHandler(roid, newHandler, closedHandler, callback) {
428 | this.unregister(newHandler);
429 | this.unregister(closedHandler);
430 | this.call("NotificationRegistryInterface", "unregisterChangeProgressOnProject", {
431 | roid: roid,
432 | endPointId: this.webSocket.endPointId
433 | }, callback);
434 | }
435 |
436 | registerChangeProgressRevisionHandler(poid, roid, newHandler, closedHandler, callback) {
437 | this.register("NotificationInterface", "newProgressOnRevisionTopic", newHandler, () => {
438 | this.register("NotificationInterface", "closedProgressOnRevisionTopic", closedHandler, () => {
439 | this.call("NotificationRegistryInterface", "registerChangeProgressOnRevision", {
440 | poid: poid,
441 | roid: roid,
442 | endPointId: this.webSocket.endPointId
443 | }, () => {
444 | if (callback != null) {
445 | callback();
446 | }
447 | });
448 | });
449 | });
450 | }
451 |
452 | registerNewProjectHandler(handler, callback) {
453 | this.register("NotificationInterface", "newProject", handler, () => {
454 | this.call("NotificationRegistryInterface", "registerNewProjectHandler", {
455 | endPointId: this.webSocket.endPointId
456 | }, () => {
457 | if (callback != null) {
458 | callback();
459 | }
460 | });
461 | });
462 | }
463 |
464 | unregisterNewProjectHandler(handler, callback) {
465 | this.unregister(handler);
466 | if (this.webSocket.endPointId != null) {
467 | this.call("NotificationRegistryInterface", "unregisterNewProjectHandler", {
468 | endPointId: this.webSocket.endPointId
469 | }, () => {
470 | if (callback != null) {
471 | callback();
472 | }
473 | }, () => {
474 | // Discard
475 | });
476 | }
477 | }
478 |
479 | unregisterNewRevisionOnSpecificProjectHandler(poid, handler, callback) {
480 | this.unregister(handler);
481 | this.call("NotificationRegistryInterface", "unregisterNewRevisionOnSpecificProjectHandler", {
482 | endPointId: this.webSocket.endPointId,
483 | poid: poid
484 | }, () => {
485 | if (callback != null) {
486 | callback();
487 | }
488 | }, () => {
489 | // Discard
490 | });
491 | }
492 |
493 | unregisterNewExtendedDataOnRevisionHandler(roid, handler, callback) {
494 | this.unregister(handler);
495 | this.call("NotificationRegistryInterface", "unregisterNewExtendedDataOnRevisionHandler", {
496 | endPointId: this.webSocket.endPointId,
497 | roid: roid
498 | }, () => {
499 | if (callback != null) {
500 | callback();
501 | }
502 | });
503 | }
504 |
505 | registerProgressHandler(topicId, handler, callback) {
506 | this.register("NotificationInterface", "progress", handler, () => {
507 | this.call("NotificationRegistryInterface", "registerProgressHandler", {
508 | topicId: topicId,
509 | endPointId: this.webSocket.endPointId
510 | }, () => {
511 | if (callback != null) {
512 | callback();
513 | } else {
514 | this.call("NotificationRegistryInterface", "getProgress", {
515 | topicId: topicId
516 | }, (state) => {
517 | handler(topicId, state);
518 | });
519 | }
520 | });
521 | });
522 | }
523 |
524 | unregisterProgressHandler(topicId, handler, callback) {
525 | this.unregister(handler);
526 | this.call("NotificationRegistryInterface", "unregisterProgressHandler", {
527 | topicId: topicId,
528 | endPointId: this.webSocket.endPointId
529 | }, () => {}).done(callback);
530 | }
531 |
532 | unregister(listener) {
533 | for (let i in this.listeners) {
534 | for (let j in this.listeners[i]) {
535 | const list = this.listeners[i][j];
536 | for (let k = 0; k < list.length; k++) {
537 | if (list[k] === listener) {
538 | list.splice(k, 1);
539 | return;
540 | }
541 | }
542 | }
543 | }
544 | }
545 |
546 | createRequest(interfaceName, method, data) {
547 | let object = {};
548 | object["interface"] = interfaceName;
549 | object.method = method;
550 | for (var key in data) {
551 | if (data[key] instanceof Set) {
552 | // Convert ES6 Set to an array
553 | data[key] = Array.from(data[key]);
554 | }
555 | }
556 | object.parameters = data;
557 |
558 | return object;
559 | }
560 |
561 | getJson(address, data, success, error) {
562 | const xhr = new XMLHttpRequest();
563 | xhr.open("POST", address);
564 | xhr.onerror = () => {
565 | if (error != null) {
566 | error("Unknown network error");
567 | }
568 | };
569 | xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
570 | xhr.onload = (jqXHR, textStatus, errorThrown) => {
571 | if (xhr.status === 200) {
572 | let data = "";
573 | try {
574 | data = JSON.parse(xhr.responseText);
575 | } catch (e) {
576 | if (e instanceof SyntaxError) {
577 | if (error != null) {
578 | error(e);
579 | } else {
580 | this.notifier.setError(e);
581 | console.error(e);
582 | }
583 | } else {
584 | console.error(e);
585 | }
586 | }
587 | success(data);
588 | } else {
589 | if (error != null) {
590 | error(jqXHR, textStatus, errorThrown);
591 | } else {
592 | this.notifier.setError(textStatus);
593 | console.error(jqXHR, textStatus, errorThrown);
594 | }
595 | }
596 | };
597 | xhr.send(JSON.stringify(data));
598 | }
599 |
600 | multiCall(requests, callback, errorCallback, showBusy, showDone, showError, connectWebSocket) {
601 | if (!this.webSocket.connected && this.token != null && connectWebSocket) {
602 | this.webSocket.connect().then(() => {
603 | this.multiCall(requests, callback, errorCallback, showBusy, showDone, showError);
604 | });
605 | return;
606 | }
607 | const promise = new BimServerApiPromise();
608 | let request = null;
609 | if (requests.length == 1) {
610 | request = requests[0];
611 | if (this.interfaceMapping[request[0]] == null) {
612 | this.log("Interface " + request[0] + " not found");
613 | }
614 | request = {
615 | request: this.createRequest(this.interfaceMapping[request[0]], request[1], request[2])
616 | };
617 | } else if (requests.length > 1) {
618 | let requestObjects = [];
619 | requests.forEach((request) => {
620 | if (this.interfaceMapping[request[0]] == null) {
621 | this.log("Interface " + request[0] + " not found");
622 | }
623 | requestObjects.push(this.createRequest(this.interfaceMapping[request[0]], request[1], request[2]));
624 | });
625 | request = {
626 | requests: requestObjects
627 | };
628 | } else if (requests.length === 0) {
629 | promise.fire();
630 | callback();
631 | }
632 |
633 | // this.notifier.clear();
634 |
635 | if (this.token != null) {
636 | request.token = this.token;
637 | }
638 |
639 | let key = requests[0][1];
640 | requests.forEach((item, index) => {
641 | if (index > 0) {
642 | key += "_" + item;
643 | }
644 | });
645 |
646 | let showedBusy = false;
647 | if (showBusy) {
648 | if (this.lastBusyTimeOut != null) {
649 | clearTimeout(this.lastBusyTimeOut);
650 | this.lastBusyTimeOut = null;
651 | }
652 | if (typeof window !== 'undefined' && window.setTimeout != null) {
653 | this.lastBusyTimeOut = window.setTimeout(() => {
654 | this.notifier.setInfo(this.translate(key + "_BUSY"), -1);
655 | showedBusy = true;
656 | }, 200);
657 | }
658 | }
659 |
660 | // this.notifier.resetStatusQuick();
661 |
662 | this.log("request", request);
663 |
664 | this.getJson(this.address, request, (data) => {
665 | this.log("response", data);
666 | let errorsToReport = [];
667 | if (requests.length == 1) {
668 | if (showBusy) {
669 | if (this.lastBusyTimeOut != null) {
670 | clearTimeout(this.lastBusyTimeOut);
671 | }
672 | }
673 | if (data.response.exception != null) {
674 | if (showError) {
675 | if (this.lastTimeOut != null) {
676 | clearTimeout(this.lastTimeOut);
677 | }
678 | this.notifier.setError(data.response.exception.message);
679 | } else {
680 | if (showedBusy) {
681 | this.notifier.resetStatus();
682 | }
683 | errorsToReport.push(data.response.exception);
684 | }
685 | } else {
686 | if (showDone) {
687 | this.notifier.setSuccess(this.translate(key + "_DONE"), 5000);
688 | } else {
689 | if (showedBusy) {
690 | this.notifier.resetStatus();
691 | }
692 | }
693 | }
694 | } else if (requests.length > 1) {
695 | data.responses.forEach((response) => {
696 | if (response.exception != null) {
697 | if (errorCallback == null) {
698 | this.notifier.setError(response.exception.message);
699 | } else {
700 | errorsToReport.push(response.exception);
701 | }
702 | }
703 | });
704 | }
705 | if (errorsToReport.length > 0 && errorCallback) {
706 | if (requests.length == 1) {
707 | errorCallback(errorsToReport[0]); // with one request (and one error) -> call with an object
708 | } else {
709 | errorCallback(errorsToReport); // multiple requests, sends an array of errors
710 | }
711 | } else {
712 | if (requests.length == 1) {
713 | callback(data.response);
714 | } else if (requests.length > 1) {
715 | callback(data.responses);
716 | }
717 | }
718 | promise.fire();
719 | },
720 | (jqXHR, textStatus, errorThrown) => {
721 | if (textStatus == "abort") {
722 | // ignore
723 | } else {
724 | this.log(errorThrown);
725 | this.log(textStatus);
726 | this.log(jqXHR);
727 | if (this.lastTimeOut != null) {
728 | clearTimeout(this.lastTimeOut);
729 | }
730 | this.notifier.setError(this.translate("ERROR_REMOTE_METHOD_CALL"));
731 | }
732 | if (errorCallback != null) {
733 | const result = {};
734 | result.error = textStatus;
735 | result.ok = false;
736 | errorCallback(result);
737 | }
738 | promise.fire();
739 | });
740 | return promise;
741 | }
742 |
743 | getModel(poid, roid, schema, deep, callback, name) {
744 | const model = new Model(this, poid, roid, schema);
745 | if (name != null) {
746 | model.name = name;
747 | }
748 | model.load(deep, callback);
749 | return model;
750 | }
751 |
752 | createModel(poid, callback) {
753 | const model = new Model(this, poid);
754 | model.init(callback);
755 | return model;
756 | }
757 |
758 | callWithNoIndication(interfaceName, methodName, data, callback, errorCallback) {
759 | return this.call(interfaceName, methodName, data, callback, errorCallback, false, false, false);
760 | }
761 |
762 | callWithFullIndication(interfaceName, methodName, data, callback) {
763 | return this.call(interfaceName, methodName, data, callback, null, true, true, true);
764 | }
765 |
766 | callWithUserErrorIndication(action, data, callback) {
767 | return this.call(null, null, data, callback, null, false, false, true);
768 | }
769 |
770 | callWithUserErrorAndDoneIndication(action, data, callback) {
771 | return this.call(null, null, data, callback, null, false, true, true);
772 | }
773 |
774 | isA(schema, typeSubject, typeName) {
775 | let isa = false;
776 | if (typeSubject == typeName) {
777 | return true;
778 | }
779 |
780 | let subject = this.schemas[schema][typeSubject];
781 |
782 | // TODO duplicate code (also twice in model.js)
783 | if (typeSubject === "GeometryInfo" || typeSubject === "GeometryData" || typeSubject === "Buffer") {
784 | subject = this.schemas.geometry[typeSubject];
785 | }
786 |
787 | if (subject == null) {
788 | console.log(typeSubject, "not found");
789 | }
790 | subject.superclasses.some((superclass) => {
791 | if (superclass == typeName) {
792 | isa = true;
793 | return true;
794 | }
795 | if (this.isA(schema, superclass, typeName)) {
796 | isa = true;
797 | return true;
798 | }
799 | return false;
800 | });
801 | return isa;
802 | }
803 |
804 | initiateCheckin(project, deserializerOid, callback, errorCallback) {
805 | this.callWithNoIndication("ServiceInterface", "initiateCheckin", {
806 | deserializerOid: deserializerOid,
807 | poid: project.oid
808 | }, (topicId) => {
809 | if (callback != null) {
810 | callback(topicId);
811 | }
812 | }, (error) => {
813 | errorCallback(error);
814 | });
815 | }
816 |
817 | checkin(topicId, project, comment, file, deserializerOid, progressListener, success, error) {
818 | const xhr = new XMLHttpRequest();
819 |
820 | xhr.upload.addEventListener("progress",
821 | (e) => {
822 | if (e.lengthComputable) {
823 | const percentage = Math.round((e.loaded * 100) / e.total);
824 | progressListener(percentage);
825 | }
826 | }, false);
827 |
828 | xhr.addEventListener("load", (event) => {
829 | const result = JSON.parse(xhr.response);
830 |
831 | if (result.exception == null) {
832 | if (success != null) {
833 | success(result.checkinid);
834 | }
835 | } else {
836 | if (error == null) {
837 | console.error(result.exception);
838 | } else {
839 | error(result.exception);
840 | }
841 | }
842 | }, false);
843 |
844 | xhr.open("POST", this.baseUrl + "/upload");
845 |
846 | const formData = new FormData();
847 |
848 | formData.append("token", this.token);
849 | formData.append("deserializerOid", deserializerOid);
850 | formData.append("comment", comment);
851 | formData.append("poid", project.oid);
852 | formData.append("topicId", topicId);
853 | formData.append("file", file);
854 |
855 | xhr.send(formData);
856 | }
857 |
858 | addExtendedData(roid, title, schema, data, success, error) {
859 | const reader = new FileReader();
860 | const xhr = new XMLHttpRequest();
861 |
862 | xhr.addEventListener("load", (e) => {
863 | const result = JSON.parse(xhr.response);
864 |
865 | if (result.exception == null) {
866 | this.call("ServiceInterface", "addExtendedDataToRevision", {
867 | roid: roid,
868 | extendedData: {
869 | __type: "SExtendedData",
870 | title: title,
871 | schemaId: schema.oid,
872 | fileId: result.fileId
873 | }
874 | }, () => {
875 | success(result.checkinid);
876 | });
877 | } else {
878 | error(result.exception);
879 | }
880 | }, false);
881 | xhr.open("POST", this.baseUrl + "/upload");
882 | if (typeof data == "File") {
883 | var file = data;
884 | reader.onload = () => {
885 | const formData = new FormData();
886 | formData.append("action", "file");
887 | formData.append("token", this.token);
888 |
889 | const blob = new Blob([file], {
890 | type: schema.contentType
891 | });
892 |
893 | formData.append("file", blob, file.name);
894 | xhr.send(formData);
895 | };
896 | reader.readAsBinaryString(file);
897 | } else {
898 | // Assuming data is a Blob
899 | const formData = new FormData();
900 | formData.append("action", "file");
901 | formData.append("token", this.token);
902 | formData.append("file", data, data.name);
903 | xhr.send(formData);
904 | }
905 | }
906 |
907 | setToken(token, callback, errorCallback) {
908 | this.token = token;
909 | this.call("AuthInterface", "getLoggedInUser", {}, (data) => {
910 | this.user = data;
911 | this.webSocket.connect(callback);
912 | }, () => {
913 | this.token = null;
914 | if (errorCallback != null) {
915 | errorCallback();
916 | }
917 | }, true, false, true, false);
918 | }
919 |
920 | callWithWebsocket(interfaceName, methodName, data) {
921 | var promise = new Promise((resolve, reject) => {
922 | var id = this.idCounter++;
923 | this.websocketCalls.set(id, (response) => {
924 | resolve(response.response.result);
925 | });
926 | var request = {
927 | id: id,
928 | request: {
929 | interface: interfaceName,
930 | method: methodName,
931 | parameters: data
932 | }
933 | };
934 | if (this.token != null) {
935 | request.token = this.token;
936 | }
937 | this.webSocket.send(request);
938 | });
939 | return promise;
940 | }
941 |
942 | /**
943 | * Call a single method, this method delegates to the multiCall method
944 | * @param {string} interfaceName - Interface name, e.g. "ServiceInterface"
945 | * @param {string} methodName - Methodname, e.g. "addProject"
946 | * @param {Object} data - Object with a field per arument
947 | * @param {Function} callback - Function to callback, first argument in callback will be the returned object
948 | * @param {Function} errorCallback - Function to callback on error
949 | * @param {boolean} showBusy - Whether to show busy indication
950 | * @param {boolean} showDone - Whether to show done indication
951 | * @param {boolean} showError - Whether to show errors
952 | *
953 | */
954 | call(interfaceName, methodName, data, callback, errorCallback, showBusy = true, showDone = false, showError = true, connectWebSocket = true) {
955 | return this.multiCall([
956 | [
957 | interfaceName,
958 | methodName,
959 | data
960 | ]
961 | ], (data) => {
962 | if (data.exception == null) {
963 | if (callback != null) {
964 | callback(data.result);
965 | }
966 | } else {
967 | if (errorCallback != null) {
968 | errorCallback(data.exception);
969 | }
970 | }
971 | }, errorCallback, showBusy, showDone, showError, connectWebSocket);
972 | }
973 | }
974 |
--------------------------------------------------------------------------------
/geometry.js:
--------------------------------------------------------------------------------
1 | export const geometry = {
2 | "classes" : {
3 | "GeometryInfo" : {
4 | "domain" : "geometry",
5 | "superclasses" : [ ],
6 | "fields" : {
7 | "bounds" : {
8 | "type" : "Bounds",
9 | "reference" : true,
10 | "many" : false,
11 | "inverse" : false
12 | },
13 | "boundsUntransformed" : {
14 | "type" : "Bounds",
15 | "reference" : true,
16 | "many" : false,
17 | "inverse" : false
18 | },
19 | "startVertex" : {
20 | "type" : "int",
21 | "reference" : false,
22 | "many" : false,
23 | "inverse" : false
24 | },
25 | "startIndex" : {
26 | "type" : "int",
27 | "reference" : false,
28 | "many" : false,
29 | "inverse" : false
30 | },
31 | "primitiveCount" : {
32 | "type" : "int",
33 | "reference" : false,
34 | "many" : false,
35 | "inverse" : false
36 | },
37 | "transformation" : {
38 | "type" : "bytearray",
39 | "reference" : false,
40 | "many" : false,
41 | "inverse" : false
42 | },
43 | "data" : {
44 | "type" : "GeometryData",
45 | "reference" : true,
46 | "many" : false,
47 | "inverse" : false
48 | },
49 | "area" : {
50 | "type" : "double",
51 | "reference" : false,
52 | "many" : false,
53 | "inverse" : false
54 | },
55 | "volume" : {
56 | "type" : "double",
57 | "reference" : false,
58 | "many" : false,
59 | "inverse" : false
60 | },
61 | "hasTransparency" : {
62 | "type" : "boolean",
63 | "reference" : false,
64 | "many" : false,
65 | "inverse" : false
66 | },
67 | "ifcProductOid" : {
68 | "type" : "long",
69 | "reference" : false,
70 | "many" : false,
71 | "inverse" : false
72 | },
73 | "ifcProductUuid" : {
74 | "type" : "bytearray",
75 | "reference" : false,
76 | "many" : false,
77 | "inverse" : false
78 | },
79 | "ifcProductRid" : {
80 | "type" : "int",
81 | "reference" : false,
82 | "many" : false,
83 | "inverse" : false
84 | },
85 | "density" : {
86 | "type" : "EFloat",
87 | "reference" : false,
88 | "many" : false,
89 | "inverse" : false
90 | },
91 | "boundsMm" : {
92 | "type" : "Bounds",
93 | "reference" : true,
94 | "many" : false,
95 | "inverse" : false
96 | },
97 | "boundsUntransformedMm" : {
98 | "type" : "Bounds",
99 | "reference" : true,
100 | "many" : false,
101 | "inverse" : false
102 | },
103 | "additionalData" : {
104 | "type" : "string",
105 | "reference" : false,
106 | "many" : false,
107 | "inverse" : false
108 | },
109 | "nrColors" : {
110 | "type" : "int",
111 | "reference" : false,
112 | "many" : false,
113 | "inverse" : false
114 | },
115 | "nrVertices" : {
116 | "type" : "int",
117 | "reference" : false,
118 | "many" : false,
119 | "inverse" : false
120 | },
121 | "ifcProductPid" : {
122 | "type" : "int",
123 | "reference" : false,
124 | "many" : false,
125 | "inverse" : false
126 | }
127 | }
128 | },
129 | "Vector3f" : {
130 | "domain" : "geometry",
131 | "superclasses" : [ ],
132 | "fields" : {
133 | "x" : {
134 | "type" : "double",
135 | "reference" : false,
136 | "many" : false,
137 | "inverse" : false
138 | },
139 | "y" : {
140 | "type" : "double",
141 | "reference" : false,
142 | "many" : false,
143 | "inverse" : false
144 | },
145 | "z" : {
146 | "type" : "double",
147 | "reference" : false,
148 | "many" : false,
149 | "inverse" : false
150 | }
151 | }
152 | },
153 | "Bounds" : {
154 | "domain" : "geometry",
155 | "superclasses" : [ ],
156 | "fields" : {
157 | "min" : {
158 | "type" : "Vector3f",
159 | "reference" : true,
160 | "many" : false,
161 | "inverse" : false
162 | },
163 | "max" : {
164 | "type" : "Vector3f",
165 | "reference" : true,
166 | "many" : false,
167 | "inverse" : false
168 | }
169 | }
170 | },
171 | "Buffer" : {
172 | "domain" : "geometry",
173 | "superclasses" : [ ],
174 | "fields" : {
175 | "data" : {
176 | "type" : "bytearray",
177 | "reference" : false,
178 | "many" : false,
179 | "inverse" : false
180 | }
181 | }
182 | },
183 | "GeometryData" : {
184 | "domain" : "geometry",
185 | "superclasses" : [ ],
186 | "fields" : {
187 | "nrIndices" : {
188 | "type" : "int",
189 | "reference" : false,
190 | "many" : false,
191 | "inverse" : false
192 | },
193 | "nrVertices" : {
194 | "type" : "int",
195 | "reference" : false,
196 | "many" : false,
197 | "inverse" : false
198 | },
199 | "nrNormals" : {
200 | "type" : "int",
201 | "reference" : false,
202 | "many" : false,
203 | "inverse" : false
204 | },
205 | "nrColors" : {
206 | "type" : "int",
207 | "reference" : false,
208 | "many" : false,
209 | "inverse" : false
210 | },
211 | "indices" : {
212 | "type" : "Buffer",
213 | "reference" : true,
214 | "many" : false,
215 | "inverse" : false
216 | },
217 | "vertices" : {
218 | "type" : "Buffer",
219 | "reference" : true,
220 | "many" : false,
221 | "inverse" : false
222 | },
223 | "verticesQuantized" : {
224 | "type" : "Buffer",
225 | "reference" : true,
226 | "many" : false,
227 | "inverse" : false
228 | },
229 | "normals" : {
230 | "type" : "Buffer",
231 | "reference" : true,
232 | "many" : false,
233 | "inverse" : false
234 | },
235 | "normalsQuantized" : {
236 | "type" : "Buffer",
237 | "reference" : true,
238 | "many" : false,
239 | "inverse" : false
240 | },
241 | "colorsQuantized" : {
242 | "type" : "Buffer",
243 | "reference" : true,
244 | "many" : false,
245 | "inverse" : false
246 | },
247 | "color" : {
248 | "type" : "Vector4f",
249 | "reference" : true,
250 | "many" : false,
251 | "inverse" : false
252 | },
253 | "hasTransparency" : {
254 | "type" : "boolean",
255 | "reference" : false,
256 | "many" : false,
257 | "inverse" : false
258 | },
259 | "reused" : {
260 | "type" : "int",
261 | "reference" : false,
262 | "many" : false,
263 | "inverse" : false
264 | },
265 | "type" : {
266 | "type" : "short",
267 | "reference" : false,
268 | "many" : false,
269 | "inverse" : false
270 | },
271 | "mostUsedColor" : {
272 | "type" : "Vector4f",
273 | "reference" : true,
274 | "many" : false,
275 | "inverse" : false
276 | },
277 | "boundsMm" : {
278 | "type" : "Bounds",
279 | "reference" : true,
280 | "many" : false,
281 | "inverse" : false
282 | },
283 | "saveableTriangles" : {
284 | "type" : "int",
285 | "reference" : false,
286 | "many" : false,
287 | "inverse" : false
288 | },
289 | "colorPack" : {
290 | "type" : "ColorPack",
291 | "reference" : true,
292 | "many" : false,
293 | "inverse" : false
294 | },
295 | "lineIndices" : {
296 | "type" : "Buffer",
297 | "reference" : true,
298 | "many" : false,
299 | "inverse" : false
300 | },
301 | "nrLineIndices" : {
302 | "type" : "int",
303 | "reference" : false,
304 | "many" : false,
305 | "inverse" : false
306 | }
307 | }
308 | },
309 | "Vector4f" : {
310 | "domain" : "geometry",
311 | "superclasses" : [ ],
312 | "fields" : {
313 | "x" : {
314 | "type" : "EFloat",
315 | "reference" : false,
316 | "many" : false,
317 | "inverse" : false
318 | },
319 | "y" : {
320 | "type" : "EFloat",
321 | "reference" : false,
322 | "many" : false,
323 | "inverse" : false
324 | },
325 | "z" : {
326 | "type" : "EFloat",
327 | "reference" : false,
328 | "many" : false,
329 | "inverse" : false
330 | },
331 | "w" : {
332 | "type" : "EFloat",
333 | "reference" : false,
334 | "many" : false,
335 | "inverse" : false
336 | }
337 | }
338 | },
339 | "ColorPack" : {
340 | "domain" : "geometry",
341 | "superclasses" : [ ],
342 | "fields" : {
343 | "data" : {
344 | "type" : "bytearray",
345 | "reference" : false,
346 | "many" : false,
347 | "inverse" : false
348 | }
349 | }
350 | }
351 | }
352 | };
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BIMserver JavaScript API
6 |
7 |
8 | To make it easier to interact with the OpenSource BIMserver from a web environment (like a browser or NodeJS) you can use this library.
9 | This library uses the ECMAScript6 Modules concept. Not all browsers support this yet.
10 |
11 |
12 | Caching
13 |
14 | The "?_v=%VERSION%" additions are there for efficient caching purposes. Any server system serving these files can tell the client to cache these files indefinitely.
15 |
16 |
17 | Links
18 |
27 |
28 | To include this library in your project, copy this to your <head>
29 |
30 | <script type="module" src="bimserverapipromise.js?_v=%VERSION%"></script>
31 | <script type="module" src="bimserverapiwebsocket.js?_v=%VERSION%"></script>
32 | <script type="module" src="bimserverclient.js?_v=%VERSION%"></script>
33 | <script type="module" src="ifc2x3tc1.js?_v=%VERSION%"></script>
34 | <script type="module" src="ifc4.js?_v=%VERSION%"></script>
35 | <script type="module" src="model.js?_v=%VERSION%"></script>
36 | <script type="module" src="translations_en.js?_v=%VERSION%"></script>
37 |
38 |
39 | Combined minified version (only available on a released version):
40 |
41 | bimserverapi.js?_v=%VERSION%
42 |
43 | Static import example
44 |
45 | // Import the library, all dependencies will be handled by the module system
46 | import BimServerClient from './bimserverclient.js';
47 |
48 | // Create a new API, the path given should point to the base path of a BIMserver. This can also be a full URL like "http://bimserveraddress"
49 | var api = new BimServerClient("../..");
50 | api.init((client, version) => {
51 | console.log(version.version);
52 | });
53 |
54 |
55 | Dynamic import example
56 |
57 | // When the location on the API is not known in advance, you can use dynamic loading, in most browsers you'll need to use a "dev" version for this to work (Chrome 64 for example).
58 | var address = "http://addressofapi";
59 | Promise.all([
60 | address + "/bimserverclient.js",
61 | address + "/bimserverapipromise.js"
62 | ].map(x => import(x)))
63 | .then(([BimServerClient, BimServerApiPromise]) => {
64 | var api = new BimServerClient.BimServerClient("../..");
65 | api.init((client, version) => {
66 | document.getElementById("version").innerHTML = JSON.stringify(version.version, 0, 2);
67 | });
68 | });
69 |
70 |
71 | (Live) Version returned from local BIMserver
72 |
73 |
74 |
75 |
82 |
83 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/model.js:
--------------------------------------------------------------------------------
1 | import {BimServerApiPromise} from "./bimserverapipromise.js";
2 |
3 | export class Model {
4 | constructor(bimServerApi, poid, roid, schema) {
5 | this.schema = schema;
6 | this.bimServerApi = bimServerApi;
7 | this.poid = poid;
8 | this.roid = roid;
9 | this.waiters = [];
10 |
11 | this.objects = {};
12 | this.objectsByGuid = {};
13 | this.objectsByName = {};
14 |
15 | this.oidsFetching = {};
16 | this.guidsFetching = {};
17 | this.namesFetching = {};
18 |
19 | // Those are only fully loaded types (all of them), should not be stored here if loaded partially
20 | this.loadedTypes = [];
21 | this.loadedDeep = false;
22 | this.changedObjectOids = {};
23 | this.loading = false;
24 | this.logging = true;
25 |
26 | this.changes = 0;
27 | this.changeListeners = [];
28 | }
29 |
30 | init(callback) {
31 | callback();
32 | }
33 |
34 | load(deep, modelLoadCallback) {
35 | const othis = this;
36 |
37 | if (deep) {
38 | this.loading = true;
39 | this.bimServerApi.getJsonStreamingSerializer(function (serializer) {
40 | othis.bimServerApi.call("ServiceInterface", "download", {
41 | roids: [othis.roid],
42 | serializerOid: serializer.oid,
43 | sync: false
44 | }, function (topicId) {
45 | const url = othis.bimServerApi.generateRevisionDownloadUrl({
46 | topicId: topicId,
47 | serializerOid: serializer.oid
48 | });
49 | othis.bimServerApi.getJson(url, null, function (data) {
50 | data.objects.forEach(function (object) {
51 | othis.objects[object._i] = othis.createWrapper(object, object._t);
52 | });
53 | othis.loading = false;
54 | othis.loadedDeep = true;
55 | othis.waiters.forEach(function (waiter) {
56 | waiter();
57 | });
58 | othis.waiters = [];
59 | othis.bimServerApi.call("ServiceInterface", "cleanupLongAction", {
60 | topicId: topicId
61 | }, function () {
62 | if (modelLoadCallback != null) {
63 | modelLoadCallback(othis);
64 | }
65 | });
66 | }, function (error) {
67 | console.log(error);
68 | });
69 | });
70 | });
71 | } else {
72 | if (modelLoadCallback != null) {
73 | modelLoadCallback(othis);
74 | }
75 | }
76 | }
77 |
78 | // Start a transaction, make sure to wait for the callback to be called, only after that the transaction will be active
79 | startTransaction(callback) {
80 | this.bimServerApi.call("LowLevelInterface", "startTransaction", {
81 | poid: this.poid
82 | }, (tid) => {
83 | this.tid = tid;
84 | callback(tid);
85 | });
86 | }
87 |
88 | // Checks whether a transaction is running, if not, it throws an exception, otherwise it return the tid
89 | checkTransaction() {
90 | if (this.tid != null) {
91 | return this.tid;
92 | }
93 | throw new Error("No transaction is running, call startTransaction first");
94 | }
95 |
96 | create(className, object, callback) {
97 | const tid = this.checkTransaction();
98 | object._t = className;
99 | const wrapper = this.createWrapper({}, className);
100 | this.bimServerApi.call("LowLevelInterface", "createObject", {
101 | tid: tid,
102 | className: className
103 | }, (oid) => {
104 | wrapper._i = oid;
105 | this.objects[object._i] = wrapper;
106 | object._s = 1;
107 | if (callback != null) {
108 | callback(object);
109 | }
110 | });
111 | return object;
112 | }
113 |
114 | reset() {
115 |
116 | }
117 |
118 | commit(comment, callback) {
119 | const tid = this.checkTransaction();
120 | this.bimServerApi.call("LowLevelInterface", "commitTransaction", {
121 | tid: tid,
122 | comment: comment
123 | }, function (roid) {
124 | if (callback != null) {
125 | callback(roid);
126 | }
127 | });
128 | }
129 |
130 | abort(callback) {
131 | const tid = this.checkTransaction();
132 | this.bimServerApi.call("LowLevelInterface", "abortTransaction", {
133 | tid: tid
134 | }, function () {
135 | if (callback != null) {
136 | callback();
137 | }
138 | });
139 | }
140 |
141 | addChangeListener(changeListener) {
142 | this.changeListeners.push(changeListener);
143 | }
144 |
145 | incrementChanges() {
146 | this.changes++;
147 | this.changeListeners.forEach((changeListener) => {
148 | changeListener(this.changes);
149 | });
150 | }
151 |
152 | extendClass(wrapperClass, typeName) {
153 | let realType = this.bimServerApi.schemas[this.schema][typeName];
154 | if (typeName === "GeometryInfo" || typeName === "GeometryData" || typeName === "Buffer") {
155 | realType = this.bimServerApi.schemas.geometry[typeName];
156 | }
157 | realType.superclasses.forEach((typeName) => {
158 | this.extendClass(wrapperClass, typeName);
159 | });
160 |
161 | const othis = this;
162 |
163 | for (let fieldName in realType.fields) {
164 | const field = realType.fields[fieldName];
165 | field.name = fieldName;
166 | wrapperClass.fields.push(field);
167 | (function (field, fieldName) {
168 | if (field.reference) {
169 | wrapperClass["set" + fieldName.firstUpper() + "Wrapped"] = function (typeName, value) {
170 | const object = this.object;
171 | object[fieldName] = {
172 | _t: typeName,
173 | value: value
174 | };
175 | const tid = othis.checkTransaction();
176 | const type = othis.bimServerApi.schemas[othis.schema][typeName];
177 | const wrappedValueType = type.fields.wrappedValue;
178 | if (wrappedValueType.type === "string") {
179 | othis.bimServerApi.call("LowLevelInterface", "setWrappedStringAttribute", {
180 | tid: tid,
181 | oid: object._i,
182 | attributeName: fieldName,
183 | type: typeName,
184 | value: value
185 | }, function () {
186 | if (object.changedFields == null) {
187 | object.changedFields = {};
188 | }
189 | object.changedFields[fieldName] = true;
190 | othis.changedObjectOids[object.oid] = true;
191 | othis.incrementChanges();
192 | });
193 | }
194 | };
195 | wrapperClass["set" + fieldName.firstUpper()] = function (value) {
196 | const tid = othis.checkTransaction();
197 | const object = this.object;
198 | object[fieldName] = value;
199 | if (value == null) {
200 | othis.bimServerApi.call("LowLevelInterface", "unsetReference", {
201 | tid: tid,
202 | oid: object._i,
203 | referenceName: fieldName,
204 | }, function () {
205 | if (object.changedFields == null) {
206 | object.changedFields = {};
207 | }
208 | object.changedFields[fieldName] = true;
209 | othis.changedObjectOids[object.oid] = true;
210 | });
211 | } else {
212 | othis.bimServerApi.call("LowLevelInterface", "setReference", {
213 | tid: tid,
214 | oid: object._i,
215 | referenceName: fieldName,
216 | referenceOid: value._i
217 | }, function () {
218 | if (object.changedFields == null) {
219 | object.changedFields = {};
220 | }
221 | object.changedFields[fieldName] = true;
222 | othis.changedObjectOids[object.oid] = true;
223 | });
224 | }
225 | };
226 | wrapperClass["add" + fieldName.firstUpper()] = function (value, callback) {
227 | const object = this.object;
228 | const tid = othis.checkTransaction();
229 | if (object[fieldName] == null) {
230 | object[fieldName] = [];
231 | }
232 | object[fieldName].push(value);
233 | othis.bimServerApi.call("LowLevelInterface", "addReference", {
234 | tid: tid,
235 | oid: object._i,
236 | referenceName: fieldName,
237 | referenceOid: value._i
238 | }, function () {
239 | if (object.changedFields == null) {
240 | object.changedFields = {};
241 | }
242 | object.changedFields[fieldName] = true;
243 | othis.changedObjectOids[object.oid] = true;
244 | if (callback != null) {
245 | callback();
246 | }
247 | });
248 | };
249 | wrapperClass["remove" + fieldName.firstUpper()] = function (value, callback) {
250 | const object = this.object;
251 | const tid = othis.checkTransaction();
252 | const list = object[fieldName];
253 | const index = list.indexOf(value);
254 | list.splice(index, 1);
255 |
256 | othis.bimServerApi.call("LowLevelInterface", "removeReference", {
257 | tid: tid,
258 | oid: object._i,
259 | referenceName: fieldName,
260 | index: index
261 | }, function () {
262 | if (object.changedFields == null) {
263 | object.changedFields = {};
264 | }
265 | object.changedFields[fieldName] = true;
266 | othis.changedObjectOids[object.oid] = true;
267 | if (callback != null) {
268 | callback();
269 | }
270 | });
271 | };
272 | wrapperClass["get" + fieldName.firstUpper()] = function (callback) {
273 | const object = this.object;
274 | const model = this.model;
275 | const promise = new BimServerApiPromise();
276 | if (object[fieldName] != null) {
277 | if (field.many) {
278 | object[fieldName].forEach(function (item, index) {
279 | callback(item, index);
280 | });
281 | } else {
282 | callback(object[fieldName]);
283 | }
284 | promise.fire();
285 | return promise;
286 | }
287 | const embValue = object["_e" + fieldName];
288 | if (embValue != null) {
289 | if (callback != null) {
290 | callback(embValue);
291 | }
292 | promise.fire();
293 | return promise;
294 | }
295 | const value = object["_r" + fieldName];
296 | if (field.many) {
297 | if (object[fieldName] == null) {
298 | object[fieldName] = [];
299 | }
300 | if (value != null) {
301 | model.get(value, function (v) {
302 | object[fieldName].push(v);
303 | callback(v, object[fieldName].length - 1);
304 | }).done(function () {
305 | promise.fire();
306 | });
307 | } else {
308 | promise.fire();
309 | }
310 | } else {
311 | if (value != null) {
312 | const ref = othis.objects[value._i];
313 | if (value._i == -1) {
314 | callback(null);
315 | promise.fire();
316 | } else if (ref == null || ref.object._s == 0) {
317 | model.get(value._i, function (v) {
318 | object[fieldName] = v;
319 | callback(v);
320 | }).done(function () {
321 | promise.fire();
322 | });
323 | } else {
324 | object[fieldName] = ref;
325 | callback(ref);
326 | promise.fire();
327 | }
328 | } else {
329 | callback(null);
330 | promise.fire();
331 | }
332 | }
333 | return promise;
334 | };
335 | } else {
336 | wrapperClass["get" + fieldName.firstUpper()] = function (callback) {
337 | const object = this.object;
338 | if (field.many) {
339 | if (object[fieldName] == null) {
340 | object[fieldName] = [];
341 | }
342 | // object[fieldName].push = function () {};
343 | }
344 | if (callback != null) {
345 | callback(object[fieldName]);
346 | }
347 | return object[fieldName];
348 | };
349 | wrapperClass["set" + fieldName.firstUpper()] = function (value) {
350 | const object = this.object;
351 | object[fieldName] = value;
352 | const tid = othis.checkTransaction();
353 | if (field.many) {
354 | othis.bimServerApi.call("LowLevelInterface", "setDoubleAttributes", {
355 | tid: tid,
356 | oid: object._i,
357 | attributeName: fieldName,
358 | values: value
359 | }, function () {});
360 | } else {
361 | if (value == null) {
362 | othis.bimServerApi.call("LowLevelInterface", "unsetAttribute", {
363 | tid: tid,
364 | oid: object._i,
365 | attributeName: fieldName
366 | }, function () {});
367 | } else if (field.type === "string") {
368 | othis.bimServerApi.call("LowLevelInterface", "setStringAttribute", {
369 | tid: tid,
370 | oid: object._i,
371 | attributeName: fieldName,
372 | value: value
373 | }, function () {});
374 | } else if (field.type === "double") {
375 | othis.bimServerApi.call("LowLevelInterface", "setDoubleAttribute", {
376 | tid: tid,
377 | oid: object._i,
378 | attributeName: fieldName,
379 | value: value
380 | }, function () {});
381 | } else if (field.type === "boolean") {
382 | othis.bimServerApi.call("LowLevelInterface", "setBooleanAttribute", {
383 | tid: tid,
384 | oid: object._i,
385 | attributeName: fieldName,
386 | value: value
387 | }, function () {});
388 | } else if (field.type === "int") {
389 | othis.bimServerApi.call("LowLevelInterface", "setIntegerAttribute", {
390 | tid: tid,
391 | oid: object._i,
392 | attributeName: fieldName,
393 | value: value
394 | }, function () {});
395 | } else if (field.type === "enum") {
396 | othis.bimServerApi.call("LowLevelInterface", "setEnumAttribute", {
397 | tid: tid,
398 | oid: object._i,
399 | attributeName: fieldName,
400 | value: value
401 | }, function () {});
402 | } else {
403 | othis.bimServerApi.log("Unimplemented type " + typeof value);
404 | }
405 | object[fieldName] = value;
406 | }
407 | if (object.changedFields == null) {
408 | object.changedFields = {};
409 | }
410 | object.changedFields[fieldName] = true;
411 | othis.changedObjectOids[object.oid] = true;
412 | };
413 | }
414 | })(field, fieldName);
415 | }
416 | }
417 |
418 | dumpByType() {
419 | const mapLoaded = {};
420 | const mapNotLoaded = {};
421 | for (let oid in this.objects) {
422 | const object = this.objects[oid];
423 | const type = object.getType();
424 | const counter = mapLoaded[type];
425 | if (object.object._s == 1) {
426 | if (counter == null) {
427 | mapLoaded[type] = 1;
428 | } else {
429 | mapLoaded[type] = counter + 1;
430 | }
431 | }
432 | if (object.object._s == 0) {
433 | const counter = mapNotLoaded[type];
434 | if (counter == null) {
435 | mapNotLoaded[type] = 1;
436 | } else {
437 | mapNotLoaded[type] = counter + 1;
438 | }
439 | }
440 | }
441 | console.log("LOADED");
442 | for (let type in mapLoaded) {
443 | console.log(type, mapLoaded[type]);
444 | }
445 | console.log("NOT_LOADED");
446 | for (let type in mapNotLoaded) {
447 | console.log(type, mapNotLoaded[type]);
448 | }
449 | }
450 |
451 | getClass(typeName) {
452 | const othis = this;
453 |
454 | if (this.bimServerApi.classes[typeName] == null) {
455 | let realType = this.bimServerApi.schemas[this.schema][typeName];
456 | if (realType == null) {
457 | if (typeName === "GeometryInfo" || typeName === "GeometryData" || typeName === "Buffer") {
458 | realType = this.bimServerApi.schemas.geometry[typeName];
459 | }
460 | if (realType == null) {
461 | throw "Type " + typeName + " not found in schema " + this.schema;
462 | }
463 | }
464 |
465 | const wrapperClass = {
466 | fields: []
467 | };
468 |
469 | wrapperClass.isA = function (typeName) {
470 | return othis.bimServerApi.isA(othis.schema, this.object._t, typeName);
471 | };
472 | wrapperClass.getType = function () {
473 | return this.object._t;
474 | };
475 | wrapperClass.remove = function (removeCallback) {
476 | const tid = othis.checkTransaction();
477 | othis.bimServerApi.call("LowLevelInterface", "removeObject", {
478 | tid: tid,
479 | oid: this.object._i
480 | }, function () {
481 | if (removeCallback != null) {
482 | removeCallback();
483 | }
484 | delete othis.objects[this.object._i];
485 | });
486 | };
487 |
488 | othis.extendClass(wrapperClass, typeName);
489 |
490 | othis.bimServerApi.classes[typeName] = wrapperClass;
491 | }
492 | return othis.bimServerApi.classes[typeName];
493 | }
494 |
495 | createWrapper(object, typeName) {
496 | if (this.objects[object._i] != null) {
497 | console.log("Warning!", object);
498 | }
499 | if (typeName == null) {
500 | console.warn("typeName = null", object);
501 | }
502 | object.oid = object._i;
503 | const cl = this.getClass(typeName);
504 | if (cl == null) {
505 | console.error("No class found for " + typeName);
506 | }
507 | const wrapper = Object.create(cl);
508 | // transient variables
509 | wrapper.trans = {
510 | mode: 2
511 | };
512 | wrapper.oid = object.oid;
513 | wrapper.model = this;
514 | wrapper.object = object;
515 | return wrapper;
516 | }
517 |
518 | size(callback) {
519 | this.bimServerApi.call("ServiceInterface", "getRevision", {
520 | roid: this.roid
521 | }, function (revision) {
522 | callback(revision.size);
523 | });
524 | }
525 |
526 | count(type, includeAllSubTypes, callback) {
527 | // TODO use includeAllSubTypes
528 | this.bimServerApi.call("LowLevelInterface", "count", {
529 | roid: this.roid,
530 | className: type
531 | }, function (size) {
532 | callback(size);
533 | });
534 | }
535 |
536 | getByX(methodName, keyname, fetchingMap, targetMap, query, getValueMethod, list, callback) {
537 | const promise = new BimServerApiPromise();
538 | if (typeof list == "string" || typeof list == "number") {
539 | list = [list];
540 | }
541 | let len = list.length;
542 | // Iterating in reverse order because we remove items from this array
543 | while (len--) {
544 | const item = list[len];
545 | if (targetMap[item] != null) {
546 | // Already loaded? Remove from list and call callback
547 | const existingObject = targetMap[item].object;
548 | if (existingObject._s == 1) {
549 | const index = list.indexOf(item);
550 | list.splice(index, 1);
551 | callback(targetMap[item]);
552 | }
553 | } else if (fetchingMap[item] != null) {
554 | // Already loading? Add the callback to the list and remove from fetching list
555 | fetchingMap[item].push(callback);
556 | const index = list.indexOf(item);
557 | list.splice(index, 1);
558 | }
559 | }
560 |
561 | const othis = this;
562 | // Any left?
563 | if (list.length > 0) {
564 | list.forEach(function (item) {
565 | fetchingMap[item] = [];
566 | });
567 | othis.bimServerApi.getJsonStreamingSerializer(function (serializer) {
568 | const request = {
569 | roids: [othis.roid],
570 | query: JSON.stringify(query),
571 | serializerOid: serializer.oid,
572 | sync: false
573 | };
574 | othis.bimServerApi.call("ServiceInterface", "download", request, function (topicId) {
575 | const url = othis.bimServerApi.generateRevisionDownloadUrl({
576 | topicId: topicId,
577 | serializerOid: serializer.oid
578 | });
579 | othis.bimServerApi.getJson(url, null, function (data) {
580 | if (data.objects.length > 0) {
581 | let done = 0;
582 | data.objects.forEach(function (object) {
583 | let wrapper = null;
584 | if (othis.objects[object._i] != null) {
585 | wrapper = othis.objects[object._i];
586 | if (wrapper.object._s != 1) {
587 | wrapper.object = object;
588 | }
589 | } else {
590 | wrapper = othis.createWrapper(object, object._t);
591 | }
592 | const item = getValueMethod(object);
593 | // Checking the value again, because sometimes serializers send more objects...
594 | if (list.indexOf(item) != -1) {
595 | targetMap[item] = wrapper;
596 | if (fetchingMap[item] != null) {
597 | fetchingMap[item].forEach(function (cb) {
598 | cb(wrapper);
599 | });
600 | delete fetchingMap[item];
601 | }
602 | callback(wrapper);
603 | }
604 | done++;
605 | if (done == data.objects.length) {
606 | othis.bimServerApi.call("ServiceInterface", "cleanupLongAction", {
607 | topicId: topicId
608 | }, function () {
609 | promise.fire();
610 | });
611 | }
612 | });
613 | } else {
614 | othis.bimServerApi.log("Object with " + keyname + " " + list + " not found");
615 | callback(null);
616 | promise.fire();
617 | }
618 | }, function (error) {
619 | console.log(error);
620 | });
621 | });
622 | });
623 | } else {
624 | promise.fire();
625 | }
626 | return promise;
627 | }
628 |
629 | getByGuids(guids, callback) {
630 | const query = {
631 | guids: guids
632 | };
633 | return this.getByX("getByGuid", "guid", this.guidsFetching, this.objectsByGuid, query, function (object) {
634 | return object.GlobalId;
635 | }, guids, callback);
636 | }
637 |
638 | get(oids, callback) {
639 | if (typeof oids == "number") {
640 | oids = [oids];
641 | } else if (typeof oids == "string") {
642 | oids = [parseInt(oids)];
643 | } else if (Array.isArray(oids)) {
644 | const newOids = [];
645 | oids.forEach(function (oid) {
646 | if (typeof oid == "object") {
647 | newOids.push(oid._i);
648 | } else {
649 | newOids.push(oid);
650 | }
651 | });
652 | oids = newOids;
653 | }
654 | const query = {
655 | oids: oids
656 | };
657 | return this.getByX("get", "OID", this.oidsFetching, this.objects, query, function (object) {
658 | return object._i;
659 | }, oids, callback);
660 | }
661 |
662 | getByName(names, callback) {
663 | const query = {
664 | names: names
665 | };
666 | return this.getByX("getByName", "name", this.namesFetching, this.objectsByName, query, function (object) {
667 | return object.getName == null ? null : object.getName();
668 | }, names, callback);
669 | }
670 |
671 | query(query, callback, errorCallback) {
672 | const promise = new BimServerApiPromise();
673 | const fullTypesLoading = {};
674 | if (query.queries != null) {
675 | query.queries.forEach((subQuery) => {
676 | if (subQuery.type != null) {
677 | if (typeof subQuery.type === "object") {
678 | fullTypesLoading[subQuery.type.name] = true;
679 | this.loadedTypes[subQuery.type.name] = {};
680 | if (subQuery.type.includeAllSubTypes) {
681 | const schema = this.bimServerApi.schemas[this.schema];
682 | this.bimServerApi.getAllSubTypes(schema, subQuery.type.name, (subTypeName) => {
683 | fullTypesLoading[subTypeName] = true;
684 | this.loadedTypes[subTypeName] = {};
685 | });
686 | }
687 | } else {
688 | fullTypesLoading[subQuery.type] = true;
689 | this.loadedTypes[subQuery.type] = {};
690 | if (subQuery.includeAllSubTypes) {
691 | const schema = this.bimServerApi.schemas[this.schema];
692 | this.bimServerApi.getAllSubTypes(schema, subQuery.type, (subTypeName) => {
693 | fullTypesLoading[subTypeName] = true;
694 | this.loadedTypes[subTypeName] = {};
695 | });
696 | }
697 | }
698 | }
699 | });
700 | }
701 | this.bimServerApi.getJsonStreamingSerializer((serializer) => {
702 | this.bimServerApi.callWithFullIndication("ServiceInterface", "download", {
703 | roids: [this.roid],
704 | query: JSON.stringify(query),
705 | serializerOid: serializer.oid,
706 | sync: false
707 | }, (topicId) => {
708 | let handled = false;
709 | this.bimServerApi.registerProgressHandler(topicId, (topicId, state) => {
710 | if (state.title == "Done preparing" && !handled) {
711 | handled = true;
712 | const url = this.bimServerApi.generateRevisionDownloadUrl({
713 | topicId: topicId,
714 | serializerOid: serializer.oid
715 | });
716 | this.bimServerApi.notifier.setInfo(this.bimServerApi.translate("GETTING_MODEL_DATA"), -1);
717 | this.bimServerApi.getJson(url, null, (data) => {
718 | //console.log("query", data.objects.length);
719 | data.objects.forEach((object) => {
720 | let wrapper = this.objects[object._i];
721 | if (wrapper == null) {
722 | wrapper = this.createWrapper(object, object._t);
723 | this.objects[object._i] = wrapper;
724 | if (fullTypesLoading[object._t] != null) {
725 | this.loadedTypes[object._t][wrapper.oid] = wrapper;
726 | }
727 | } else {
728 | if (object._s == 1) {
729 | wrapper.object = object;
730 | }
731 | }
732 | // if (othis.loadedTypes[wrapper.getType()] == null) {
733 | // othis.loadedTypes[wrapper.getType()] = {};
734 | // }
735 | // othis.loadedTypes[wrapper.getType()][object._i] = wrapper;
736 | if (object._s == 1 && callback != null) {
737 | callback(wrapper);
738 | }
739 | });
740 | // othis.dumpByType();
741 | this.bimServerApi.call("ServiceInterface", "cleanupLongAction", {
742 | topicId: topicId
743 | }, () => {
744 | promise.fire();
745 | this.bimServerApi.notifier.setSuccess(this.bimServerApi.translate("MODEL_DATA_DONE"));
746 | });
747 | });
748 | } else if (state.state == "AS_ERROR") {
749 | if (errorCallback != null) {
750 | errorCallback(state.title);
751 | } else {
752 | console.error(state.title);
753 | }
754 | }
755 | });
756 | });
757 | });
758 | return promise;
759 | }
760 |
761 | getAllOfType(type, includeAllSubTypes, callback) {
762 | const promise = new BimServerApiPromise();
763 | if (this.loadedDeep) {
764 | for (let oid in this.objects) {
765 | const object = this.objects[oid];
766 | if (object._t == type) {
767 | callback(object);
768 | }
769 | }
770 | promise.fire();
771 | } else {
772 | const types = [];
773 | types.push(type);
774 | if (includeAllSubTypes) {
775 | this.bimServerApi.getAllSubTypes(this.bimServerApi.schemas[this.schema], type, function (subType) {
776 | types.push(subType);
777 | });
778 | }
779 |
780 | const query = {
781 | queries: []
782 | };
783 |
784 | types.forEach((t) => {
785 | if (this.loadedTypes[t] && Object.getOwnPropertyNames(this.loadedTypes[t]).length !== 0) {
786 | for (let oid in this.loadedTypes[t]) {
787 | callback(this.loadedTypes[t][oid]);
788 | }
789 | } else {
790 | query.queries.push({
791 | type: t
792 | });
793 | }
794 | });
795 |
796 | if (query.queries.length > 0) {
797 | this.bimServerApi.getJsonStreamingSerializer((serializer) => {
798 | this.bimServerApi.call("ServiceInterface", "download", {
799 | roids: [this.roid],
800 | query: JSON.stringify(query),
801 | serializerOid: serializer.oid,
802 | sync: false
803 | }, (topicId) => {
804 | const url = this.bimServerApi.generateRevisionDownloadUrl({
805 | topicId: topicId,
806 | serializerOid: serializer.oid
807 | });
808 | this.bimServerApi.getJson(url, null, (data) => {
809 | data.objects.forEach((object) => {
810 | if (!this.loadedTypes[object._t]) {
811 | this.loadedTypes[object._t] = {}
812 | }
813 |
814 | if (this.objects[object._i]) {
815 | // Hmm we are doing a query on type, but some objects have already loaded, let's use those instead
816 | const wrapper = this.objects[object._i];
817 | if (wrapper.object._s !== 1) {
818 | // Replace the value with something that's LOADED
819 | wrapper.object = object;
820 | }
821 | if (wrapper.isA(object._t)) {
822 | this.loadedTypes[object._t][object._i] = wrapper;
823 | callback(wrapper);
824 | }
825 | } else {
826 | const wrapper = this.createWrapper(object, object._t);
827 | this.objects[object._i] = wrapper;
828 | if (object._s == 1) {
829 | this.loadedTypes[object._t][object._i] = wrapper;
830 | callback(wrapper);
831 | }
832 | }
833 | });
834 | this.bimServerApi.call("ServiceInterface", "cleanupLongAction", {
835 | topicId: topicId
836 | }, () => {
837 | promise.fire();
838 | });
839 | }, (error) => {
840 | console.log(error);
841 | });
842 | });
843 | });
844 | } else {
845 | promise.fire();
846 | }
847 | }
848 | return promise;
849 | }
850 | }
851 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bimserverapi",
3 | "groupId": "org.opensourcebim",
4 | "artifactId": "javascriptapi",
5 | "organization": "OpenSource BIM",
6 | "version": "0.0.167",
7 | "description": "A JavaScript API for the OpenSource BIMserver",
8 | "author": {
9 | "name": "Ruben de Laat",
10 | "email": "ruben@logic-labs.nl"
11 | },
12 | "scripts": {
13 | "build": "rollup -c"
14 | },
15 | "files": [
16 | "*.js"
17 | ],
18 | "main": "build/bimserverapi.js",
19 | "module": "bimserverclient.js",
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/opensourceBIM/BIMserver-JavaScript-API"
23 | },
24 | "bugs": {
25 | "url": "https://github.com/opensourceBIM/BIMserver-JavaScript-API/issues"
26 | },
27 | "keywords": [],
28 | "browser": {
29 | "xhr2": false,
30 | "websocket": false
31 | },
32 | "dependencies": {
33 | "websocket": "*",
34 | "xhr2": "*"
35 | },
36 | "devDependencies": {
37 | "babel-core": "^6.26.0",
38 | "babel-plugin-external-helpers": "^6.22.0",
39 | "babel-preset-env": "^1.6.1",
40 | "grunt": "*",
41 | "grunt-contrib-concat": "*",
42 | "grunt-contrib-jshint": "*",
43 | "grunt-contrib-nodeunit": "*",
44 | "grunt-contrib-uglify": "*",
45 | "grunt-zip": "*",
46 | "rollup": "^0.50.0",
47 | "rollup-plugin-babel": "^3.0.2",
48 | "rollup-plugin-commonjs": "^8.2.6",
49 | "rollup-plugin-node-resolve": "^3.0.0",
50 | "rollup-plugin-uglify": "^2.0.1"
51 | },
52 | "preferGlobal": true,
53 | "private": false,
54 | "analyze": true,
55 | "license": "AGPL-3.0",
56 | "readmeFilename": "README.md",
57 | "tonicExampleFilename": "tonicExample.js"
58 | }
59 |
--------------------------------------------------------------------------------
/plugin/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opensourceBIM/BIMserver-JavaScript-API/74b42a77f264a36952e8b7ffe41af99dd0c0c4ca/plugin/icon.png
--------------------------------------------------------------------------------
/plugin/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | bimserverjavascriptapi
5 | BIMserver JavaScript API
6 | JavaScript API for BIMserver
7 |
8 |
--------------------------------------------------------------------------------
/plugin/version.properties:
--------------------------------------------------------------------------------
1 | build.date=${timestamp}
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.opensourcebim
5 | bimserverapi
6 | 0.0.177-SNAPSHOT
7 | BIMServer JavaScript API
8 | JavaScript API for BIMserver
9 | https://github.com/opensourceBIM/BIMserver-JavaScript-API
10 |
11 | OpenSource BIM
12 | opensourcebim.org
13 |
14 |
15 |
16 | GNU LGPLv3
17 | https://choosealicense.com/licenses/lgpl-3.0/
18 | repo
19 |
20 |
21 |
22 |
23 | Ruben de Laat
24 | ruben@logic-labs.nl
25 |
26 |
27 |
28 | scm:git:https://github.com/opensourceBIM/BIMserver-JavaScript-API.git
29 | scm:git:https://github.com/opensourceBIM/BIMserver-JavaScript-API.git
30 | bimserverapi-0.0.167
31 | https://github.com/opensourceBIM/BIMserver-JavaScript-API.git
32 |
33 |
34 | GitHub
35 | https://github.com/opensourceBIM/BIMserver-JavaScript-API/issues
36 |
37 |
38 |
39 | ossrh
40 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
41 |
42 |
43 | ossrh
44 | https://oss.sonatype.org/content/repositories/snapshots
45 |
46 |
47 |
48 | yyyy-MM-dd'T'HH:mm:ssZ
49 | UTF-8
50 | ${maven.build.timestamp}
51 |
52 |
53 |
54 | org.opensourcebim
55 | pluginbase
56 | 1.5.177
57 |
58 |
59 |
60 |
61 |
62 | .
63 | .
64 |
65 | index.html
66 | *.js
67 |
68 |
69 |
70 | ../../output
71 |
72 |
73 | ../../build
74 |
75 |
76 | plugin
77 | true
78 | plugin
79 |
80 |
81 |
82 |
83 | org.codehaus.mojo
84 | build-helper-maven-plugin
85 |
86 |
87 | attach-plugin
88 | package
89 |
90 | attach-artifact
91 |
92 |
93 |
94 |
95 | plugin/plugin.xml
96 | xml
97 | plugin
98 |
99 |
100 | plugin/icon.png
101 | png
102 | icon
103 |
104 |
105 | ${project.build.outputDirectory}/plugin/version.properties
106 | properties
107 | version
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | org.sonatype.plugins
116 | nexus-staging-maven-plugin
117 | 1.6.3
118 | true
119 |
120 | ossrh
121 | https://oss.sonatype.org/
122 | true
123 | 60
124 |
125 |
126 |
127 | maven-release-plugin
128 | 2.5.3
129 |
130 | github.com
131 | false
132 | release
133 | deploy
134 |
135 |
136 |
137 |
138 |
139 |
140 | release
141 |
142 |
143 |
144 | maven-gpg-plugin
145 | 1.5
146 |
147 |
148 | sign-artifacts
149 | verify
150 |
151 | sign
152 |
153 |
154 |
155 | --pinentry-mode
156 | loopback
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-node-resolve';
2 | import commonjs from 'rollup-plugin-commonjs';
3 | import babel from 'rollup-plugin-babel';
4 | import uglify from 'rollup-plugin-uglify';
5 |
6 | export default {
7 | input: 'bimserverclient.js',
8 | output: {
9 | format: 'umd',
10 | name: 'bimserverapi',
11 | file: 'build/bimserverapi.umd.js',
12 | sourceMap: true
13 | },
14 | plugins: [
15 | resolve({
16 | jsnext: true,
17 | main: true,
18 | preferBuiltins: true,
19 | browser: true
20 | }),
21 | commonjs({
22 | sourceMap: false
23 | }),
24 | babel({
25 | exclude: ['node_modules/**']
26 | })
27 | ]
28 | };
--------------------------------------------------------------------------------
/tonicExample.js:
--------------------------------------------------------------------------------
1 | var bimserverapi = require("bimserverapi");
2 |
3 | bimserverapi.login("admin@bimserver.org", "admin");
--------------------------------------------------------------------------------
/translations_en.js:
--------------------------------------------------------------------------------
1 | export const translations = {
2 | GETDATAOBJECTSBYTYPE_BUSY: "Loading objects",
3 | REQUESTPASSWORDCHANGE_BUSY: "Busy sending password reset e-mail",
4 | REQUESTPASSWORDCHANGE_DONE: "A password reset e-mail has been sent",
5 | SETSERVERSETTINGS_DONE: "Server settings successfully updated",
6 | ENABLEPLUGIN_DONE: "Plugin successfully enabled",
7 | DISABLEPLUGIN_DONE: "Plugin successfully disabled",
8 | SETDEFAULTWEBMODULE_DONE: "Default webmodule changed",
9 | SETDEFAULTQUERYENGINE_DONE: "Default Query Engine successfully changed",
10 | SETDEFAULTMODELMERGER_DONE: "Default Model Merger successfully changed",
11 | SETDEFAULTSERIALIZER_DONE: "Default Serializer successfully changed",
12 | SETDEFAULTOBJECTIDM_DONE: "Default ObjectIDM successfully changed",
13 | SETDEFAULTRENDERENGINE_DONE: "Default Render Engine successfully changed",
14 | SETDEFAULTMODELCOMPARE_DONE: "Default Model Compare successfully changed",
15 | LOGIN_BUSY: "Trying to login",
16 | CHANGEUSERTYPE_DONE: "Type of user successfully changed",
17 | ADDUSER_DONE: "User successfully added, you should receive a validation email shortly",
18 | UPDATEINTERNALSERVICE_DONE: "Internal service successfully updated",
19 | UPDATEMODELCOMPARE_DONE: "Model compare plugin successfully updated",
20 | UPDATEMODELMERGER_DONE: "Model merger successfully updated",
21 | UPDATEQUERYENGINE_DONE: "Query engine plugin successfully updated",
22 | UPDATEOBJECTIDM_DONE: "ObjectIDM succesfully updated",
23 | UPDATEDESERIALIZER_DONE: "Serializer succesfully updated",
24 | ADDUSERTOPROJECT_DONE: "User successfully added to project",
25 | REMOVEUSERFROMPROJECT_DONE: "User successfully removed from project",
26 | UNDELETEPROJECT_DONE: "Project successfully undeleted",
27 | DELETEPROJECT_DONE: "Project successfully deleted",
28 | ADDPROJECT_DONE: "Project successfully added",
29 | VALIDATEACCOUNT_DONE: "Account successfully validated, you can now login",
30 | ADDPROJECTASSUBPROJECT_DONE: "Sub project added successfully",
31 | DOWNLOADBYJSONQUERY_BUSY: "Downloading BIM",
32 | CHECKINFROMURL_DONE: "Done checking in from URL",
33 | GETLOGGEDINUSER_BUSY: "Getting user details",
34 | SETPLUGINSETTINGS_DONE: "Plugin settings successfully saved",
35 | GETSERVERINFO_BUSY: "Getting server info",
36 | GETVERSION_BUSY: "Getting server version",
37 | GETPROJECTBYPOID_BUSY: "Getting project details",
38 | GETALLRELATEDPROJECTS_BUSY: "Getting related project's details",
39 | GETSERIALIZERBYPLUGINCLASSNAME_BUSY: "Getting serializer info",
40 | CLEANUPLONGACTION_BUSY: "Cleaning up",
41 | GETREVISIONSUMMARY_BUSY: "Getting revision summary",
42 | DOWNLOADBYOIDS_BUSY: "Downloading model data",
43 | REGISTERPROGRESSHANDLER_BUSY: "Registering for updates on progress",
44 | GETALLREVISIONSOFPROJECT_BUSY: "Getting all revisions of project",
45 | GETPLUGINDESCRIPTOR_BUSY: "Getting plugin information",
46 | GETUSERSETTINGS_BUSY: "Getting user settings",
47 | GETALLQUERYENGINES_BUSY: "Getting query engines",
48 | REGISTERNEWPROJECTHANDLER_BUSY: "Registering for updates on new projects",
49 | ADDUSER_BUSY: "Adding user...",
50 | GETAVAILABLEPLUGINBUNDLES_BUSY: "Loading available plugins, this can take a while...",
51 | GETAVAILABLEPLUGINBUNDLES_DONE: "Done loading available plugins",
52 | GETINSTALLEDPLUGINBUNDLES_BUSY: "Loading installed plugins, this can take a while...",
53 | GETINSTALLEDPLUGINBUNDLES_DONE: "Done loading installed plugins",
54 | INSTALLPLUGINBUNDLE_BUSY: "Installing plugin...",
55 | INSTALLPLUGINBUNDLE_DONE: "Plugin successfully installed",
56 | GETPLUGININFORMATION_BUSY: "Getting plugin information, this can take a while for large plugins...",
57 | GETPLUGININFORMATION_DONE: "Plugin information successfully retrieved",
58 | DOWNLOAD_BUSY: "Downloading model data...",
59 | DOWNLOAD_DONE: "Model data downloaded",
60 | LOGIN_DONE: "Login successful",
61 | LOGOUT_DONE: "Logout successful",
62 | UPDATEPROJECT_DONE: "Project successfully updated",
63 | TRIGGERREVISIONSERVICE_BUSY: "Triggering service...",
64 | TRIGGERREVISIONSERVICE_DONE: "Service triggered successfully",
65 | INSTALLPLUGINBUNDLEFROMFILE_DONE: "Plugin bundle successfully installed from file",
66 | CHECKINFROMURL_BUSY: "Checking in from URL...",
67 | ERROR_REMOTE_METHOD_CALL: "Remote error (server probably down or not reachable)",
68 | GETTING_MODEL_DATA: "Getting model data...",
69 | MODEL_DATA_DONE: "Model data successfully downloaded...",
70 | INITIATECHECKIN_BUSY: "Initiating checkin...",
71 | GETTILECOUNTS_BUSY: "Counting tiles...",
72 | LISTBOUNDINGBOXES_BUSY: "Loading bounding boxes...",
73 | GETALLPROJECTS_BUSY: "Loading all projects...",
74 | GETSUGGESTEDDESERIALIZERFOREXTENSION_BUSY: "Loading deserializer...",
75 | GETDENSITYTHRESHOLD_BUSY: "Loading density information...",
76 | LISTPLUGINSINBUNDLE_DONE: "Plugins in bundle loaded successfully",
77 | CHECKINFROMURLSYNC_BUSY: "Checking in from URL...",
78 | SETPLUGINSYSTEMSETTINGS_DONE: "Plugin system settings successfully updated",
79 | INSTALLPLUGINBUNDLEFROMFILE_BUSY: "Installing plugin bundle from file..."
80 | };
--------------------------------------------------------------------------------