Java tutorial
/* * * Copyright 2003 - 2016 The eFaps Team * * 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. * */ package org.efaps.admin; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.efaps.admin.common.SystemConfiguration; import org.efaps.admin.datamodel.Type; import org.efaps.admin.event.EventDefinition; import org.efaps.admin.event.EventType; import org.efaps.admin.event.Parameter; import org.efaps.admin.event.Parameter.ParameterValues; import org.efaps.admin.event.Return; import org.efaps.admin.ui.AbstractUserInterfaceObject; import org.efaps.api.IEnumValue; import org.efaps.api.datamodel.Overwrite; import org.efaps.db.Context; import org.efaps.db.transaction.ConnectionResource; import org.efaps.db.wrapper.SQLPart; import org.efaps.db.wrapper.SQLSelect; import org.efaps.util.EFapsException; import org.efaps.util.UUIDUtil; import org.efaps.util.cache.CacheObjectInterface; import org.efaps.util.cache.CacheReloadException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author The eFaps Team * */ public abstract class AbstractAdminObject implements CacheObjectInterface, Serializable { /** * Needed for serialization. */ private static final long serialVersionUID = 1L; /** * Logging instance used in this class. */ private static final Logger LOG = LoggerFactory.getLogger(AbstractAdminObject.class); /** * Select statement to get the properties. */ private static final String SELECT = new SQLSelect().column("NAME").column("VALUE").from("T_CMPROPERTY") .addPart(SQLPart.WHERE).addColumnPart(null, "ABSTRACT").addPart(SQLPart.EQUAL).addValuePart("?") .toString(); /** * The instance variable stores the id of the collections object. * * @see #getId */ private final long id; /** * This is the instance variable for the universal unique identifier of this * admin object. * * @see #getUUID */ private final UUID uuid; /** * This is the instance variable for the name of this admin object. * * @see #setName * @see #getName */ private final String name; /** * This is the instance variable for the properties. * * @getProperties */ private final Map<String, String> properties = new HashMap<>(); /** * All events for this AdminObject are stored in this map. */ private final Map<EventType, List<EventDefinition>> events = new HashMap<>(); /** * checked for events? */ private boolean eventChecked = false; /** * Is this Admin Object dirty, meaning was it altered after first initialization * and it might be necessary to cache it again. */ private boolean dirty = false; /** * Constructor to set instance variables {@link #id}, {@link #uuid} and * {@link #name} of this administrational object. * * @param _id id to set * @param _uuid universal unique identifier * @param _name name to set * @see #id * @see #uuid * @see #name */ protected AbstractAdminObject(final long _id, final String _uuid, final String _name) { this.id = _id; this.uuid = _uuid == null || _uuid.trim().isEmpty() ? null : UUID.fromString(_uuid.trim()); this.name = _name == null ? null : _name.trim(); } /** * Sets the link properties for this object. * * @param _linkTypeUUID UUID of the type of the link property * @param _toId to id * @param _toTypeUUID UUDI of the to type * @param _toName to name * @throws EFapsException on error */ protected void setLinkProperty(final UUID _linkTypeUUID, final long _toId, final UUID _toTypeUUID, final String _toName) throws EFapsException { setDirty(); } /** * The instance method sets all properties of this administrational object. * All properties are stores in instance variable {@link #properties}. * * @param _name name of the property (key) * @param _value value of the property * @see #properties * @throws CacheReloadException on error */ protected void setProperty(final String _name, final String _value) throws CacheReloadException { getProperties().put(_name, _value); setDirty(); } /** * The value of the given property is returned. * * @param _name name of the property (key) * @return value of the property with the given name / key. * @see #properties */ public String getProperty(final String _name) { return evalProperties().get(_name); } /** * The value of the given property is returned. * * @param _enum the enum * @return value of the property with the given name / key. * @see #properties */ public String getProperty(final IEnumValue _enum) { return getProperty(_enum.value()); } /** * The value of the given property is returned. * * @param _name name of the property (key) * @return value of the property with the given name / key. * @see #properties */ public boolean containsProperty(final String _name) { return evalProperties().containsKey(_name); } /** * The value of the given property is returned. * * @param _enum the enum * @return value of the property with the given name / key. * @see #properties */ public boolean containsProperty(final IEnumValue _enum) { return containsProperty(_enum.value()); } /** * @return unmodifiable map of properties */ public Map<String, String> getPropertyMap() { return MapUtils.unmodifiableMap(evalProperties()); } /** * Adds a new event to this AdminObject. * * @param _eventtype Eventtype class name to add * @param _eventdef EventDefinition to add * @see #events * @throws CacheReloadException on error */ public void addEvent(final EventType _eventtype, final EventDefinition _eventdef) throws CacheReloadException { List<EventDefinition> evenList = this.events.get(_eventtype); if (evenList == null) { evenList = new ArrayList<>(); this.events.put(_eventtype, evenList); } if (!evenList.contains(_eventdef)) { evenList.add(_eventdef); } // if there are more than one event they must be sorted by their index // position if (evenList.size() > 1) { Collections.sort(evenList, new Comparator<EventDefinition>() { @Override public int compare(final EventDefinition _eventDef0, final EventDefinition _eventDef1) { return Long.compare(_eventDef0.getIndexPos(), _eventDef1.getIndexPos()); } }); } setDirty(); } /** * Returns the list of events defined for given event type. * * @param _eventType event type * @return list of events for the given event type */ public List<EventDefinition> getEvents(final EventType _eventType) { if (!this.eventChecked) { this.eventChecked = true; try { EventDefinition.addEvents(this); } catch (final EFapsException e) { AbstractAdminObject.LOG.error("Could not read events for Name:; {}', UUID: {}", this.name, this.uuid); } } return this.events.get(_eventType); } /** * Does this instance have Event, for the specified EventType ? * * @param _eventtype type of event to check for * @return <i>true</i>, if this instance has a trigger, otherwise * <i>false</i>. */ public boolean hasEvents(final EventType _eventtype) { if (!this.eventChecked) { this.eventChecked = true; try { EventDefinition.addEvents(this); } catch (final EFapsException e) { AbstractAdminObject.LOG.error("Could not read events for Name:; {}', UUID: {}", this.name, this.uuid); } } return this.events.get(_eventtype) != null; } /** * The method gets all events for the given event type and executes them in * the given order. If no events are defined, nothing is done. * * @param _eventtype type of event to execute * @param _args arguments used as parameter (doubles with first parameters * defining the key, second parameter the value itself) * @return List with Returns * @throws EFapsException on error */ public List<Return> executeEvents(final EventType _eventtype, final Object... _args) throws EFapsException { final List<Return> ret = new ArrayList<>(); if (hasEvents(_eventtype)) { final Parameter param = new Parameter(); if (_args != null) { // add all parameters for (int i = 0; i < _args.length; i += 2) { if (i + 1 < _args.length && _args[i] instanceof ParameterValues) { param.put((ParameterValues) _args[i], _args[i + 1]); } } } ret.addAll(executeEvents(_eventtype, param)); } return ret; } /** * The method gets all events for the given event type and executes them in * the given order. If no events are defined, nothing is done. * * @param _eventtype type of event to execute * @param _param Parameter to be passed to the esjp * @return List with Returns * @throws EFapsException on error */ public List<Return> executeEvents(final EventType _eventtype, final Parameter _param) throws EFapsException { final List<Return> ret = new ArrayList<>(); if (hasEvents(_eventtype)) { if (this instanceof AbstractUserInterfaceObject) { // add ui object to parameter _param.put(ParameterValues.UIOBJECT, this); } // execute all triggers for (final EventDefinition evenDef : this.events.get(_eventtype)) { ret.add(evenDef.execute(_param)); } } return ret; } /** * The instance method reads the properties for this administration object. * Each found property is set with instance method {@link #setProperty}. * * @throws CacheReloadException on error * * @see #setProperty */ protected void readFromDB4Properties() throws CacheReloadException { ConnectionResource con = null; try { con = Context.getThreadContext().getConnectionResource(); final PreparedStatement stmt = con.getConnection().prepareStatement(AbstractAdminObject.SELECT); stmt.setObject(1, getId()); final ResultSet rs = stmt.executeQuery(); AbstractAdminObject.LOG.debug("Reading Properties for '{}'", getName()); while (rs.next()) { final String nameStr = rs.getString(1).trim(); final String value = rs.getString(2).trim(); setProperty(nameStr, value); AbstractAdminObject.LOG.debug(" Name: '{}' - Value: '{}'", new Object[] { nameStr, value }); } rs.close(); stmt.close(); if (con.isOpened()) { con.commit(); } } catch (final SQLException e) { throw new CacheReloadException("could not read properties for " + "'" + getName() + "'", e); } catch (final EFapsException e) { throw new CacheReloadException("could not read properties for " + "'" + getName() + "'", e); } finally { if (con != null && con.isOpened()) { try { con.abort(); } catch (final EFapsException e) { throw new CacheReloadException("could not read properties for " + "'" + getName() + "'", e); } } } } /** * Reads all links for this administration object. Each found link property * is set with instance method {@link setLinkProperty}. * * @throws CacheReloadException on error * @see #setLinkProperty */ protected void readFromDB4Links() throws CacheReloadException { ConnectionResource con = null; try { con = Context.getThreadContext().getConnectionResource(); final SQLSelect select = new SQLSelect().column(0, "TYPEID").column(0, "TOID").column(1, "TYPEID") .column(1, "NAME").from("T_CMABSTRACT2ABSTRACT", 0).leftJoin("T_CMABSTRACT", 1, "ID", 0, "TOID") .addPart(SQLPart.WHERE).addColumnPart(0, "FROMID").addPart(SQLPart.EQUAL).addValuePart(getId()); final Statement stmt = con.getConnection().createStatement(); final ResultSet rs = stmt.executeQuery(select.getSQL()); AbstractAdminObject.LOG.debug("Reading Links for '{}'", getName()); final List<Object[]> values = new ArrayList<>(); while (rs.next()) { final long conTypeId = rs.getLong(1); final long toId = rs.getLong(2); final long toTypeId = rs.getLong(3); final String toName = rs.getString(4); values.add(new Object[] { conTypeId, toId, toTypeId, toName.trim() }); } rs.close(); stmt.close(); con.commit(); for (final Object[] row : values) { final UUID conTypeUUID = Type.getUUID4Id((Long) row[0]); AbstractAdminObject.LOG.debug(" Connection Type UUID: {}", conTypeUUID); final UUID toTypeUUID = Type.getUUID4Id((Long) row[2]); AbstractAdminObject.LOG.debug(" To Type UUID: {}", toTypeUUID); if (conTypeUUID != null && toTypeUUID != null) { setLinkProperty(conTypeUUID, (Long) row[1], toTypeUUID, String.valueOf(row[3])); AbstractAdminObject.LOG.debug(" ID: {}, name: {}", row[1], row[3]); } } } catch (final SQLException e) { throw new CacheReloadException("could not read db links for " + "'" + getName() + "'", e); // CHECKSTYLE:OFF } catch (final RuntimeException e) { // CHECKSTYLE:ON throw new CacheReloadException("could not read db links for " + "'" + getName() + "'", e); } catch (final EFapsException e) { throw new CacheReloadException("could not read properties for " + "'" + getName() + "'", e); } finally { if (con != null && con.isOpened()) { try { con.abort(); } catch (final EFapsException e) { throw new CacheReloadException("could not read properties for " + "'" + getName() + "'", e); } } } } /** * This is the getter method for instance variable {@link #id}. * * @return value of instance variable {@id} * @see #id */ @Override public long getId() { return this.id; } /** * This is the getter method for instance variable {@link #uuid}. * * @return value of instance variable {@uuid} * @see #uuid */ @Override public UUID getUUID() { return this.uuid; } /** * This is the getter method for instance variable {@link #name}. * * @return value of instance variable {@link #name} * @see #name * @see #setName */ @Override public String getName() { return this.name; } /** * This is the getter method for instance variable {@link #properties}. * * @return value of instance variable {@link #properties} * @see #properties */ protected Map<String, String> getProperties() { return this.properties; } /** * This is the getter method for instance variable {@link #properties}. * * @return value of instance variable {@link #properties} * */ protected Map<String, String> evalProperties() { final Map<String, String> ret = getProperties(); try { if (ret.containsKey(Overwrite.SYSTEMCONFIG.value())) { final String sysConfStr = ret.get(Overwrite.SYSTEMCONFIG.value()); final SystemConfiguration sysConfig; if (UUIDUtil.isUUID(sysConfStr)) { sysConfig = SystemConfiguration.get(UUID.fromString(sysConfStr)); } else { sysConfig = SystemConfiguration.get(sysConfStr); } if (sysConfig != null) { final Properties props = sysConfig .getAttributeValueAsProperties(ret.get(Overwrite.ATTRIBUTE.value())); ret.putAll(props.entrySet().stream() .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()))); } } } catch (final EFapsException e) { LOG.error("Catched error on evaluation of Properties.", e); } return ret; } /** * This is the getter method for instance variable {@link #events}. * * @return value of instance variable {@link #events} * @see #events */ protected Map<EventType, List<EventDefinition>> getEvents() { return this.events; } /** * Getter method for the instance variable {@link #dirty}. * * @return value of instance variable {@link #dirty} */ public boolean isDirty() { return this.dirty; } /** * Declare Object as dirty. */ protected void setDirty() { this.dirty = true; } /** * Declare Object as undirty. */ protected void setUndirty() { this.dirty = false; } /** * The method overrides the original method 'toString' and returns the name * of the user interface object. * * @return name of the user interface object */ @Override public String toString() { return new ToStringBuilder(this).append("name", getName()).append("uuid", getUUID()).append("id", getId()) .append("properties", getProperties()).append("events", this.events).toString(); } }