001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019package org.apache.isis.viewer.restfulobjects.rendering.service.swagger.internal;
020
021import java.math.BigDecimal;
022import java.math.BigInteger;
023import java.util.Arrays;
024import java.util.List;
025import java.util.Map;
026import java.util.UUID;
027import java.util.function.Supplier;
028
029import javax.inject.Named;
030
031import org.joda.time.DateTime;
032import org.joda.time.LocalDate;
033import org.joda.time.LocalDateTime;
034import org.springframework.beans.factory.annotation.Autowired;
035import org.springframework.stereotype.Component;
036
037import org.apache.isis.commons.internal.base._NullSafe;
038import org.apache.isis.commons.internal.collections._Lists;
039import org.apache.isis.commons.internal.collections._Maps;
040import org.apache.isis.viewer.restfulobjects.rendering.service.swagger.internal.ValuePropertyPlugin.ValuePropertyCollector;
041
042import io.swagger.models.properties.BooleanProperty;
043import io.swagger.models.properties.ByteArrayProperty;
044import io.swagger.models.properties.DateProperty;
045import io.swagger.models.properties.DateTimeProperty;
046import io.swagger.models.properties.DecimalProperty;
047import io.swagger.models.properties.DoubleProperty;
048import io.swagger.models.properties.FloatProperty;
049import io.swagger.models.properties.IntegerProperty;
050import io.swagger.models.properties.LongProperty;
051import io.swagger.models.properties.Property;
052import io.swagger.models.properties.StringProperty;
053import io.swagger.models.properties.UUIDProperty;
054
055@Component
056@Named("isisMetaModel.ValuePropertyFactoryDefault")
057public class ValuePropertyFactoryDefault implements ValuePropertyFactory {
058
059    private final Map<Class<?>, Factory> propertyFactoryByClass = _Maps.newHashMap();
060
061    @Autowired(required = false) private List<ValuePropertyPlugin> valuePropertyPlugins;
062    
063    public static interface Factory extends Supplier<Property> {};
064
065    public ValuePropertyFactoryDefault() {
066
067        propertyFactoryByClass.put(boolean.class, BooleanProperty::new);
068        propertyFactoryByClass.put(Boolean.class, BooleanProperty::new);
069
070        propertyFactoryByClass.put(byte.class, IntegerProperty::new);
071        propertyFactoryByClass.put(Byte.class, IntegerProperty::new);
072        propertyFactoryByClass.put(short.class, IntegerProperty::new);
073        propertyFactoryByClass.put(Short.class, IntegerProperty::new);
074        propertyFactoryByClass.put(int.class, IntegerProperty::new);
075        propertyFactoryByClass.put(Integer.class, IntegerProperty::new);
076        propertyFactoryByClass.put(BigInteger.class, IntegerProperty::new);
077
078        propertyFactoryByClass.put(long.class, LongProperty::new);
079        propertyFactoryByClass.put(Long.class, LongProperty::new);
080        propertyFactoryByClass.put(java.sql.Timestamp.class, LongProperty::new);
081
082        propertyFactoryByClass.put(BigDecimal.class, DecimalProperty::new);
083
084        propertyFactoryByClass.put(float.class, FloatProperty::new);
085        propertyFactoryByClass.put(Float.class, FloatProperty::new);
086
087        propertyFactoryByClass.put(double.class, DoubleProperty::new);
088        propertyFactoryByClass.put(Double.class, DoubleProperty::new);
089
090        propertyFactoryByClass.put(char.class, StringProperty::new);
091        propertyFactoryByClass.put(Character.class, StringProperty::new);
092        propertyFactoryByClass.put(char[].class, StringProperty::new);
093        propertyFactoryByClass.put(String.class, StringProperty::new);
094
095        propertyFactoryByClass.put(UUID.class, UUIDProperty::new);
096
097        propertyFactoryByClass.put(java.util.Date.class, DateTimeProperty::new);
098        propertyFactoryByClass.put(DateTime.class, DateTimeProperty::new);
099        propertyFactoryByClass.put(LocalDateTime.class, DateTimeProperty::new);
100
101        propertyFactoryByClass.put(java.sql.Date.class, DateProperty::new);
102        propertyFactoryByClass.put(LocalDate.class, DateProperty::new);
103
104        propertyFactoryByClass.put(byte[].class, ByteArrayProperty::new);
105        propertyFactoryByClass.put(org.apache.isis.applib.value.Blob.class, ByteArrayProperty::new);
106
107        // add propertyFactories from plugins
108        discoverValueProperties().visitEntries(propertyFactoryByClass::put);
109
110    }
111
112    @Override
113    public Property newProperty(Class<?> cls) {
114        if(cls == null) {
115            return null;
116        }
117
118        final Factory factory = propertyFactoryByClass.get(cls);
119        if(factory != null) {
120            return factory.get();
121        }
122
123        // special case, want to treat as a value
124        if(cls.isEnum()) {
125            final StringProperty property = new StringProperty();
126            final Object[] enumConstants = cls.getEnumConstants();
127
128            final List<String> enumNames = _Lists.map(
129                    Arrays.asList(enumConstants), input->((Enum<?>)input).name());
130            property.setEnum(enumNames);
131            return property;
132        }
133
134        return null;
135    }
136
137    // -- HELPER
138
139    private ValuePropertyCollector discoverValueProperties() {
140        
141        final ValuePropertyCollector collector = ValuePropertyPlugin.collector();
142        _NullSafe.stream(valuePropertyPlugins).forEach(plugin->{
143            plugin.plugin(collector);
144        });
145        return collector;
146    }
147
148}