Search in sources :

Example 1 with PropertiesDefinition

use of org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition in project winery by eclipse.

the class BackendUtils method deriveWPD.

/**
 * Derives Winery's Properties Definition from an existing properties definition
 *
 * @param ci     the entity type to try to modify the WPDs
 * @param errors the list to add errors to
 */
public static void deriveWPD(TEntityType ci, List<String> errors) {
    BackendUtils.LOGGER.trace("deriveWPD");
    PropertiesDefinition propertiesDefinition = ci.getPropertiesDefinition();
    QName element = propertiesDefinition.getElement();
    if (element == null) {
        BackendUtils.LOGGER.debug("only works for an element definition, not for types");
    } else {
        BackendUtils.LOGGER.debug("Looking for the definition of {" + element.getNamespaceURI() + "}" + element.getLocalPart());
        // fetch the XSD defining the element
        final XsdImportManager xsdImportManager = RepositoryFactory.getRepository().getXsdImportManager();
        Map<String, RepositoryFileReference> mapFromLocalNameToXSD = xsdImportManager.getMapFromLocalNameToXSD(new Namespace(element.getNamespaceURI(), false), false);
        RepositoryFileReference ref = mapFromLocalNameToXSD.get(element.getLocalPart());
        if (ref == null) {
            String msg = "XSD not found for " + element.getNamespaceURI() + " / " + element.getLocalPart();
            BackendUtils.LOGGER.debug(msg);
            errors.add(msg);
            return;
        }
        final Optional<XSModel> xsModelOptional = BackendUtils.getXSModel(ref);
        if (!xsModelOptional.isPresent()) {
            LOGGER.error("no XSModel found");
        }
        XSModel xsModel = xsModelOptional.get();
        XSElementDeclaration elementDeclaration = xsModel.getElementDeclaration(element.getLocalPart(), element.getNamespaceURI());
        if (elementDeclaration == null) {
            String msg = "XSD model claimed to contain declaration for {" + element.getNamespaceURI() + "}" + element.getLocalPart() + ", but it did not.";
            BackendUtils.LOGGER.debug(msg);
            errors.add(msg);
            return;
        }
        // go through the XSD definition and
        XSTypeDefinition typeDefinition = elementDeclaration.getTypeDefinition();
        if (typeDefinition instanceof XSComplexTypeDefinition) {
            XSComplexTypeDefinition cTypeDefinition = (XSComplexTypeDefinition) typeDefinition;
            XSParticle particle = cTypeDefinition.getParticle();
            if (particle == null) {
                BackendUtils.LOGGER.debug("XSD does not follow the requirements put by winery: Complex type does not contain particles");
            } else {
                XSTerm term = particle.getTerm();
                if (term instanceof XSModelGroup) {
                    XSModelGroup modelGroup = (XSModelGroup) term;
                    if (modelGroup.getCompositor() == XSModelGroup.COMPOSITOR_SEQUENCE) {
                        XSObjectList particles = modelGroup.getParticles();
                        int len = particles.getLength();
                        boolean everyThingIsASimpleType = true;
                        PropertyDefinitionKVList list = new PropertyDefinitionKVList();
                        if (len != 0) {
                            for (int i = 0; i < len; i++) {
                                XSParticle innerParticle = (XSParticle) particles.item(i);
                                XSTerm innerTerm = innerParticle.getTerm();
                                if (innerTerm instanceof XSElementDeclaration) {
                                    XSElementDeclaration innerElementDeclaration = (XSElementDeclaration) innerTerm;
                                    String name = innerElementDeclaration.getName();
                                    XSTypeDefinition innerTypeDefinition = innerElementDeclaration.getTypeDefinition();
                                    if (innerTypeDefinition instanceof XSSimpleType) {
                                        XSSimpleType xsSimpleType = (XSSimpleType) innerTypeDefinition;
                                        String typeNS = xsSimpleType.getNamespace();
                                        String typeName = xsSimpleType.getName();
                                        if (typeNS.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                                            PropertyDefinitionKV def = new PropertyDefinitionKV();
                                            def.setKey(name);
                                            // convention at WPD: use "xsd" as prefix for XML Schema Definition
                                            def.setType("xsd:" + typeName);
                                            list.add(def);
                                        } else {
                                            everyThingIsASimpleType = false;
                                            break;
                                        }
                                    } else {
                                        everyThingIsASimpleType = false;
                                        break;
                                    }
                                } else {
                                    everyThingIsASimpleType = false;
                                    break;
                                }
                            }
                        }
                        if (everyThingIsASimpleType) {
                            // everything went allright, we can add a WPD
                            WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition();
                            wpd.setIsDerivedFromXSD(Boolean.TRUE);
                            wpd.setElementName(element.getLocalPart());
                            wpd.setNamespace(element.getNamespaceURI());
                            wpd.setPropertyDefinitionKVList(list);
                            ModelUtilities.replaceWinerysPropertiesDefinition(ci, wpd);
                            BackendUtils.LOGGER.debug("Successfully generated WPD");
                        } else {
                            BackendUtils.LOGGER.debug("XSD does not follow the requirements put by winery: Not all types in the sequence are simple types");
                        }
                    } else {
                        BackendUtils.LOGGER.debug("XSD does not follow the requirements put by winery: Model group is not a sequence");
                    }
                } else {
                    BackendUtils.LOGGER.debug("XSD does not follow the requirements put by winery: Not a model group");
                }
            }
        } else {
            BackendUtils.LOGGER.debug("XSD does not follow the requirements put by winery: No Complex Type Definition");
        }
    }
}
Also used : XSTypeDefinition(org.apache.xerces.xs.XSTypeDefinition) XSObjectList(org.apache.xerces.xs.XSObjectList) PropertyDefinitionKV(org.eclipse.winery.model.tosca.kvproperties.PropertyDefinitionKV) XSParticle(org.apache.xerces.xs.XSParticle) XSTerm(org.apache.xerces.xs.XSTerm) QName(javax.xml.namespace.QName) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) Namespace(org.eclipse.winery.common.ids.Namespace) HasTargetNamespace(org.eclipse.winery.model.tosca.HasTargetNamespace) XSComplexTypeDefinition(org.apache.xerces.xs.XSComplexTypeDefinition) XSSimpleType(org.apache.xerces.impl.dv.XSSimpleType) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) PropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition) XSElementDeclaration(org.apache.xerces.xs.XSElementDeclaration) XSModel(org.apache.xerces.xs.XSModel) PropertyDefinitionKVList(org.eclipse.winery.model.tosca.kvproperties.PropertyDefinitionKVList) XsdImportManager(org.eclipse.winery.repository.backend.xsd.XsdImportManager) XSModelGroup(org.apache.xerces.xs.XSModelGroup)

Example 2 with PropertiesDefinition

use of org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition in project winery by eclipse.

the class CsarImporter method adjustEntityType.

/**
 * All EntityTypes may contain properties definition. In case a winery properties definition is found, the TOSCA
 * conforming properties definition is removed
 *
 * @param ci      the entity type
 * @param wid     the Winery id of the entitytype
 * @param newDefs the definitions, the entiy type is contained in. The imports might be adjusted here
 * @param errors  Used to collect the errors
 */
private static void adjustEntityType(TEntityType ci, EntityTypeId wid, Definitions newDefs, final List<String> errors) {
    PropertiesDefinition propertiesDefinition = ci.getPropertiesDefinition();
    if (propertiesDefinition != null) {
        WinerysPropertiesDefinition winerysPropertiesDefinition = ModelUtilities.getWinerysPropertiesDefinition(ci);
        boolean deriveWPD;
        if (winerysPropertiesDefinition == null) {
            deriveWPD = true;
        } else {
            if (winerysPropertiesDefinition.getIsDerivedFromXSD() == null) {
                // if the winery's properties are defined by Winery itself,
                // remove the TOSCA conforming properties definition as a Winery properties definition exists (and which takes precedence)
                ci.setPropertiesDefinition(null);
                // no derivation from properties required as the properties are generated by Winery
                deriveWPD = false;
                // we have to remove the import, too
                // Determine the location
                String elementName = winerysPropertiesDefinition.getElementName();
                String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD(wid, null, elementName);
                // remove the import matching that location
                List<TImport> imports = newDefs.getImport();
                boolean found = false;
                if (imports != null) {
                    Iterator<TImport> iterator = imports.iterator();
                    TImport imp;
                    while (iterator.hasNext()) {
                        imp = iterator.next();
                        // TODO: add check for QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE instead of import location. The current routine, however, works, too.
                        if (imp.getLocation().equals(loc)) {
                            found = true;
                            break;
                        }
                    }
                    // noinspection StatementWithEmptyBody
                    if (found) {
                        // imp with Winery's k/v location found
                        iterator.remove();
                        // the XSD has been imported in importOtherImport
                        // it was too difficult to do the location check there, therefore we just remove the XSD from the repository here
                        XSDImportId importId = new XSDImportId(winerysPropertiesDefinition.getNamespace(), elementName, false);
                        try {
                            RepositoryFactory.getRepository().forceDelete(importId);
                        } catch (IOException e) {
                            CsarImporter.LOGGER.debug("Could not delete Winery's generated XSD definition", e);
                            errors.add("Could not delete Winery's generated XSD definition");
                        }
                    } else {
                    // K/V properties definition was incomplete
                    }
                }
            } else {
                // winery's properties are derived from an XSD
                // The export does NOT add an imports statement: only the wpd exists
                // We remove that as
                ModelUtilities.removeWinerysPropertiesDefinition(ci);
                // derive the WPDs again from the properties definition
                deriveWPD = true;
            }
        }
        if (deriveWPD) {
            BackendUtils.deriveWPD(ci, errors);
        }
    }
}
Also used : XSDImportId(org.eclipse.winery.common.ids.definitions.imports.XSDImportId) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) PropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) IOException(java.io.IOException)

Example 3 with PropertiesDefinition

use of org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition in project winery by eclipse.

the class PropertiesDefinitionResource method onJsonPost.

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response onJsonPost(PropertiesDefinitionResourceApiData data) {
    if (data.selectedValue == PropertiesDefinitionEnum.Element || data.selectedValue == PropertiesDefinitionEnum.Type) {
        // first of all, remove Winery's Properties definition (if it exists)
        ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType());
        // replace old properties definition by new one
        PropertiesDefinition def = new PropertiesDefinition();
        if (data.propertiesDefinition.getElement() != null) {
            def.setElement(data.propertiesDefinition.getElement());
        } else if (data.propertiesDefinition.getType() != null) {
            def.setType(data.propertiesDefinition.getType());
        } else {
            return Response.status(Status.BAD_REQUEST).entity("Wrong data submitted!").build();
        }
        this.getEntityType().setPropertiesDefinition(def);
        List<String> errors = new ArrayList<>();
        BackendUtils.deriveWPD(this.getEntityType(), errors);
        // currently the errors are just logged
        for (String error : errors) {
            PropertiesDefinitionResource.LOGGER.debug(error);
        }
        return RestUtils.persist(this.parentRes);
    } else if (data.selectedValue == PropertiesDefinitionEnum.Custom) {
        TEntityType et = this.parentRes.getEntityType();
        // clear current properties definition
        et.setPropertiesDefinition(null);
        // create winery properties definition and persist it
        ModelUtilities.replaceWinerysPropertiesDefinition(et, data.winerysPropertiesDefinition);
        String namespace = data.winerysPropertiesDefinition.getNamespace();
        NamespaceManager namespaceManager = RepositoryFactory.getRepository().getNamespaceManager();
        if (!namespaceManager.hasPrefix(namespace)) {
            namespaceManager.addNamespace(namespace);
        }
        return RestUtils.persist(this.parentRes);
    }
    return Response.status(Status.BAD_REQUEST).entity("Wrong data submitted!").build();
}
Also used : NamespaceManager(org.eclipse.winery.repository.backend.NamespaceManager) TEntityType(org.eclipse.winery.model.tosca.TEntityType) PropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) ArrayList(java.util.ArrayList)

Example 4 with PropertiesDefinition

use of org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition in project winery by eclipse.

the class ToscaExportUtil method writeDefinitionsElement.

/**
 * Writes the Definitions belonging to the given definitgion children to the output stream
 *
 * @return a collection of DefinitionsChildIds referenced by the given component
 * @throws RepositoryCorruptException if tcId does not exist
 */
private Collection<DefinitionsChildId> writeDefinitionsElement(IRepository repository, DefinitionsChildId tcId, OutputStream out) throws JAXBException, RepositoryCorruptException, IOException {
    if (!repository.exists(tcId)) {
        String error = "Component instance " + tcId.toReadableString() + " does not exist.";
        ToscaExportUtil.LOGGER.error(error);
        throw new RepositoryCorruptException(error);
    }
    this.getPrepareForExport(repository, tcId);
    Definitions entryDefinitions = repository.getDefinitions(tcId);
    // BEGIN: Definitions modification
    // the "imports" collection contains the imports of Definitions, not of other definitions
    // the other definitions are stored in entryDefinitions.getImport()
    // we modify the internal definitions object directly. It is not written back to the storage. Therefore, we do not need to clone it
    // the imports (pointing to not-definitions (xsd, wsdl, ...)) already have a correct relative URL. (quick hack)
    URI uri = (URI) this.exportConfiguration.get(ToscaExportUtil.ExportProperties.REPOSITORY_URI.toString());
    if (uri != null) {
        // we are in the plain-XML mode, the URLs of the imports have to be adjusted
        for (TImport i : entryDefinitions.getImport()) {
            String loc = i.getLocation();
            if (!loc.startsWith("../")) {
                LOGGER.warn("Location is not relative for id " + tcId.toReadableString());
            }
            ;
            loc = loc.substring(3);
            loc = uri + loc;
            // now the location is an absolute URL
            i.setLocation(loc);
        }
    }
    // files of imports have to be added to the CSAR, too
    for (TImport i : entryDefinitions.getImport()) {
        String loc = i.getLocation();
        if (Util.isRelativeURI(loc)) {
            // locally stored, add to CSAR
            GenericImportId iid = new GenericImportId(i);
            String fileName = Util.getLastURIPart(loc);
            fileName = Util.URLdecode(fileName);
            RepositoryFileReference ref = new RepositoryFileReference(iid, fileName);
            this.putRefAsReferencedItemInCsar(ref);
        }
    }
    Collection<DefinitionsChildId> referencedDefinitionsChildIds = repository.getReferencedDefinitionsChildIds(tcId);
    // adjust imports: add imports of definitions to it
    Collection<TImport> imports = new ArrayList<>();
    for (DefinitionsChildId id : referencedDefinitionsChildIds) {
        this.addToImports(repository, id, imports);
    }
    entryDefinitions.getImport().addAll(imports);
    if (entryDefinitions.getElement() instanceof TEntityType) {
        TEntityType entityType = (TEntityType) entryDefinitions.getElement();
        // we have an entity type with a possible properties definition
        WinerysPropertiesDefinition wpd = entityType.getWinerysPropertiesDefinition();
        if (wpd != null) {
            if (wpd.getIsDerivedFromXSD() == null) {
                // Write WPD only to file if it exists and is NOT derived from an XSD (which may happen during import)
                String wrapperElementNamespace = wpd.getNamespace();
                String wrapperElementLocalName = wpd.getElementName();
                // BEGIN: add import and put into CSAR
                TImport imp = new TImport();
                entryDefinitions.getImport().add(imp);
                // fill known import values
                imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                imp.setNamespace(wrapperElementNamespace);
                // add "winerysPropertiesDefinition" flag to import tag to support
                Map<QName, String> otherAttributes = imp.getOtherAttributes();
                otherAttributes.put(QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE, "true");
                // Determine location
                String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD((EntityTypeId) tcId, uri, wrapperElementLocalName);
                if (uri == null) {
                    ToscaExportUtil.LOGGER.trace("CSAR Export mode. Putting XSD into CSAR");
                    // CSAR Export mode
                    // XSD has to be put into the CSAR
                    Document document = ModelUtilities.getWinerysPropertiesDefinitionXsdAsDocument(wpd);
                    // loc in import is URLencoded, loc on filesystem isn't
                    String locInCSAR = Util.URLdecode(loc);
                    // furthermore, the path has to start from the root of the CSAR; currently, it starts from Definitions/
                    locInCSAR = locInCSAR.substring(3);
                    ToscaExportUtil.LOGGER.trace("Location in CSAR: {}", locInCSAR);
                    this.referencesToPathInCSARMap.put(new DummyRepositoryFileReferenceForGeneratedXSD(document), locInCSAR);
                }
                imp.setLocation(loc);
                // END: add import and put into CSAR
                // BEGIN: generate TOSCA conforming PropertiesDefinition
                PropertiesDefinition propertiesDefinition = new PropertiesDefinition();
                propertiesDefinition.setType(new QName(wrapperElementNamespace, wrapperElementLocalName));
                entityType.setPropertiesDefinition(propertiesDefinition);
            // END: generate TOSCA conforming PropertiesDefinition
            } else {
            // noinspection StatementWithEmptyBody
            // otherwise WPD exists, but is derived from XSD
            // we DO NOT have to remove the winery properties definition from the output to allow "debugging" of the CSAR
            }
        }
    }
    // END: Definitions modification
    this.writeDefinitionsElement(entryDefinitions, out);
    return referencedDefinitionsChildIds;
}
Also used : TEntityType(org.eclipse.winery.model.tosca.TEntityType) QName(javax.xml.namespace.QName) Definitions(org.eclipse.winery.model.tosca.Definitions) TImport(org.eclipse.winery.model.tosca.TImport) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) Document(org.w3c.dom.Document) URI(java.net.URI) GenericImportId(org.eclipse.winery.common.ids.definitions.imports.GenericImportId) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) PropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) RepositoryCorruptException(org.eclipse.winery.repository.exceptions.RepositoryCorruptException)

Aggregations

PropertiesDefinition (org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition)4 WinerysPropertiesDefinition (org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition)4 QName (javax.xml.namespace.QName)2 RepositoryFileReference (org.eclipse.winery.common.RepositoryFileReference)2 TEntityType (org.eclipse.winery.model.tosca.TEntityType)2 IOException (java.io.IOException)1 URI (java.net.URI)1 ArrayList (java.util.ArrayList)1 XSSimpleType (org.apache.xerces.impl.dv.XSSimpleType)1 XSComplexTypeDefinition (org.apache.xerces.xs.XSComplexTypeDefinition)1 XSElementDeclaration (org.apache.xerces.xs.XSElementDeclaration)1 XSModel (org.apache.xerces.xs.XSModel)1 XSModelGroup (org.apache.xerces.xs.XSModelGroup)1 XSObjectList (org.apache.xerces.xs.XSObjectList)1 XSParticle (org.apache.xerces.xs.XSParticle)1 XSTerm (org.apache.xerces.xs.XSTerm)1 XSTypeDefinition (org.apache.xerces.xs.XSTypeDefinition)1 Namespace (org.eclipse.winery.common.ids.Namespace)1 GenericImportId (org.eclipse.winery.common.ids.definitions.imports.GenericImportId)1 XSDImportId (org.eclipse.winery.common.ids.definitions.imports.XSDImportId)1