--- /dev/null
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+/**
+ * Created by onvelocity on 11/23/15.
+ */
+
+'use strict';
+
+import _ from 'lodash'
+import d3 from 'd3'
+import UID from './../UniqueId'
+import guid from '../guid'
+import Position from './../graph/Position'
+import ColorGroups from '../ColorGroups'
+import DescriptorModel from './DescriptorModel'
+import DescriptorModelMetaFactory from './DescriptorModelMetaFactory'
+import DescriptorModelMetaProperty from './DescriptorModelMetaProperty'
+
+import Classifier from './descriptors/Classifier'
+import ClassifierMatchAttributes from './descriptors/ClassifierMatchAttributes'
+import ConnectionPoint from './descriptors/ConnectionPoint'
+import VnfdConnectionPointRef from './descriptors/VnfdConnectionPointRef'
+import ConstituentVnfd from './descriptors/ConstituentVnfd'
+import ConstituentVnfdConnectionPoint from './descriptors/ConstituentVnfdConnectionPoint'
+import ForwardingGraph from './descriptors/ForwardingGraph'
+import InternalConnectionPoint from './descriptors/InternalConnectionPoint'
+import InternalVirtualLink from './descriptors/InternalVirtualLink'
+import NetworkService from './descriptors/NetworkService'
+import PhysicalNetworkFunction from './descriptors/PhysicalNetworkFunction'
+import RecordServicePath from './descriptors/RecordServicePath'
+import RspConnectionPointRef from './descriptors/RspConnectionPointRef'
+import VirtualDeploymentUnit from './descriptors/VirtualDeploymentUnit'
+import VirtualLink from './descriptors/VirtualLink'
+import VirtualNetworkFunction from './descriptors/VirtualNetworkFunction'
+import VirtualNetworkFunctionReadOnlyWrapper from './descriptors/VirtualNetworkFunctionReadOnlyWrapper'
+import InternalConnectionPointRef from './descriptors/InternalConnectionPointRef'
+import VirtualNetworkFunctionConnectionPoint from './descriptors/VirtualNetworkFunctionConnectionPoint'
+import VirtualDeploymentUnitInternalConnectionPoint from './descriptors/VirtualDeploymentUnitInternalConnectionPoint'
+
+function findChildDescriptorModelAndUpdateModel(model, parent) {
+ if (parent instanceof DescriptorModel) {
+ const child = parent.findChildByUid(model);
+ if (child) {
+ child.model = model;
+ return child;
+ }
+ }
+}
+
+let identity = 0;
+
+class DescriptorModelFactory {
+
+
+ static containerIdentity(d) {
+ const parentId = UID.from(d && d.parent);
+ // note the incremental counter is to always force d3 models to update
+ return (parentId ? parentId + ':' : '') + UID.from(d) + ':' + identity++;
+ }
+
+ /**
+ * Create a reduce function that creates a DescriptorModel element tree
+ * representation of a Catalog Item and then returns a flat list of
+ * DescriptorModel elements. The first item in the array is root.
+
+ * @returns {Function}
+ */
+ static buildCatalogItemFactory(catalogs) {
+
+ function findCatalogItemByTypeAndId(type, id) {
+ return catalogs.filter(catalog => catalog.type === type).reduce((a, b) => a.concat(b.descriptors), []).filter(d => d.id === id)[0];
+ }
+
+ function mapVLD(vld, containerList) {
+ containerList.push(vld);
+ vld.connection.forEach(d => containerList.push(d));
+ }
+
+ function mapIVLD(ivld, containerList) {
+ containerList.push(ivld);
+ ivld.connection.forEach(d => containerList.push(d));
+ }
+
+ function mapRspConnectionPoint(cp, containerList) {
+ containerList.push(cp);
+ }
+
+ function mapClassifier(classifier, containerList) {
+ containerList.push(classifier);
+ // get the referenced vnfd required for rendering the connection point
+ const vnfdRef = findCatalogItemByTypeAndId('vnfd', classifier.model['vnfd-id-ref']);
+ if (vnfdRef) {
+ classifier.uiState.vnfdRef = vnfdRef;
+ }
+ classifier.matchAttributes.forEach(attr => containerList.push(attr));
+ }
+
+ function mapRSP(rsp, containerList) {
+ containerList.push(rsp);
+ rsp.vnfdConnectionPointRef.forEach(cpRef => mapRspConnectionPoint(cpRef, containerList));
+ }
+
+ function mapFG(fg, containerList) {
+ containerList.push(fg);
+ fg.rsp.forEach(rsp => mapRSP(rsp, containerList));
+ fg.classifier.forEach(classifier => mapClassifier(classifier, containerList));
+ }
+
+ function mapVDU(vdu, containerList) {
+ containerList.push(vdu);
+ vdu.connectionPoint.forEach(d => containerList.push(d));
+ }
+
+ function mapCVNFD(cvnfd, containerList) {
+ // get the referenced vnfd required for rendering the connection points
+ const vnfdRef = findCatalogItemByTypeAndId('vnfd', cvnfd.model['vnfd-id-ref']);
+ if (!vnfdRef) {
+ console.warn('No VNFD found in catalog with id: ' + cvnfd['vnfd-id-ref']);
+ }
+ cvnfd.vnfdRef = vnfdRef;
+ containerList.push(cvnfd);
+ cvnfd.vld.forEach(vld => mapIVLD(vld, containerList));
+ cvnfd.connectionPoint.forEach(cp => containerList.push(cp));
+ }
+
+ function mapNSD(nsd, containerList) {
+ containerList.push(nsd);
+ nsd.constituentVnfd.forEach(cvnfd => mapCVNFD(cvnfd, containerList));
+ nsd.vld.forEach(vld => mapVLD(vld, containerList));
+ nsd.vnffgd.forEach(fg => mapFG(fg, containerList));
+ }
+
+ function mapVNFD(vnfd, containerList) {
+ containerList.push(vnfd);
+ vnfd.vdu.forEach(vdu => mapVDU(vdu, containerList));
+ vnfd.vld.forEach(vld => mapIVLD(vld, containerList));
+ vnfd.connectionPoint.forEach(cp => containerList.push(cp));
+ }
+
+ function mapPNFD(pnfd, containerList) {
+ containerList.push(pnfd);
+ }
+
+ return (containerList, obj) => {
+ if (_.isEmpty(obj)) {
+ return containerList;
+ }
+ switch (obj.uiState.type) {
+ case 'nsd':
+ mapNSD(DescriptorModelFactory.newNetworkService(obj), containerList);
+ break;
+ case 'vnfd':
+ mapVNFD(DescriptorModelFactory.newVirtualNetworkFunction(obj), containerList);
+ break;
+ case 'pnfd':
+ mapPNFD(DescriptorModelFactory.newPhysicalNetworkFunction(obj), containerList);
+ break;
+ default:
+ throw new ReferenceError('only catalog items can be rendered in the canvas. unexpected type: ' + obj.uiState.type);
+ }
+ return containerList;
+ };
+
+ }
+
+ static newNetworkService(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new NetworkService(model, parent);
+ }
+
+ static newConstituentVnfd(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new ConstituentVnfd(model, parent);
+ }
+
+ static newVirtualNetworkFunction(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VirtualNetworkFunction(model, parent);
+ }
+
+ static newVirtualNetworkFunctionConnectionPoint(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VirtualNetworkFunctionConnectionPoint(model, parent);
+ }
+
+ static newInternalConnectionPoint(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new InternalConnectionPoint(model, parent);
+ }
+
+ static newVirtualDeploymentUnit(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VirtualDeploymentUnit(model, parent);
+ }
+
+ static newVirtualDeploymentUnitInternalConnectionPoint(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VirtualDeploymentUnitInternalConnectionPoint(model, parent);
+ }
+
+ static newVirtualLink(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VirtualLink(model, parent);
+ }
+
+ static newInternalVirtualLink(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new InternalVirtualLink(model, parent);
+ }
+
+ static newPhysicalNetworkFunction(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new PhysicalNetworkFunction(model, parent);
+ }
+
+ static newConstituentVnfdConnectionPoint(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new ConstituentVnfdConnectionPoint(model, parent);
+ }
+
+ static newVnfdConnectionPointRef(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new VnfdConnectionPointRef(model, parent);
+ }
+
+ static newForwardingGraph(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new ForwardingGraph(model, parent);
+ }
+
+ static newRecordServicePath(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new RecordServicePath(model, parent);
+ }
+
+ static newRspConnectionPointRef(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new RspConnectionPointRef(model, parent);
+ }
+
+ static newVirtualNetworkFunctionReadOnlyWrapper(vnfdToWrap, parent) {
+ let model;
+ if (vnfdToWrap instanceof DescriptorModel) {
+ if (vnfdToWrap instanceof VirtualNetworkFunction) {
+ model = vnfdToWrap.model;
+ } else {
+ throw new ReferenceError(`expected a VirtualNetworkFunction but got a ${vnfdToWrap.className}`);
+ }
+ } else {
+ model = vnfdToWrap;
+ }
+ return new VirtualNetworkFunctionReadOnlyWrapper(_.cloneDeep(model), parent);
+ }
+
+ static newClassifier(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new Classifier(model, parent);
+ }
+
+ static newClassifierMatchAttributes(model, parent) {
+ return findChildDescriptorModelAndUpdateModel(model, parent) || new ClassifierMatchAttributes(model, parent);
+ }
+
+ static newInternalConnectionPointRef(model, parent) {
+ // note do not find children bc model is not an object it is a leaf-list primative and so the class manages it
+ return new InternalConnectionPointRef(model, parent);
+ }
+
+ /**
+ * Special instance of a RecordServicePath that will create its parent ForwardingGraph it does not exist.
+ *
+ * This is useful to present a stub RSP as an initiator to create Paths without explicitly creating an RSP - just
+ * start building a path and it auto-magically builds the RSP.
+ *
+ * @param parent
+ * @param model
+ */
+ static newRecordServicePathFactory(model, parent) {
+ return new AutoCreateRecordServicePath(model, parent);
+ }
+
+ static isContainer(obj) {
+ return obj instanceof DescriptorModel;
+ }
+
+ static isConnector(obj) {
+ return obj instanceof ConnectionPoint;
+ }
+
+ static isConnectionPoint(obj) {
+ return obj instanceof ConnectionPoint;
+ }
+
+ static isConstituentVnfd(obj) {
+ return obj instanceof ConstituentVnfd;
+ }
+
+ static isConstituentVnfdWithServiceChain(obj, chain) {
+ return obj instanceof ConstituentVnfd && obj.vnfdServiceFunctionChain === chain;
+ }
+
+ static isNetworkService(obj) {
+ return obj instanceof NetworkService;
+ }
+
+ static isVnfdConnectionPointRef(obj) {
+ return obj instanceof VnfdConnectionPointRef;
+ }
+
+ static isRecordServicePath(obj) {
+ return obj instanceof RecordServicePath;
+ }
+
+ static isRspConnectionPointRef(obj) {
+ return obj instanceof RspConnectionPointRef;
+ }
+
+ static isVirtualLink(obj) {
+ return obj instanceof VirtualLink;
+ }
+
+ static isVirtualNetworkFunction(obj) {
+ return obj instanceof VirtualNetworkFunction;
+ }
+
+ static isForwardingGraph(obj) {
+ return obj instanceof ForwardingGraph;
+ }
+
+ static isInternalConnectionPoint(obj) {
+ return obj instanceof InternalConnectionPoint;
+ }
+
+ static isInternalVirtualLink(obj) {
+ return obj instanceof InternalVirtualLink;
+ }
+
+ static get VirtualLink () {
+ return VirtualLink;
+ }
+
+ static get NetworkService () {
+ return NetworkService;
+ }
+
+ static get ForwardingGraph () {
+ return ForwardingGraph;
+ }
+
+ static get VirtualNetworkFunction () {
+ return VirtualNetworkFunction;
+ }
+
+ static get ConstituentVnfd () {
+ return ConstituentVnfd;
+ }
+
+ static get Classifier() {
+ return Classifier;
+ }
+
+ static get ClassifierMatchAttributes() {
+ return ClassifierMatchAttributes;
+ }
+
+ static get VnfdConnectionPointRef() {
+ return VnfdConnectionPointRef;
+ }
+
+ static get VirtualDeploymentUnit() {
+ return VirtualDeploymentUnit;
+ }
+
+ static get InternalConnectionPoint() {
+ return InternalConnectionPoint;
+ }
+
+ static get InternalVirtualLink() {
+ return InternalVirtualLink;
+ }
+
+ static get InternalConnectionPointRef() {
+ return InternalConnectionPointRef;
+ }
+
+ static get VirtualNetworkFunctionConnectionPoint() {
+ return VirtualNetworkFunctionConnectionPoint;
+ }
+
+ static get VirtualDeploymentUnitInternalConnectionPoint() {
+ return VirtualDeploymentUnitInternalConnectionPoint;
+ }
+
+}
+
+/**
+ * Auto create a RecordServicePath when a VnfdConnectionPointRef is added.
+ */
+class AutoCreateRecordServicePath extends RecordServicePath {
+
+ constructor(model, parent) {
+ super(model, null);
+ this.parent = parent;
+ this.isFactory = true;
+ }
+
+ create() {
+ return this.parent.createRsp();
+ }
+
+ createVnfdConnectionPointRef(obj) {
+ const rsp = this.create();
+ rsp.createVnfdConnectionPointRef(obj);
+ return rsp;
+ }
+
+}
+
+export default DescriptorModelFactory;