001/* 002 * Stallion Core: A Modern Web Framework 003 * 004 * Copyright (C) 2015 - 2016 Stallion Software LLC. 005 * 006 * This program is free software: you can redistribute it and/or modify it under the terms of the 007 * GNU General Public License as published by the Free Software Foundation, either version 2 of 008 * the License, or (at your option) any later version. This program is distributed in the hope that 009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 011 * License for more details. You should have received a copy of the GNU General Public License 012 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. 013 * 014 * 015 * 016 */ 017 018package io.stallion.dataAccess; 019 020import com.fasterxml.jackson.annotation.JsonIgnore; 021import io.stallion.reflection.PropertyUtils; 022//import org.apache.commons.beanutils.PropertyUtils; 023 024import java.math.BigInteger; 025import java.util.Collection; 026import java.util.HashMap; 027import java.util.Map; 028import java.util.Set; 029 030 031/** 032 * A Model subclass that implements the Map interface and accepts arbitrary 033 * key/value data. This is used by server-side Javascript plugins, which 034 * cannot define standard Java pojos, and this is used to add custom data 035 * to pages, posts, or other objects that are created via text files, 036 * without having go into creating a Java project and writing out classes 037 * that contain the fields. 038 * 039 */ 040public interface MappedModel extends Map<String, Object> { 041 //private Map<String, Object> attributes = new HashMap<String, Object>(); 042 043 public default int size() { 044 return toCompleteMap().size(); 045 } 046 047 @JsonIgnore 048 public default boolean isEmpty() { 049 return toCompleteMap().isEmpty(); 050 } 051 052 053 public default boolean containsKey(String key) { 054 return getAttributes().containsKey(key) || PropertyUtils.isReadable(this, key); 055 } 056 057 public default boolean containsKey(Object key) { 058 return getAttributes().containsKey(key) || PropertyUtils.isReadable(this, key.toString()); 059 } 060 061 062 public default boolean containsValue(Object value) { 063 return getAttributes().containsValue(value); 064 } 065 066 067 public default Object get(Object key) { 068 try { 069 if (PropertyUtils.isReadable(this, key.toString())) { 070 071 return PropertyUtils.getProperty(this, key.toString()); 072 } 073 074 return getAttributes().get(key); 075 } catch (Exception ex) { 076 throw new RuntimeException(ex); 077 } 078 } 079 080 public default Object put(String key, Object value) { 081 try { 082 if (key.equals("id") || key.equals("lastModifiedMillis") && !(value instanceof Long)) { 083 if (value instanceof Double) { 084 value = ((Double) value).longValue(); 085 } else if (value instanceof Integer) { 086 value = ((Integer) value).longValue(); 087 } else if (value instanceof Float) { 088 value = ((Float) value).longValue(); 089 } else if (value instanceof BigInteger) { 090 value = ((BigInteger) value).longValue(); 091 } 092 093 } 094 if (PropertyUtils.isWriteable(this, key)) { 095 Class cls = null; 096 if (value != null) { 097 cls = value.getClass(); 098 } 099 PropertyUtils.setProperty(this, key, value); 100 return null; 101 } else { 102 return getAttributes().put(key, value); 103 } 104 } catch (Exception ex) { 105 throw new RuntimeException(ex); 106 } 107 } 108 109 110 public default Object remove(Object obj) { 111 return getAttributes().remove(obj); 112 } 113 114 115 public default void putAll(Map<? extends String, ? extends Object> m) { 116 getAttributes().putAll(m); 117 } 118 119 120 public default void clear() { 121 122 } 123 124 public default Set<String> keySet() { 125 return toCompleteMap().keySet(); 126 } 127 128 129 public default Collection<Object> values() { 130 return toCompleteMap().values(); 131 } 132 133 134 public default Set<Map.Entry<String, Object>> entrySet() { 135 return toCompleteMap().entrySet(); 136 } 137 138 default Map<String, Object> toCompleteMap() { 139 Map map = PropertyUtils.getProperties(this, JsonIgnore.class); 140 for(Map.Entry<String, Object> entry: getAttributes().entrySet()) { 141 map.put(entry.getKey(), entry.getValue()); 142 } 143 return map; 144 } 145 146 @JsonIgnore 147 public Map<String, Object> getAttributes(); 148 149 public void setAttributes(Map<String, Object> attributes); 150 151}