001/*
002 * (C) Copyright 2006-2019 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.core.schema;
021
022import org.nuxeo.runtime.RuntimeMessage.Level;
023import org.nuxeo.runtime.RuntimeMessage.Source;
024import org.nuxeo.runtime.RuntimeServiceException;
025import org.nuxeo.runtime.logging.DeprecationLogger;
026import org.nuxeo.runtime.model.ComponentContext;
027import org.nuxeo.runtime.model.ComponentInstance;
028import org.nuxeo.runtime.model.ComponentName;
029import org.nuxeo.runtime.model.DefaultComponent;
030
031/**
032 * The TypeService is the component dealing with registration of schemas and document types (and facets and prefetch
033 * configuration).
034 * <p>
035 * The implementation is delegated to the SchemaManager.
036 */
037public class TypeService extends DefaultComponent {
038
039    private static final String XP_SCHEMA = "schema";
040
041    private static final String XP_DOCTYPE = "doctype";
042
043    private static final String XP_CONFIGURATION = "configuration";
044
045    private static final String XP_DEPRECATION = "deprecation";
046
047    private SchemaManagerImpl schemaManager;
048
049    @Override
050    public void activate(ComponentContext context) {
051        super.activate(context);
052        schemaManager = new SchemaManagerImpl();
053    }
054
055    @Override
056    public void deactivate(ComponentContext context) {
057        super.deactivate(context);
058        schemaManager = null;
059    }
060
061    @Override
062    public void registerContribution(Object contribution, String xp, ComponentInstance component) {
063        switch (xp) {
064        case XP_DOCTYPE:
065            if (contribution instanceof DocumentTypeDescriptor) {
066                schemaManager.registerDocumentType((DocumentTypeDescriptor) contribution);
067            } else if (contribution instanceof FacetDescriptor) {
068                schemaManager.registerFacet((FacetDescriptor) contribution);
069            } else if (contribution instanceof ProxiesDescriptor) {
070                schemaManager.registerProxies((ProxiesDescriptor) contribution);
071            }
072            break;
073        case XP_SCHEMA:
074            if (contribution instanceof SchemaBindingDescriptor) {
075                // use the context of the bundle contributing the extension to load schemas
076                SchemaBindingDescriptor sbd = (SchemaBindingDescriptor) contribution;
077                sbd.context = component.getContext();
078                schemaManager.registerSchema(sbd);
079            } else if (contribution instanceof PropertyDescriptor) {
080                xp = computeSchemaExtensionPoint(contribution.getClass());
081                super.registerContribution(contribution, xp, component);
082            }
083            break;
084        case XP_CONFIGURATION:
085            schemaManager.registerConfiguration((TypeConfiguration) contribution);
086            break;
087        case XP_DEPRECATION:
088            xp = computeSchemaExtensionPoint(PropertyDescriptor.class);
089            PropertyDescriptor contrib = ((PropertyDeprecationDescriptor) contribution).toPropertyDescriptor();
090            super.registerContribution(contrib, xp, component);
091            ComponentName compName = component.getName();
092            String message = String.format(
093                    "Deprecation contribution on component: %s should now be contributed to extension point: %s ",
094                    compName, XP_SCHEMA);
095            DeprecationLogger.log(message, "11.1");
096            addRuntimeMessage(Level.WARNING, message, Source.EXTENSION, compName.getName());
097            break;
098        default:
099            throw new RuntimeServiceException("Unknown extension point: " + xp);
100        }
101    }
102
103    @Override
104    public void unregisterContribution(Object contribution, String xp, ComponentInstance component) {
105        switch (xp) {
106        case XP_DOCTYPE:
107            if (contribution instanceof DocumentTypeDescriptor) {
108                schemaManager.unregisterDocumentType((DocumentTypeDescriptor) contribution);
109            } else if (contribution instanceof FacetDescriptor) {
110                schemaManager.unregisterFacet((FacetDescriptor) contribution);
111            } else if (contribution instanceof ProxiesDescriptor) {
112                schemaManager.unregisterProxies((ProxiesDescriptor) contribution);
113            }
114            break;
115        case XP_SCHEMA:
116            if (contribution instanceof SchemaBindingDescriptor) {
117                schemaManager.unregisterSchema((SchemaBindingDescriptor) contribution);
118            } else if (contribution instanceof PropertyDescriptor) {
119                xp = computeSchemaExtensionPoint(contribution.getClass());
120                super.unregisterContribution(contribution, xp, component);
121            }
122            break;
123        case XP_CONFIGURATION:
124            schemaManager.unregisterConfiguration((TypeConfiguration) contribution);
125            break;
126        case XP_DEPRECATION:
127            xp = computeSchemaExtensionPoint(PropertyDescriptor.class);
128            PropertyDescriptor contrib = ((PropertyDeprecationDescriptor) contribution).toPropertyDescriptor();
129            super.unregisterContribution(contrib, xp, component);
130            break;
131        default:
132            throw new RuntimeServiceException("Unknown extension point: " + xp);
133        }
134    }
135
136    protected String computeSchemaExtensionPoint(Class<?> klass) {
137        return String.format("%s-%s", XP_SCHEMA, klass.getSimpleName());
138    }
139
140    @Override
141    @SuppressWarnings("unchecked")
142    public <T> T getAdapter(Class<T> adapter) {
143        if (SchemaManager.class.isAssignableFrom(adapter)
144                || PropertyCharacteristicHandler.class.isAssignableFrom(adapter)
145                || TypeProvider.class.isAssignableFrom(adapter)) {
146            return (T) schemaManager;
147        }
148        return null;
149    }
150
151    @Override
152    public void start(ComponentContext context) {
153        schemaManager.registerPropertyCharacteristics(
154                getDescriptors(computeSchemaExtensionPoint(PropertyDescriptor.class)));
155        schemaManager.flushPendingsRegistration();
156    }
157
158    @Override
159    public void stop(ComponentContext context) {
160        schemaManager.clearPropertyCharacteristics();
161    }
162
163    @Override
164    public int getApplicationStartedOrder() {
165        return -100;
166    }
167}