001/*
002 * (C) Copyright 2006-2014 Nuxeo SA (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.api.model.impl;
021
022import static org.nuxeo.ecm.core.api.model.impl.AbstractProperty.IS_DEPRECATED;
023import static org.nuxeo.ecm.core.api.model.impl.AbstractProperty.IS_SECURED;
024
025import java.util.stream.IntStream;
026
027import org.nuxeo.ecm.core.api.model.Property;
028import org.nuxeo.ecm.core.api.model.impl.primitives.BinaryProperty;
029import org.nuxeo.ecm.core.api.model.impl.primitives.BlobProperty;
030import org.nuxeo.ecm.core.api.model.impl.primitives.BooleanProperty;
031import org.nuxeo.ecm.core.api.model.impl.primitives.DateProperty;
032import org.nuxeo.ecm.core.api.model.impl.primitives.DoubleProperty;
033import org.nuxeo.ecm.core.api.model.impl.primitives.ExternalBlobProperty;
034import org.nuxeo.ecm.core.api.model.impl.primitives.LongProperty;
035import org.nuxeo.ecm.core.api.model.impl.primitives.StringProperty;
036import org.nuxeo.ecm.core.schema.PropertyCharacteristicHandler;
037import org.nuxeo.ecm.core.schema.TypeConstants;
038import org.nuxeo.ecm.core.schema.types.Field;
039import org.nuxeo.ecm.core.schema.types.ListType;
040import org.nuxeo.ecm.core.schema.types.SimpleTypeImpl;
041import org.nuxeo.ecm.core.schema.types.Type;
042import org.nuxeo.ecm.core.schema.types.primitives.BinaryType;
043import org.nuxeo.ecm.core.schema.types.primitives.BooleanType;
044import org.nuxeo.ecm.core.schema.types.primitives.DateType;
045import org.nuxeo.ecm.core.schema.types.primitives.DoubleType;
046import org.nuxeo.ecm.core.schema.types.primitives.IntegerType;
047import org.nuxeo.ecm.core.schema.types.primitives.LongType;
048import org.nuxeo.ecm.core.schema.types.primitives.StringType;
049import org.nuxeo.runtime.api.Framework;
050
051/**
052 * The default property factory singleton.
053 */
054public class PropertyFactory {
055
056    private PropertyFactory() {
057        // utility class
058    }
059
060    public static Property createProperty(Property parent, Field field, int flags) {
061        flags = computePropertyFlags(parent, field, flags);
062        Type type = field.getType();
063        if (type instanceof SimpleTypeImpl) {
064            // type with constraint
065            type = type.getSuperType();
066        }
067        switch (type.getName()) {
068        case StringType.ID:
069            return new StringProperty(parent, field, flags);
070        case IntegerType.ID:
071        case LongType.ID:
072            return new LongProperty(parent, field, flags);
073        case DoubleType.ID:
074            return new DoubleProperty(parent, field, flags);
075        case BooleanType.ID:
076            return new BooleanProperty(parent, field, flags);
077        case DateType.ID:
078            return new DateProperty(parent, field, flags);
079        case BinaryType.ID:
080            return new BinaryProperty(parent, field, flags);
081        case TypeConstants.CONTENT:
082            return new BlobProperty(parent, field, flags);
083        case TypeConstants.EXTERNAL_CONTENT:
084            return new ExternalBlobProperty(parent, field, flags);
085        }
086        if (type.isSimpleType()) {
087            return new ScalarProperty(parent, field, flags);
088        } else if (type.isComplexType()) {
089            return new MapProperty(parent, field, flags);
090        } else if (type.isListType()) {
091            if (((ListType) type).isArray()) {
092                return new ArrayProperty(parent, field, flags);
093            } else {
094                return new ListProperty(parent, field, flags);
095            }
096        } else {
097            throw new IllegalArgumentException("Unsupported field type: " + field.getType().getName());
098        }
099    }
100
101    protected static int computePropertyFlags(Property parent, Field field, int flags) {
102        // check if property to create has flags to inherit from parent or configuration
103        if (parent instanceof AbstractProperty) { // should always be the case
104            // compute inherit flags from parent
105            flags |= IntStream.of(IS_SECURED, IS_DEPRECATED)
106                              .filter(((AbstractProperty) parent)::areFlagsSet)
107                              .reduce(0, (f1, f2) -> f1 | f2);
108            // if parent is not secured or deprecated, compute characteristics for current property
109            if ((flags & IS_SECURED) == 0 || (flags & IS_DEPRECATED) == 0) {
110                String schemaName = parent.getSchema().getName();
111                StringBuilder xpathBuilder = new StringBuilder();
112                if (parent.getParent() != null) {
113                    xpathBuilder.append(parent.getXPath()).append('/');
114                }
115                xpathBuilder.append(field.getName().getLocalName());
116                String xpath = xpathBuilder.toString();
117
118                PropertyCharacteristicHandler propertyHandler = Framework.getService(
119                        PropertyCharacteristicHandler.class);
120                if ((flags & IS_SECURED) == 0 && propertyHandler.isSecured(schemaName, xpath)) {
121                    flags |= IS_SECURED;
122                }
123                if ((flags & IS_DEPRECATED) == 0 && propertyHandler.isDeprecated(schemaName, xpath)) {
124                    flags |= IS_DEPRECATED;
125                }
126            }
127        }
128        return flags;
129    }
130
131}