Java tutorial
/* * Copyright (C) 2006-2016 Talend Inc. - www.talend.com * * This source code is available under agreement available at * %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt * * You should have received a copy of the agreement along with this program; if not, write to Talend SA 9 rue Pages * 92150 Suresnes, France */ package com.amalto.core.storage; import static com.amalto.core.query.user.UserQueryBuilder.eq; import static com.amalto.core.query.user.UserQueryBuilder.from; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.talend.mdm.commmon.metadata.ComplexTypeMetadata; import org.talend.mdm.commmon.metadata.ContainedComplexTypeMetadata; import org.talend.mdm.commmon.metadata.DefaultMetadataVisitor; import org.talend.mdm.commmon.metadata.FieldMetadata; import org.talend.mdm.commmon.metadata.MetadataRepository; import org.talend.mdm.commmon.metadata.MetadataVisitor; import org.talend.mdm.commmon.metadata.TypeMetadata; import org.talend.mdm.commmon.util.webapp.XSystemObjects; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import com.amalto.core.metadata.ClassRepository; import com.amalto.core.objects.ObjectPOJO; import com.amalto.core.query.user.Select; import com.amalto.core.query.user.UserQueryBuilder; import com.amalto.core.server.StorageAdmin; import com.amalto.core.storage.record.DataRecord; import com.amalto.core.storage.record.DataRecordReader; import com.amalto.core.storage.record.XmlDOMDataRecordReader; import com.amalto.core.storage.record.XmlSAXDataRecordReader; import com.amalto.xmlserver.interfaces.ItemPKCriteria; import com.amalto.xmlserver.interfaces.XmlServerException; public class SystemStorageWrapper extends StorageWrapper { private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); private static final String SYSTEM_PREFIX = "amaltoOBJECTS"; //$NON-NLS-1$ private static final String CUSTOM_FORM_TYPE = "custom-form-pOJO"; //$NON-NLS-1$ private static final String DROPPED_ITEM_TYPE = "dropped-item-pOJO"; //$NON-NLS-1$ private static final String COMPLETED_ROUTING_ORDER = "completed-routing-order-v2-pOJO"; //$NON-NLS-1$ private static final String FAILED_ROUTING_ORDER = "failed-routing-order-v2-pOJO"; //$NON-NLS-1$ private static final String SYNCHRONIZATION_OBJECT_TYPE = "synchronization-object-pOJO"; //$NON-NLS-1$ private static final String BROWSEITEM_PREFIX_INFO = "SearchTemplate.BrowseItem."; //$NON-NLS-1$ private static final Logger LOGGER = Logger.getLogger(SystemStorageWrapper.class); public SystemStorageWrapper() { DOCUMENT_BUILDER_FACTORY.setNamespaceAware(true); // Create "system" storage StorageAdmin admin = getStorageAdmin(); if (!admin.exist(StorageAdmin.SYSTEM_STORAGE, StorageType.SYSTEM)) { String datasource = admin.getDatasource(StorageAdmin.SYSTEM_STORAGE); admin.create(StorageAdmin.SYSTEM_STORAGE, StorageAdmin.SYSTEM_STORAGE, StorageType.SYSTEM, datasource); } } private ComplexTypeMetadata getType(String clusterName, Storage storage, String uniqueID) { MetadataRepository repository = storage.getMetadataRepository(); if (uniqueID != null && uniqueID.startsWith("amalto_local_service_")) { //$NON-NLS-1$ return repository.getComplexType("service-bMP"); //$NON-NLS-1$ } if (clusterName.startsWith(SYSTEM_PREFIX) || clusterName.startsWith("amalto")) { //$NON-NLS-1$ if (!"amaltoOBJECTSservices".equals(clusterName)) { //$NON-NLS-1$ return repository.getComplexType( ClassRepository.format(clusterName.substring(SYSTEM_PREFIX.length()) + "POJO")); //$NON-NLS-1$ } else { return repository .getComplexType(ClassRepository.format(clusterName.substring(SYSTEM_PREFIX.length()))); } } if (XSystemObjects.DC_MDMITEMSTRASH.getName().equals(clusterName)) { return repository.getComplexType(DROPPED_ITEM_TYPE); } else if (XSystemObjects.DC_PROVISIONING.getName().equals(clusterName)) { String typeName = getTypeName(uniqueID); if ("Role".equals(typeName)) { //$NON-NLS-1$ return repository.getComplexType("role-pOJO"); //$NON-NLS-1$ } return repository.getComplexType(typeName); } else if ("MDMDomainObjects".equals(clusterName) || "MDMItemImages".equals(clusterName) //$NON-NLS-1$//$NON-NLS-2$ || "FailedAutoCommitSvnMessage".equals(clusterName)) { //$NON-NLS-1$ return null; // Documents for these clusters don't have a predefined structure. } // No id, so no type to be read. if (uniqueID == null) { return null; } // MIGRATION.completed.record return repository.getComplexType(getTypeName(uniqueID)); } @Override public List<String> getItemPKsByCriteria(ItemPKCriteria criteria) throws XmlServerException { String clusterName = criteria.getClusterName(); Storage storage = getStorage(clusterName); MetadataRepository repository = storage.getMetadataRepository(); int totalCount = 0; List<String> itemPKResults = new LinkedList<String>(); String typeName = criteria.getConceptName(); try { storage.begin(); if (typeName != null && !typeName.isEmpty()) { String internalTypeName = typeName; String objectRootElementName = ObjectPOJO.getObjectRootElementName(typeName); if (objectRootElementName != null) { internalTypeName = objectRootElementName; } totalCount = getTypeItemCount(criteria, repository.getComplexType(internalTypeName), storage); itemPKResults.addAll( getTypeItems(criteria, repository.getComplexType(internalTypeName), storage, typeName)); } else { // TMDM-4651: Returns type in correct dependency order. Collection<ComplexTypeMetadata> types = getClusterTypes(clusterName); int maxCount = criteria.getMaxItems(); if (criteria.getSkip() < 0) { // MDM Studio may send negative values criteria.setSkip(0); } List<String> currentInstanceResults; String objectRootElementName; for (ComplexTypeMetadata type : types) { String internalTypeName = type.getName(); objectRootElementName = ObjectPOJO.getObjectRootElementName(internalTypeName); if (objectRootElementName != null) { internalTypeName = objectRootElementName; } int count = getTypeItemCount(criteria, repository.getComplexType(internalTypeName), storage); totalCount += count; if (itemPKResults.size() < maxCount) { if (count > criteria.getSkip()) { currentInstanceResults = getTypeItems(criteria, repository.getComplexType(internalTypeName), storage, type.getName()); int n = maxCount - itemPKResults.size(); if (n <= currentInstanceResults.size()) { itemPKResults.addAll(currentInstanceResults.subList(0, n)); } else { itemPKResults.addAll(currentInstanceResults); } criteria.setMaxItems(criteria.getMaxItems() - currentInstanceResults.size()); criteria.setSkip(0); } else { criteria.setSkip(criteria.getSkip() - count); } } } } itemPKResults.add(0, "<totalCount>" + totalCount + "</totalCount>"); //$NON-NLS-1$ //$NON-NLS-2$ } finally { storage.commit(); } return itemPKResults; } @Override protected Storage getStorage(String dataClusterName) { return storageAdmin.get(StorageAdmin.SYSTEM_STORAGE, StorageType.SYSTEM); } @Override public long deleteCluster(String clusterName) throws XmlServerException { return 0; } @Override public String[] getAllClusters() throws XmlServerException { Set<String> internalClusterNames = DispatchWrapper.getInternalClusterNames(); return internalClusterNames.toArray(new String[internalClusterNames.size()]); } @Override public long deleteAllClusters() throws XmlServerException { return 0; } @Override public long createCluster(String clusterName) throws XmlServerException { return 0; } @Override public boolean existCluster(String cluster) throws XmlServerException { return true; } @Override protected Collection<ComplexTypeMetadata> getClusterTypes(String clusterName) { Storage storage = getStorage(clusterName); MetadataRepository repository = storage.getMetadataRepository(); return filter(repository, clusterName); } public static Collection<ComplexTypeMetadata> filter(MetadataRepository repository, String clusterName) { if (clusterName.startsWith(SYSTEM_PREFIX) || clusterName.startsWith("amalto")) { //$NON-NLS-1$ if (!"amaltoOBJECTSservices".equals(clusterName)) { //$NON-NLS-1$ final String className = ClassRepository .format(clusterName.substring(SYSTEM_PREFIX.length()) + "POJO"); //$NON-NLS-1$ return filterRepository(repository, className); } else { final String className = ClassRepository.format(clusterName.substring(SYSTEM_PREFIX.length())); return filterRepository(repository, className); } } else if (XSystemObjects.DC_MDMITEMSTRASH.getName().equals(clusterName)) { return filterRepository(repository, DROPPED_ITEM_TYPE); } else if (XSystemObjects.DC_CONF.getName().equals(clusterName)) { return filterRepository(repository, "Conf", "AutoIncrement"); //$NON-NLS-1$ //$NON-NLS-2$ } else if (XSystemObjects.DC_CROSSREFERENCING.getName().equals(clusterName)) { return Collections.emptyList(); // TODO Support crossreferencing } else if (XSystemObjects.DC_PROVISIONING.getName().equals(clusterName)) { return filterRepository(repository, "User", "Role"); //$NON-NLS-1$ //$NON-NLS-2$ } else if (XSystemObjects.DC_SEARCHTEMPLATE.getName().equals(clusterName)) { return filterRepository(repository, "BrowseItem", "HierarchySearchItem"); //$NON-NLS-1$ //$NON-NLS-2$ } else { return repository.getUserComplexTypes(); } } private static Collection<ComplexTypeMetadata> filterRepository(MetadataRepository repository, String... typeNames) { final Set<ComplexTypeMetadata> filteredTypes = new HashSet<ComplexTypeMetadata>(); MetadataVisitor<Void> transitiveTypeClosure = new DefaultMetadataVisitor<Void>() { private final Set<TypeMetadata> visitedTypes = new HashSet<>(); @Override public Void visit(ComplexTypeMetadata complexType) { if (!visitedTypes.add(complexType)) { return null; } if (complexType.isInstantiable()) { filteredTypes.add(complexType); } return super.visit(complexType); } @Override public Void visit(ContainedComplexTypeMetadata containedType) { if (!visitedTypes.add(containedType)) { return null; } if (containedType.isInstantiable()) { filteredTypes.add(containedType); } return super.visit(containedType); } }; for (String typeName : typeNames) { ComplexTypeMetadata type = repository.getComplexType(typeName); if (type != null) { type.accept(transitiveTypeClosure); } } return filteredTypes; } @Override public String[] getAllDocumentsUniqueID(String clusterName) throws XmlServerException { String pureClusterName = getPureClusterName(clusterName); boolean includeClusterAndTypeName = getClusterTypes(pureClusterName).size() > 1; return getAllDocumentsUniqueID(clusterName, includeClusterAndTypeName); } @Override public long putDocumentFromDOM(Element root, String uniqueID, String clusterName) throws XmlServerException { long start = System.currentTimeMillis(); { DataRecordReader<Element> reader = new XmlDOMDataRecordReader(); Storage storage = getStorage(clusterName); ComplexTypeMetadata type = getType(clusterName, storage, uniqueID); if (type == null) { return -1; // TODO } MetadataRepository repository = storage.getMetadataRepository(); DataRecord record = reader.read(repository, type, root); for (FieldMetadata keyField : type.getKeyFields()) { if (record.get(keyField) == null) { LOGGER.warn( "Ignoring update for record '" + uniqueID + "' (does not provide key information)."); //$NON-NLS-1$ //$NON-NLS-2$ return 0; } } storage.update(record); } return System.currentTimeMillis() - start; } @Override public long putDocumentFromSAX(String dataClusterName, XMLReader docReader, InputSource input) throws XmlServerException { long start = System.currentTimeMillis(); { Storage storage = getStorage(dataClusterName); ComplexTypeMetadata type = getType(dataClusterName, storage, input.getPublicId()); if (type == null) { return -1; // TODO } DataRecordReader<XmlSAXDataRecordReader.Input> reader = new XmlSAXDataRecordReader(); XmlSAXDataRecordReader.Input readerInput = new XmlSAXDataRecordReader.Input(docReader, input); DataRecord record = reader.read(storage.getMetadataRepository(), type, readerInput); storage.update(record); } return System.currentTimeMillis() - start; } @Override public long putDocumentFromString(String xmlString, String uniqueID, String clusterName) throws XmlServerException { return putDocumentFromString(xmlString, uniqueID, clusterName, null); } @Override public long putDocumentFromString(String xmlString, String uniqueID, String clusterName, String documentType) throws XmlServerException { try { InputSource source = new InputSource(new StringReader(xmlString)); Document document = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(source); return putDocumentFromDOM(document.getDocumentElement(), uniqueID, clusterName); } catch (Exception e) { throw new XmlServerException(e); } } @Override public String getDocumentAsString(String clusterName, String uniqueID) throws XmlServerException { return getDocumentAsString(clusterName, uniqueID, "UTF-8"); //$NON-NLS-1$ } @Override public String getDocumentAsString(String clusterName, String uniqueID, String encoding) throws XmlServerException { if (encoding == null) { encoding = "UTF-8"; //$NON-NLS-1$ } Storage storage = getStorage(clusterName); ComplexTypeMetadata type = getType(clusterName, storage, uniqueID); if (type == null) { return null; // TODO } UserQueryBuilder qb; boolean isUserFormat = false; String documentUniqueID; if (DROPPED_ITEM_TYPE.equals(type.getName())) { // head.Product.Product.0- (but DM1.Bird.bid3) if (uniqueID.endsWith("-")) { //$NON-NLS-1$ uniqueID = uniqueID.substring(0, uniqueID.length() - 1); } // TODO Code may not correctly handle composite id (but no system objects use this) documentUniqueID = uniqueID; if (StringUtils.countMatches(uniqueID, ".") >= 3) { //$NON-NLS-1$ documentUniqueID = StringUtils.substringAfter(uniqueID, "."); //$NON-NLS-1$ } } else if (COMPLETED_ROUTING_ORDER.equals(type.getName()) || FAILED_ROUTING_ORDER.equals(type.getName())) { documentUniqueID = uniqueID; } else { // TMDM-5513 custom form layout pk contains double dot .. to split, but it's a system definition object // like this Product..Product..product_layout isUserFormat = !uniqueID.contains("..") && uniqueID.indexOf('.') > 0; //$NON-NLS-1$ documentUniqueID = uniqueID; if (uniqueID.startsWith(PROVISIONING_PREFIX_INFO)) { documentUniqueID = StringUtils.substringAfter(uniqueID, PROVISIONING_PREFIX_INFO); } else if (uniqueID.startsWith(BROWSEITEM_PREFIX_INFO)) { documentUniqueID = StringUtils.substringAfter(uniqueID, BROWSEITEM_PREFIX_INFO); //$NON-NLS-1$ } else if (isUserFormat) { documentUniqueID = StringUtils.substringAfterLast(uniqueID, "."); //$NON-NLS-1$ } } qb = from(type).where(eq(type.getKeyFields().iterator().next(), documentUniqueID)); StorageResults results = null; try { storage.begin(); results = storage.fetch(qb.getSelect()); String xmlString = getXmlString(clusterName, type, results.iterator(), uniqueID, encoding, isUserFormat); storage.commit(); return xmlString; } catch (IOException e) { storage.rollback(); throw new XmlServerException(e); } finally { if (results != null) { results.close(); } } } @Override public long deleteDocument(String clusterName, String uniqueID, String documentType) throws XmlServerException { Storage storage = getStorage(clusterName); ComplexTypeMetadata type = getType(clusterName, storage, uniqueID); if (type == null) { return -1; } if (DROPPED_ITEM_TYPE.equals(type.getName())) { // head.Product.Product.0- uniqueID = uniqueID.substring(0, uniqueID.length() - 1); uniqueID = StringUtils.substringAfter(uniqueID, "."); //$NON-NLS-1$ } else if (!COMPLETED_ROUTING_ORDER.equals(type.getName()) && !FAILED_ROUTING_ORDER.equals(type.getName()) && !CUSTOM_FORM_TYPE.equals(type.getName()) && !SYNCHRONIZATION_OBJECT_TYPE.equals(type.getName())) { if (uniqueID.startsWith(PROVISIONING_PREFIX_INFO)) { uniqueID = StringUtils.substringAfter(uniqueID, PROVISIONING_PREFIX_INFO); } else if (uniqueID.startsWith(BROWSEITEM_PREFIX_INFO)) { uniqueID = StringUtils.substringAfter(uniqueID, BROWSEITEM_PREFIX_INFO); //$NON-NLS-1$ } else if (uniqueID.contains(".")) { //$NON-NLS-1$ uniqueID = StringUtils.substringAfterLast(uniqueID, "."); //$NON-NLS-1$ } } long start = System.currentTimeMillis(); { UserQueryBuilder qb = from(type).where(eq(type.getKeyFields().iterator().next(), uniqueID)); StorageResults results = null; try { storage.begin(); Select select = qb.getSelect(); results = storage.fetch(select); if (results.getCount() == 0) { throw new IllegalArgumentException("Could not find document to delete."); //$NON-NLS-1$ } storage.delete(select); storage.commit(); } catch (Exception e) { storage.rollback(); throw new XmlServerException(e); } finally { if (results != null) { results.close(); } } } return System.currentTimeMillis() - start; } @Override public String[] getDocumentsAsString(String clusterName, String[] uniqueIDs) throws XmlServerException { return getDocumentsAsString(clusterName, uniqueIDs, "UTF-8"); //$NON-NLS-1$ } @Override public String[] getDocumentsAsString(String clusterName, String[] uniqueIDs, String encoding) throws XmlServerException { if (uniqueIDs == null || uniqueIDs.length == 0) { return new String[0]; } List<String> xmlStrings = new ArrayList<String>(uniqueIDs.length); for (String uniqueID : uniqueIDs) { xmlStrings.add(getDocumentAsString(clusterName, uniqueID, encoding)); } return xmlStrings.toArray(new String[xmlStrings.size()]); } }