All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidoid.beany.BeanProperties Maven / Gradle / Ivy

There is a newer version: 5.5.5
Show newest version
/*-
 * #%L
 * rapidoid-commons
 * %%
 * Copyright (C) 2014 - 2018 Nikolche Mihajlovski and contributors
 * %%
 * Licensed 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
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * 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.
 * #L%
 */

package org.rapidoid.beany;

import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.cls.Cls;
import org.rapidoid.collection.Coll;
import org.rapidoid.lambda.Lmbd;
import org.rapidoid.lambda.Mapper;
import org.rapidoid.u.U;
import org.rapidoid.util.Msc;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;


@Authors("Nikolche Mihajlovski")
@Since("2.0.0")
public class BeanProperties extends RapidoidThing implements Iterable {

	@SuppressWarnings("unchecked")
	public static BeanProperties NONE = new BeanProperties(Collections.EMPTY_MAP);

	public final Map map;

	public final Map lowercaseMap;

	public final List props;

	public final List names;

	public final ConcurrentMap extras = Coll.concurrentMap();

	public final Map selections = Coll
		.autoExpandingMap(new Mapper() {
			@Override
			public BeanProperties map(PropertySelector selector) throws Exception {

				Set include = selector.include();
				Set exclude = selector.exclude();

				List selected = new ArrayList(10);

				for (String propName : include) {
					Prop prop = map.get(propName);

					if (prop == null) {
						if (JSProp.is(propName)) {
							prop = new JSProp(propName);

						} else if (ActionsProp.is(propName)) {
							prop = new ActionsProp();

						} else {
							throw U.rte("Cannot find property '%s'!", propName);
						}
					}

					if (!veto(prop) && Lmbd.eval(selector, prop) && Lmbd.eval(selector, prop)) {
						selected.add(prop);
					}
				}

				if (U.notEmpty(exclude) || U.isEmpty(include)) {
					for (Prop prop : map.values()) {
						if (!veto(prop) && !selected.contains(prop) && !exclude.contains(prop.getName()) && Lmbd.eval(selector, prop)) {
							selected.add(prop);
						}
					}
				}

				if (U.isEmpty(include)) {
					Collections.sort(selected, selector);
				}

				return from(selected);
			}
		});

	private boolean veto(Prop prop) {
		return prop.getName().equalsIgnoreCase("clone");
	}

	public BeanProperties(Map properties) {
		this.map = Collections.unmodifiableMap(properties);
		this.lowercaseMap = Msc.lowercase(map);
		this.props = Collections.unmodifiableList(U.list(properties.values()));
		this.names = Collections.unmodifiableList(U.list(properties.keySet()));
	}

	@Override
	public Iterator iterator() {
		return props.iterator();
	}

	public Prop get(String property) {
		Prop prop = map.get(property);

		if (prop == null) {
			prop = lowercaseMap.get(property.toLowerCase());
		}

		return prop;
	}

	public BeanProperties select(PropertySelector selector) {
		return selections.get(selector);
	}

	public BeanProperties annotated(Class annotated) {
		return select(new AnnotatedPropertyFilter(annotated));
	}

	@Override
	public String toString() {
		return "BeanProperties [map=" + map + ", selections=" + selections + "]";
	}

	public static BeanProperties from(List properties) {
		Map map = Coll.synchronizedMap();

		for (Prop prop : properties) {
			map.put(prop.getName(), prop);
		}

		return new BeanProperties(map);
	}

	public static BeanProperties from(Map map) {
		Map properties = Coll.synchronizedMap();

		for (Entry e : map.entrySet()) {
			Object key = e.getKey();
			Prop prop = new MapProp(String.valueOf(key), key, Cls.of(e.getValue()));
			properties.put(prop.getName(), prop);
		}

		return new BeanProperties(properties);
	}

	public int size() {
		return map.size();
	}

	public boolean isEmpty() {
		return map.isEmpty();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy