SchemaServiceImpl.java 7.41 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.xmp.path.XMPPath
 *  com.adobe.xmp.path.XMPPathSegment
 *  com.adobe.xmp.path.XMPPathSegment$Type
 *  com.adobe.xmp.schema.model.ArrayType
 *  com.adobe.xmp.schema.model.PropertyDescription
 *  com.adobe.xmp.schema.model.PropertyType
 *  com.adobe.xmp.schema.model.SchemaDescription
 *  com.adobe.xmp.schema.model.SchemaModelFactory
 *  com.adobe.xmp.schema.model.SimpleType
 *  com.adobe.xmp.schema.model.StructType
 *  com.adobe.xmp.schema.rng.parser.RelaxNGDataModel
 *  com.adobe.xmp.schema.rng.parser.SchemaGenerationHandler
 */
package com.adobe.xmp.schema.service.impl;

import com.adobe.xmp.path.XMPPath;
import com.adobe.xmp.path.XMPPathSegment;
import com.adobe.xmp.schema.model.ArrayType;
import com.adobe.xmp.schema.model.PropertyDescription;
import com.adobe.xmp.schema.model.PropertyType;
import com.adobe.xmp.schema.model.SchemaDescription;
import com.adobe.xmp.schema.model.SchemaModelFactory;
import com.adobe.xmp.schema.model.SimpleType;
import com.adobe.xmp.schema.model.StructType;
import com.adobe.xmp.schema.rng.parser.RelaxNGDataModel;
import com.adobe.xmp.schema.rng.parser.SchemaGenerationHandler;
import com.adobe.xmp.schema.service.RelaxNGProvider;
import com.adobe.xmp.schema.service.SchemaCache;
import com.adobe.xmp.schema.service.SchemaService;
import com.adobe.xmp.schema.service.SchemaServiceException;
import com.adobe.xmp.schema.service.impl.DefaultEntityResolver;
import com.adobe.xmp.schema.service.impl.RuntimeDecoratorUtil;
import com.adobe.xmp.schema.service.impl.SchemaGenerationHandlerImpl;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.namespace.QName;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class SchemaServiceImpl
implements SchemaService {
    private RelaxNGProvider provider;
    private SchemaCache cache;

    public SchemaServiceImpl(RelaxNGProvider provider, SchemaCache cache) throws SchemaServiceException {
        if (provider == null || cache == null) {
            throw new SchemaServiceException("Parameters must not be null.");
        }
        this.provider = provider;
        this.cache = cache;
    }

    public SchemaDescription getSchemaForURI(String namespaceURI) throws SchemaServiceException {
        SchemaDescription result = this.cache.get(namespaceURI);
        if (result == null && (result = this.parseSchema(namespaceURI)) != null) {
            this.cache.put(namespaceURI, result);
        }
        return result;
    }

    private SchemaDescription parseSchema(String namespaceURI) throws SchemaServiceException {
        SchemaDescription result = null;
        try {
            if (this.provider.isAvailable(namespaceURI)) {
                InputStream rngSource = this.provider.getSchema(namespaceURI);
                DefaultEntityResolver dependencyResolver = new DefaultEntityResolver(this.provider);
                InputSource rngInput = new InputSource(rngSource);
                RelaxNGDataModel dataModel = RelaxNGDataModel.newInstance((InputSource)rngInput, (EntityResolver)dependencyResolver);
                result = dataModel.constructXMPSchema((SchemaGenerationHandler)new SchemaGenerationHandlerImpl(false, null));
                this.handleRuntimeDecorators(result);
            }
        }
        catch (Exception e) {
            throw new SchemaServiceException(e.getMessage());
        }
        return result;
    }

    public PropertyType getType(XMPPath propPath) throws SchemaServiceException {
        if (propPath == null || propPath.size() == 0) {
            throw new IllegalArgumentException("'propPath' must not be null or empty.");
        }
        PropertyType result = null;
        int lastIndex = propPath.size() - 1;
        PropertyDescription property = this.getProperty(propPath);
        if (property != null) {
            result = property.getType() instanceof ArrayType && propPath.get(lastIndex).getType() == XMPPathSegment.Type.ARRAY_INDEX ? ((ArrayType)property.getType()).getItemType() : property.getType();
        }
        return result;
    }

    public PropertyDescription getProperty(XMPPath propPath) throws SchemaServiceException {
        if (propPath == null || propPath.size() == 0) {
            throw new IllegalArgumentException("'propPath' must not be null or empty.");
        }
        PropertyType currentType = null;
        PropertyDescription currentProp = null;
        for (int i = 0; i < propPath.size(); ++i) {
            XMPPathSegment segment = propPath.get(i);
            if (i == 0) {
                SchemaDescription schema = this.getSchemaForURI(segment.getNamespace());
                if (schema != null) {
                    currentProp = schema.getProperty(segment.getName());
                }
                if (currentProp != null) {
                    currentType = currentProp.getType();
                    continue;
                }
                currentProp = null;
                break;
            }
            if (currentType instanceof SimpleType) {
                currentProp = null;
                break;
            }
            if (currentType instanceof StructType) {
                if (segment.getType() != XMPPathSegment.Type.ARRAY_INDEX) {
                    currentProp = ((StructType)currentType).getField(segment.getNamespace(), segment.getName());
                    if (currentProp != null) {
                        currentType = currentProp.getType();
                        continue;
                    }
                    currentProp = null;
                    break;
                }
                throw new SchemaServiceException("Structs cannot have array items: '" + propPath.serialize() + "'.");
            }
            if (!(currentType instanceof ArrayType)) continue;
            if (segment.getType() == XMPPathSegment.Type.ARRAY_INDEX) {
                currentType = ((ArrayType)currentType).getItemType();
                continue;
            }
            throw new SchemaServiceException("After array types only an index [] may follow: '" + propPath.serialize() + "'.");
        }
        return currentProp;
    }

    public SchemaDescription parseRelaxNG(InputStream input, SchemaService.INamespaceCallback namespaceCallback) throws SchemaServiceException {
        try {
            InputSource rngInput = new InputSource(input);
            EntityResolver dependencyResolver = new EntityResolver(){

                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                    throw new UnsupportedOperationException("Includes are not allowed in this function.");
                }
            };
            RelaxNGDataModel dataModel = RelaxNGDataModel.newInstance((InputSource)rngInput, (EntityResolver)dependencyResolver);
            SchemaDescription result = dataModel.constructXMPSchema((SchemaGenerationHandler)new SchemaGenerationHandlerImpl(false, namespaceCallback));
            this.handleRuntimeDecorators(result);
            return result;
        }
        catch (Exception e) {
            throw new SchemaServiceException(e.getMessage(), e);
        }
    }

    private void handleRuntimeDecorators(SchemaDescription schema) throws SchemaServiceException {
        if (!SchemaModelFactory.supportRuntimeDecorators) {
            return;
        }
        RuntimeDecoratorUtil.process(schema, this.provider.getRuntimeDecorators());
    }

}