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

com.marvelution.jira.plugins.sonar.services.layout.SonarPanelLayoutManagerService Maven / Gradle / Ivy

/*
 * Licensed to Marvelution under one or more contributor license 
 * agreements.  See the NOTICE file distributed with this work 
 * for additional information regarding copyright ownership.
 * Marvelution licenses this file to you 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 com.marvelution.jira.plugins.sonar.services.layout;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.IOException;
import java.util.Properties;

import com.atlassian.sal.api.transaction.TransactionCallback;
import net.java.ao.DBParam;
import net.java.ao.Query;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.marvelution.jira.plugins.sonar.services.layout.Layout.Context;
import com.marvelution.jira.plugins.sonar.services.layout.Layout.Type;
import com.marvelution.jira.plugins.sonar.upgrade.activeobjects.SonarGadgetsActiveObjectsValidator;

/**
 * Default {@link SonarPanelLayoutManager} implementation
 *
 * @author Mark Rekveld
 */
public class SonarPanelLayoutManagerService implements SonarPanelLayoutManager {

	private static final Logger LOGGER = Logger.getLogger(SonarPanelLayoutManagerService.class);
	private static final Properties LAYOUT_DEFAULT = new Properties();

	private final ActiveObjects objects;
	private final SonarGadgetsActiveObjectsValidator gadgetsValidator;
	private boolean initialCheck = true;

	/**
	 * Constructor
	 *
	 * @param objects the {@link ActiveObjects} implementation
	 */
	public SonarPanelLayoutManagerService(ActiveObjects objects, SonarGadgetsActiveObjectsValidator gadgetsValidator) {
		this.objects = checkNotNull(objects, "activeObjects");
		this.gadgetsValidator = checkNotNull(gadgetsValidator, "gadgetsValidator");
	}

	@Override
	public Gadget[] getGadgets() {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Gadget[] doInTransaction() {
				if (initialCheck) {
					gadgetsValidator.upgrade(null, objects);
					initialCheck = false;
				}
				return objects.find(Gadget.class);
			}
		});
	}

	@Override
	public Gadget getGadget(final String shortName) {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Gadget doInTransaction() {
				Gadget[] gadgets = objects.find(Gadget.class, Query.select().where("SHORT_NAME = ?",
						shortName).limit(1));
				if (gadgets != null && gadgets.length == 1) {
					return gadgets[0];
				}
				return null;
			}
		});
	}

	@Override
	public boolean addGadgetToColumn(Gadget gadget, Integer columnId) {
		return addGadgetToColumn(gadget, columnId, -1);
	}

	@Override
	public boolean addGadgetToColumn(Gadget gadget, final Integer columnId, int position) {
		Column column = objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Column doInTransaction() {
				return objects.get(Column.class, columnId);
			}
		});
		return addGadgetToColumn(gadget, column, position);
	}

	@Override
	public boolean addGadgetToColumn(Gadget gadget, Column column) {
		return addGadgetToColumn(gadget, column, -1);
	}

	@Override
	public boolean addGadgetToColumn(final Gadget gadget, final Column column, final int position) {
		checkNotNull(gadget, "Gadget may not be null");
		checkNotNull(column, "Column may not be null");
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Boolean doInTransaction() {
				if (position == -1) {
					ColumnToGadget relation = objects.create(ColumnToGadget.class, new DBParam("COLUMN_ID",
							column.getID()), new DBParam("GADGET_ID", gadget.getID()));
					relation.save();
				} else {
					ColumnToGadget[] relations = objects.find(ColumnToGadget.class,
							Query.select().where("COLUMN_ID = ?", column.getID()));
					// Create the new relation
					ColumnToGadget relation = objects.create(ColumnToGadget.class, new DBParam("COLUMN_ID",
							column.getID()), new DBParam("GADGET_ID", gadget.getID()));
					relation.save();
					if (relations != null && relations.length >= position) {
						for (int index = position; index < relations.length; index++) {
							ColumnToGadget recreate = relations[index];
							ColumnToGadget recreation = objects.create(ColumnToGadget.class,
									new DBParam("COLUMN_ID", column.getID()),
									new DBParam("GADGET_ID", recreate.getGadget().getID()));
							recreation.save();
							objects.delete(recreate);
						}
					}
				}
				return true;
			}
		});
	}

	@Override
	public boolean removeGadgetFromColumn(final Gadget gadget, final Integer columnId) {
		checkNotNull(gadget, "Gadget may not be null");
		checkNotNull(columnId, "ColumnId may not be null");
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Boolean doInTransaction() {
				objects.delete(objects.find(ColumnToGadget.class,
						Query.select().where("COLUMN_ID = ? AND GADGET_ID = ?", columnId, gadget.getID())));
				return true;
			}
		});
	}

	@Override
	public boolean removeGadgetFromColumn(Gadget gadget, Column column) {
		return removeGadgetFromColumn(gadget, column.getID());
	}

	@Override
	public boolean removeAllGadgetsFromColumn(final Column column) {
		checkNotNull(column, "Column may not be null");
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Boolean doInTransaction() {
				objects.delete(objects.find(ColumnToGadget.class, Query.select().where("COLUMN_ID = ?",
						column.getID())));
				return true;
			}
		});
	}

	@Override
	public Layout createLayout(final Layout.Type type, final Long contextID) {
		Layout layout = getLayout(contextID);
		if (layout == null) {
			return objects.executeInTransaction(new TransactionCallback() {
				@Override
				public Layout doInTransaction() {
					return createLayout(type, Layout.Context.PROJECT, contextID);
				}
			});
		} else {
			return changeLayoutType(layout, type);
		}
	}

	@Override
	public Layout changeLayoutType(final Layout layout, final Type newType) {
		if (!layout.getType().equals(newType)) {
			return objects.executeInTransaction(new TransactionCallback() {
				@Override
				public Layout doInTransaction() {
					checkNotNull(layout, "layout cannot be null");
					checkNotNull(newType, "newType cannot be null");
					LOGGER.debug("Updating Layout " + layout.getID() + " to type " + newType);
					Column[] columns = layout.getColumns();
					int index = 0;
					while (index < columns.length) {
						LOGGER.debug("Checking column " + columns[index].getID());
						if (index < newType.columns.length) {
							LOGGER.debug("Updating cloumn " + columns[index].getID() + " to type " + newType
									.columns[index]);
							Column column = columns[index];
							column.setType(newType.columns[index]);
							column.save();
						} else {
							LOGGER.debug("Deleting unneeded column " + columns[index]);
							deleteColumn(columns[index]);
						}
						index++;
					}
					// Loop through all the columns to make sure they are there
					while (index < newType.columns.length) {
						LOGGER.debug("Creating missing column of type " + newType.columns[index]);
						createColumn(layout, newType.columns[index]);
						index++;
					}
					layout.setType(newType);
					layout.save();
					return layout;
				}
			});
		}
		return layout;
	}

	@Override
	public boolean removeLayout(final Layout layout) {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Boolean doInTransaction() {
				checkNotNull(layout, "layout cannot be null");
				if (layout.getContext().equals(Layout.Context.SYSTEM)) {
					throw new IllegalStateException("The SYSTEM layout cannot be deleted!");
				}
				LOGGER.debug("Deleting Layout " + layout.getID() + " for context " + layout.getContext() + " "
						+ layout.getContextID());
				for (Column column : layout.getColumns()) {
					deleteColumn(column);
				}
				objects.delete(layout);
				return true;
			}
		});
	}

	@Override
	public Layout getSystemLayout() {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Layout doInTransaction() {
				Layout[] layouts = objects.find(Layout.class, Query.select().where("CONTEXT = ?",
						Layout.Context.SYSTEM));
				if (layouts.length == 0) {
					LOGGER.debug("Missing the Layout for Context SYSTEM, creating a new Layout for the Context.");
					return createLayout(Layout.Type.AA, Layout.Context.SYSTEM, -1L);
				} else if (layouts.length > 1) {
					LOGGER.warn("Multiple Layouts found for Context SYSTEM, this is not supported."
							+ " Deleting all except the first.");
					for (int index = 1; index < layouts.length; index++) {
						objects.delete(layouts[index]);
					}
					return layouts[0];
				} else {
					return layouts[0];
				}
			}
		});
	}

	@Override
	public Layout getLayout(final Long contextID) {
		final Layout[] layouts = objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Layout[] doInTransaction() {
				return objects.find(Layout.class,
						Query.select().where("CONTEXT = ? AND CONTEXT_ID = ?", Layout.Context.PROJECT,
								contextID).limit(1));
			}
		});
		if (layouts != null && layouts.length == 1) {
			return layouts[0];
		}
		return getSystemLayout();
	}

	@Override
	public Layout getLayout(final Context context) {
		if (Context.SYSTEM.equals(context)) {
			return getSystemLayout();
		} else if (Context.PROJECT.equals(context)) {
			throw new IllegalArgumentException("Cannot get a PROJECT Context Layout without the project Id");
		} else {
			return objects.executeInTransaction(new TransactionCallback() {
				@Override
				public Layout doInTransaction() {
					Layout[] layouts = objects.find(Layout.class, Query.select().where("CONTEXT = ?", context));
					if (layouts != null && layouts.length == 1) {
						return layouts[0];
					} else {
						LOGGER.debug("Missing the Layout for Context " + context + ", creating a new Layout for the " +
								"Context.");
						return createLayout(Layout.Type.AA, context, -1L);
					}
				}
			});
		}
	}

	@Override
	public Layout getLayoutById(final int layoutID) {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Layout doInTransaction() {
				return objects.get(Layout.class, layoutID);
			}
		});
	}

	@Override
	public Layout getLayoutByColumnId(final int columnID) {
		Column column = objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Column doInTransaction() {
				return objects.get(Column.class, columnID);
			}
		});
		if (column != null) {
			return column.getLayout();
		}
		return null;
	}

	@Override
	public Layout[] getLayouts() {
		return objects.executeInTransaction(new TransactionCallback() {
			@Override
			public Layout[] doInTransaction() {
				return objects.find(Layout.class);
			}
		});
	}

	/**
	 * Internal method create a new {@link Layout}
	 *
	 * @param type      the {@link Layout.Type}
	 * @param context   the {@link Layout.Context}
	 * @param contextID the Contextual ID, may be null if the {@link Layout.Context} supports it
	 * @return the {@link Layout}
	 */
	private Layout createLayout(Layout.Type type, Layout.Context context, Long contextID) {
		LOGGER.debug("Creating a new Layout of Type '" + type + "' and Context '" + context + "'");
		Layout layout = objects.create(Layout.class, new DBParam("TYPE", type), new DBParam("CONTEXT", context));
		if (contextID > -1) {
			layout.setContextID(contextID);
		}
		layout.save();
		for (int index = 0; index < type.columns.length; index++) {
			Column column = createColumn(layout, type.columns[index]);
			if (StringUtils.isNotBlank(LAYOUT_DEFAULT.getProperty(context.name() + ".column." + index))) {
				for (String shortname : LAYOUT_DEFAULT.getProperty(context.name() + ".column." + index).split(",")) {
					LOGGER.debug("Adding default gadget '" + shortname + "' to the " + context + " column " + index);
					addGadgetToColumn(getGadget(shortname), column);
				}
			}
		}
		return layout;
	}

	/**
	 * Internal method to create a {@link Column}
	 *
	 * @param layout the {@link Layout} to link the column to
	 * @param type   the {@link Column.Type}
	 * @return the {@link Column}
	 */
	private Column createColumn(Layout layout, Column.Type type) {
		LOGGER.debug("Creating a new Column of Type '" + type + "' for Layout with ID " + layout.getID());
		Column column = objects.create(Column.class, new DBParam("LAYOUT_ID", layout.getID()), new DBParam("TYPE", type));
		column.save();
		LOGGER.debug("Created column with ID " + column.getID());
		return column;
	}

	/**
	 * Internal method to delete a {@link Column} and all associated Gadgets
	 *
	 * @param column the {@link Column} to delete
	 */
	private void deleteColumn(Column column) {
		LOGGER.debug("Deleting unneeded column with ID: " + column.getID());
		objects.delete(objects.find(ColumnToGadget.class, Query.select().where("COLUMN_ID = ?", column.getID())));
		objects.delete(column);
	}

	static {
		try {
			LAYOUT_DEFAULT.load(SonarPanelLayoutManagerService.class.getResourceAsStream("layout-default.properties"));
		} catch (IOException e) {
			LOGGER.error("Failed to laod the layout-default.properties", e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy