| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 |
| * <p/> |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * <p/> |
| * 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. |
| */ |
| |
| package org.apache.atlas.catalog.definition; |
| |
| import org.apache.atlas.AtlasException; |
| import org.apache.atlas.catalog.*; |
| import org.apache.atlas.catalog.exception.CatalogRuntimeException; |
| import org.apache.atlas.catalog.exception.InvalidPayloadException; |
| import org.apache.atlas.catalog.projection.Projection; |
| import org.apache.atlas.catalog.projection.Relation; |
| import org.apache.atlas.typesystem.types.AttributeDefinition; |
| import org.apache.atlas.typesystem.types.AttributeInfo; |
| import org.apache.atlas.typesystem.types.Multiplicity; |
| import org.apache.atlas.typesystem.types.TypeSystem; |
| |
| import java.util.*; |
| |
| /** |
| * Base class for resource definitions. |
| */ |
| public abstract class BaseResourceDefinition implements ResourceDefinition { |
| protected static final TypeSystem typeSystem = TypeSystem.getInstance(); |
| |
| protected final Set<String> instanceProperties = new HashSet<>(); |
| protected final Set<String> collectionProperties = new HashSet<>(); |
| protected Map<String, AttributeDefinition> propertyDefs = new HashMap<>(); |
| protected Map<String, AttributeInfo> properties = new HashMap<>(); |
| |
| protected final Map<String, Projection> projections = new HashMap<>(); |
| protected final Map<String, Relation> relations = new HashMap<>(); |
| |
| protected final PropertyMapper propertyMapper; |
| protected final Map<String, PropertyValueFormatter> propertyValueFormatters = new HashMap<>(); |
| |
| |
| public BaseResourceDefinition() { |
| DefaultDateFormatter defaultDateFormatter = new DefaultDateFormatter(); |
| registerPropertyValueFormatter("creation_time", defaultDateFormatter); |
| registerPropertyValueFormatter("modified_time", defaultDateFormatter); |
| |
| this.propertyMapper = createPropertyMapper(); |
| } |
| |
| @Override |
| public void validateCreatePayload(Request request) throws InvalidPayloadException { |
| Collection<String> propKeys = new HashSet<>(request.getQueryProperties().keySet()); |
| Collection<String> missingProperties = new HashSet<>(); |
| for (AttributeInfo property : properties.values()) { |
| String name = property.name; |
| if (property.multiplicity == Multiplicity.REQUIRED) { |
| if (request.getProperty(name) == null) { |
| missingProperties.add(name); |
| } |
| } |
| propKeys.remove(name); |
| } |
| if (! missingProperties.isEmpty() || ! propKeys.isEmpty()) { |
| throw new InvalidPayloadException(missingProperties, propKeys); |
| } |
| //todo: property type validation |
| } |
| |
| @Override |
| public void validateUpdatePayload(Request request) throws InvalidPayloadException { |
| Collection<String> updateKeys = new HashSet<>(request.getUpdateProperties().keySet()); |
| Collection<String> validProperties = new HashSet<>(properties.keySet()); |
| // currently updating 'name' property for any resource is unsupported |
| validProperties.remove("name"); |
| updateKeys.removeAll(validProperties); |
| |
| if (! updateKeys.isEmpty()) { |
| throw new InvalidPayloadException(Collections.<String>emptySet(), updateKeys); |
| } |
| } |
| |
| @Override |
| public Collection<AttributeDefinition> getPropertyDefinitions() { |
| return propertyDefs.values(); |
| } |
| |
| @Override |
| public Map<String, Object> filterProperties(Request request, Map<String, Object> propertyMap) { |
| Request.Cardinality cardinality = request.getCardinality(); |
| Collection<String> requestProperties = request.getAdditionalSelectProperties(); |
| Iterator<Map.Entry<String, Object>> propIter = propertyMap.entrySet().iterator(); |
| while(propIter.hasNext()) { |
| Map.Entry<String, Object> propEntry = propIter.next(); |
| String prop = propEntry.getKey(); |
| if (! requestProperties.contains(prop)) { |
| if (cardinality == Request.Cardinality.COLLECTION) { |
| if (! collectionProperties.contains(prop)) { |
| propIter.remove(); |
| } |
| } else { |
| if (! instanceProperties.isEmpty() && ! instanceProperties.contains(prop)) { |
| propIter.remove(); |
| } |
| } |
| } |
| } |
| return propertyMap; |
| } |
| |
| @Override |
| public Map<String, Projection> getProjections() { |
| return projections; |
| } |
| |
| @Override |
| public Map<String, Relation> getRelations() { |
| return relations; |
| } |
| |
| |
| @Override |
| public synchronized PropertyMapper getPropertyMapper() { |
| return propertyMapper; |
| } |
| |
| @Override |
| public Map<String, PropertyValueFormatter> getPropertyValueFormatters() { |
| return propertyValueFormatters; |
| } |
| |
| protected void registerProperty(AttributeDefinition propertyDefinition) { |
| try { |
| propertyDefs.put(propertyDefinition.name, propertyDefinition); |
| properties.put(propertyDefinition.name, new AttributeInfo(typeSystem, propertyDefinition, null)); |
| } catch (AtlasException e) { |
| throw new CatalogRuntimeException("Unable to create attribute: " + propertyDefinition.name, e); |
| } |
| } |
| |
| protected void registerPropertyValueFormatter(String property, PropertyValueFormatter valueFormatter) { |
| propertyValueFormatters.put(property, valueFormatter); |
| } |
| |
| /** |
| * Create a new property mapper instance. |
| * Should be overridden in children where the default implementation isn't sufficient. |
| * |
| * @return a new property mapper instance |
| */ |
| protected PropertyMapper createPropertyMapper() { |
| return new DefaultPropertyMapper(); |
| } |
| } |