1   package com.trendmicro.grid.acl.ds.jpa;
2   
3   import com.trendmicro.grid.acl.ds.jpa.entities.JpaPackageDetails;
4   import com.trendmicro.grid.acl.l0.datatypes.ProcessPackageDataSet;
5   import com.trendmicro.grid.acl.metadata.Metadata;
6   import net.sf.tinyjee.config.PropertySection;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import javax.persistence.EntityManager;
11  import javax.persistence.FlushModeType;
12  import java.util.Collection;
13  import java.util.Date;
14  
15  import static com.trendmicro.grid.acl.ds.jpa.entities.JpaPackageInformation.ROOT_PACKAGE_NAME;
16  import static net.sf.tinyjee.util.Assert.assertNotEmpty;
17  import static net.sf.tinyjee.util.Assert.assertNotNull;
18  
19  /**
20   * Is the abstract base to implementations that handle aspects of the storage of processing results.
21   *
22   * @author juergen_kellerer, 2010-11-22
23   * @version 1.0
24   */
25  public abstract class AbstractReceivedResultsHandler<T> {
26  
27  	private static final Logger log = LoggerFactory.getLogger(AbstractReceivedResultsHandler.class);
28  
29  	/**
30  	 * Defines a storage context for handlers that summarizes the information needed to
31  	 * process a single transaction.
32  	 */
33  	protected static class StorageContext {
34  
35  		protected final EntityManager em;
36  		protected final Collection<ProcessPackageDataSet> receivedDataSets;
37  		protected final boolean ignoreAllUpdates, ignoreNullMetadataUpdates, enableHistoryRecording;
38  
39  		private JpaPackageDetails rootPackageReference;
40  
41  		/**
42  		 * Constructs a new instance bound to the given EntityManager.
43  		 *
44  		 * @param em						the shared entity manager to use to storing the content.
45  		 * @param receivedDataSets		  the received datasets that need to be stored.
46  		 * @param ignoreAllUpdates		  whether handlers should not handle any updates at all.
47  		 * @param ignoreNullMetadataUpdates whether handlers should ignore metadata updates when to null
48  		 *                                  (do not remove existing metadata).
49  		 * @param enableHistoryRecording disable or enable the recording of history data in the history tables
50  		 *                                    (FILE_CONTENT_HISTORY, PACKAGE_HISTORY, PACKAGE_FILES_HISTORY)
51  		 *                                     Default is enabled
52  		 */
53  		public StorageContext(EntityManager em, Collection<ProcessPackageDataSet> receivedDataSets,
54  		                      boolean ignoreAllUpdates, boolean ignoreNullMetadataUpdates, boolean enableHistoryRecording) {
55  			assertNotNull("EntityManager", em);
56  			assertNotEmpty("Collection<ProcessPackageDataSet>", receivedDataSets);
57  
58  			this.em = em;
59  			this.receivedDataSets = receivedDataSets;
60  			this.ignoreAllUpdates = ignoreAllUpdates;
61  			this.ignoreNullMetadataUpdates = ignoreAllUpdates || ignoreNullMetadataUpdates;
62  			this.enableHistoryRecording = enableHistoryRecording;
63  
64  			// Changing flush-mode to COMMIT (dramatically improves performance,
65  			// compared to AUTO when storing large object trees).
66  			if (em.getFlushMode() != FlushModeType.COMMIT)
67  				em.setFlushMode(FlushModeType.COMMIT);
68  		}
69  
70  		/**
71  		 * Returns a reference to the root package if available or 'null'.
72  		 *
73  		 * @param repository the repository to use for retrieving the reference.
74  		 * @return a reference to the root package if available or 'null'.
75  		 */
76  		protected JpaPackageDetails getRootPackageReference(JpaPackageRepository repository) {
77  			if (rootPackageReference == null) {
78  				final Integer rootPk = repository.getPackagePrimaryKeyByName(ROOT_PACKAGE_NAME);
79  				if (rootPk != null)
80  					rootPackageReference = em.getReference(JpaPackageDetails.class, rootPk);
81  			}
82  			return rootPackageReference;
83  		}
84  	}
85  
86  	/**
87  	 * Checks whether the given metadata element can be considered to be null.
88  	 *
89  	 * @param metadata the metadata element to check.
90  	 * @return true if the element equals to 'null'.
91  	 */
92  	protected static boolean isNull(Metadata metadata) {
93  		return metadata == null || metadata.getMetaElements().isEmpty();
94  	}
95  
96  	/**
97  	 * If a null safe compare method for 2 dataes.
98  	 *
99  	 * @param reference   the reference data to verify whether dataToCheck is after it.
100 	 * @param dateToCheck the date the check against reference date.
101 	 * @return true if dateToCheck is after the reference date or when reference == null && dateToCheck != null.
102 	 */
103 	protected static boolean isAfter(Date reference, Date dateToCheck) {
104 		return dateToCheck != null && (reference == null || dateToCheck.after(reference));
105 	}
106 
107 	/**
108 	 * Shortcut to retrieve a boolean value form the given property section.
109 	 *
110 	 * @param section  the section to read from.
111 	 * @param property the key of the value to extract.
112 	 * @return true if the value was set and true.
113 	 */
114 	protected static boolean getValue(PropertySection section, String property) {
115 		try {
116 			return section.getProperty(property).getValue().getBoolean();
117 		} catch (Exception e) {
118 			log.warn("TMACL-01050:Failed getting property {}, using 'false'", property);
119 			return false;
120 		}
121 	}
122 
123 	/**
124 	 * Handles the job in relation to the given storage context.
125 	 *
126 	 * @param context the data set to handle.
127 	 * @return an arbitrary value that may be used by downstream handlers, or 'null' if not relevant.
128 	 */
129 	protected abstract T handle(StorageContext context);
130 }